<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4663432300421783651</id><updated>2012-01-24T22:42:31.641-08:00</updated><category term='ruby'/><category term='sslv3'/><category term='CRLF'/><category term='cipher'/><category term='decode'/><category term='passwords'/><category term='rbkb'/><category term='CAPTCHA'/><category term='openssl'/><category term='enumeration'/><category term='break'/><category term='hacking'/><category term='cookie'/><category term='new tool'/><category term='TesserCap'/><category term='rootkit.com'/><category term='bigip'/><category term='sslv2'/><category term='SSLSmart'/><category term='Content Security Policy'/><category term='entropy'/><category term='ocr'/><category term='JTR'/><category term='password analysis'/><category term='XSS'/><category term='web application security'/><category term='tesseract'/><category term='tlsv1'/><category term='CSP'/><title type='text'>Random Security</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://gursevkalra.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4663432300421783651/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://gursevkalra.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Gursev Kalra</name><uri>http://www.blogger.com/profile/11125392470187170013</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4663432300421783651.post-3593296193108849254</id><published>2011-12-18T10:48:00.000-08:00</published><updated>2011-12-18T10:48:32.947-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='cookie'/><category scheme='http://www.blogger.com/atom/ns#' term='decode'/><category scheme='http://www.blogger.com/atom/ns#' term='bigip'/><title type='text'>Decoding BigIP Cookie</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;BigIP cookie contains internal network IP and port information in encoded format. When decoded, these cookies can help create an internal network map with potential web server IPs and their ports. &lt;br /&gt;&lt;br /&gt;F5 has described the encoding algorithm &lt;a href="http://support.f5.com/kb/en-us/products/big-ip_ltm/manuals/product/ltm_configuration_guide_10_0_0/ltm_persist_profiles.html"&gt;here&lt;/a&gt;. It works like this:&lt;br /&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;If the IP address is a.b.c.d, it is encoded as d*256^3 + c*256^2 + b*256 +a&lt;/li&gt;&lt;li&gt;To encode the port is to take the two bytes that store the port and reverse them. Thus, port 80 becomes 80 * 256 + 0 = 20480. Port 1433 (instead of 5 * 256 + 153) becomes 153 * 256 + 5 = 39173.&lt;/li&gt;&lt;li&gt;These values are combined into cookie as&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt; &amp;lt;Encoded IP Address&amp;gt;.&amp;lt;Encoded Port Address&amp;gt;.&amp;lt;Componenet we are not concerned about&amp;gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;These decoding mechanisms are packed into the following ruby script:&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre style="background: #dddddd; border: 1px dashed #CCCCCC; color: white; color: white; font-family: arial; font-size: 12px; height: auto; overflow: auto; padding: 0px; text-align: left; width: 99%;"&gt;&lt;code style="color: black; word-wrap: normal;"&gt;#!/usr/bin/ruby&lt;br /&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;#Cookie: BIGipcookie =&amp;gt; 404007104.20480.0000&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;#Cookie: BIGipcookie =&amp;gt; 404007104.39173.0000&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;if (ARGV.length == 0)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; $stderr.puts "No input provided. Run as \n\tbigip.rb BigIP Cookie Value"&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; exit&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;end&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ips = ARGV[0].split(".")&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;encoded_val = ips[0].to_i&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;port_val = ips[1].to_i&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ip = []&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;port = []&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;4.times do&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; ip &amp;lt;&amp;lt; encoded_val%256&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; encoded_val /= 256&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;end&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;2.times do&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; port &amp;lt;&amp;lt; port_val%256&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; port_val /= 256&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;end&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;puts "IP Address : #{ip.join(".")}"&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;puts "Port &amp;nbsp; &amp;nbsp; &amp;nbsp; : #{port[0]*256 + port[1]}"&lt;/span&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-TipdCyvCnDs/Tu1f9FlpxII/AAAAAAAAAwA/aTOu-kRwNpg/s1600/bigip.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="112" src="http://2.bp.blogspot.com/-TipdCyvCnDs/Tu1f9FlpxII/AAAAAAAAAwA/aTOu-kRwNpg/s320/bigip.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;A Sample bigip.rb run&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4663432300421783651-3593296193108849254?l=gursevkalra.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gursevkalra.blogspot.com/feeds/3593296193108849254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4663432300421783651&amp;postID=3593296193108849254' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4663432300421783651/posts/default/3593296193108849254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4663432300421783651/posts/default/3593296193108849254'/><link rel='alternate' type='text/html' href='http://gursevkalra.blogspot.com/2011/12/decoding-bigip-cookie.html' title='Decoding BigIP Cookie'/><author><name>Gursev Kalra</name><uri>http://www.blogger.com/profile/11125392470187170013</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-TipdCyvCnDs/Tu1f9FlpxII/AAAAAAAAAwA/aTOu-kRwNpg/s72-c/bigip.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4663432300421783651.post-326863930134524375</id><published>2011-11-28T09:41:00.000-08:00</published><updated>2011-12-06T09:07:09.545-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CRLF'/><category scheme='http://www.blogger.com/atom/ns#' term='Content Security Policy'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='CSP'/><title type='text'>Evading Content Security Policy With CRLF Injection</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Content Security Policy (&lt;a href="https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html"&gt;CSP&lt;/a&gt;) was developed with the aim of reducing content injection attacks like Cross Site Scripting. CSP allows the developers to specify the permitted content sources for their web applications and relies on HTTP response headers to enforce content restrictions.&lt;br /&gt;&lt;br /&gt;When CSP is implemented by the web application and supported by the web browser, content injection attacks can be performed by:&lt;br /&gt;&lt;br /&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Exploiting flaws in browser CSP implementation&lt;/li&gt;&lt;li&gt;Manipulating HTTP response headers.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;a href="https://www.owasp.org/index.php/CRLF_Injection"&gt;CRLF&lt;/a&gt; injection is one possible technique by which an attacker can control HTTP response headers. If client provided parameters are returned in response headers without any validation, CRLF injection can be used to bypass CSP restrictions. &lt;br /&gt;&lt;br /&gt;For demonstrations, two web pages were setup with the following content at two different origins&lt;br /&gt;&lt;b&gt;Webpage 1:&lt;/b&gt; http://localhost:3000/csp&lt;br /&gt;&lt;b&gt;Content:&lt;/b&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;http://localhost:3333/xss.js&lt;/span&gt;&lt;br /&gt;&lt;script src="http://localhost:3333/xss.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;b&gt;Webpage 2:&lt;/b&gt; http://localhost:3333/xss.js &lt;br /&gt;&lt;b&gt;Content:&lt;/b&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;alert('XSS’)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;CRLF Injection and CSP:&lt;/b&gt;&lt;br /&gt;If a HTTP response contains same HTTP header multiple times, different browsers interpret the headers &amp;nbsp;differently. Certain browsers interpret the first occurrence of the HTTP header, others choose the last one. Hence, positioning of CSP directive (X-Content-Security-Policy) in application response can play an interesting role. In the discussion below, we assume that the web application implements CSP and is vulnerable to CRLF injection:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Case 1:&lt;/b&gt; &lt;b&gt;&lt;i&gt;Attack vector is returned before the CSP header in the HTTP response headers: &lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Case 1a:&lt;/b&gt; If the browser picks the first occurrence of the CSP header, CRLF injection can then be used to insert a CSP header with following attack vector:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;lang=en_US%0d%0aX-Content-Security-Policy: allow *&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In this case, the web browser will interpret the first CSP header and will happily retrieve content from any malicious URL.&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-xmUltf8RPmM/TtPEwSiGgHI/AAAAAAAAAvU/_lvJdZhShHo/s1600/csp--1st.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="204" src="http://1.bp.blogspot.com/-xmUltf8RPmM/TtPEwSiGgHI/AAAAAAAAAvU/_lvJdZhShHo/s400/csp--1st.png" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;span style="font-family: &amp;quot;Calibri&amp;quot;, sans-serif; font-size: 11pt; line-height: 115%;"&gt;Image shows malicious CSP directive inserted before the legitimate header&amp;nbsp;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;b&gt;Case 1b:&lt;/b&gt; If the browser picks the last occurrence of the CSP header, following CRLF injection attack vector can be used to insert custom CSP header.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;lang=en_US%0d%0aX-Content-Security-Policy: allow *%0d%0a%0d%0a &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Two trailing occurrences of CRLF will push the CSP directive into the content and will not be interpreted as a CSP directive. This again allows attacker to bypass CSP protection and execute and source arbitrary content.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-aHGA8U0XLHs/TtPE6e7MAUI/AAAAAAAAAvg/wJ4zWeCy9nE/s1600/x--content--pushed--out.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="260" src="http://3.bp.blogspot.com/-aHGA8U0XLHs/TtPE6e7MAUI/AAAAAAAAAvg/wJ4zWeCy9nE/s400/x--content--pushed--out.png" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;span style="font-family: &amp;quot;Calibri&amp;quot;, sans-serif; font-size: 11pt; line-height: 115%;"&gt;Image shows CSP directive pushed out to response body and rendered ineffective&amp;nbsp;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;b&gt;Case 2: &lt;i&gt;Attack vector is returned after the CSP header in the HTTP response headers &lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Case 2a:&lt;/b&gt; If the browser picks the first occurrence of the CSP header, the CSP directive cannot be overridden for the current resource. For an attack to function one has to look into the possibility of exploiting HTTP Response Splitting.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Case 2b:&lt;/b&gt; If the browser picks the last occurrence of the CSP header, CRLF injection can be used to insert a malicious header similar to case 1a.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;lang=en_US%0d%0aX-Content-Security-Policy: allow * &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This will cause the browser to interpret the CSP directive as allow * to retrieve content from arbitrary URLs.&lt;br /&gt;&lt;br /&gt;It was observed that when more than one X-Content-Security-Policy headers were received by Firefox (7.0.1), it securely defaulted to same origin policy for all content. &lt;br /&gt;&lt;br /&gt;The POC below pushes the headers out to the response body by two CRLF sequences to achieve script execution.&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-XQtrMTPwOzM/TtPFIq9PGaI/AAAAAAAAAvs/hnX6p-lk0KU/s1600/no--xss--csp.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="313" src="http://3.bp.blogspot.com/-XQtrMTPwOzM/TtPFIq9PGaI/AAAAAAAAAvs/hnX6p-lk0KU/s400/no--xss--csp.png" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;span style="font-family: &amp;quot;Calibri&amp;quot;, sans-serif; font-size: 11pt; line-height: 115%;"&gt;Image shows script execution prevented from a different origin (http://localhost:3333)&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-X8QsHTeJsLk/TtPFZXqDk3I/AAAAAAAAAv4/yJPe6GEHoRw/s1600/xss--successful--2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="160" src="http://2.bp.blogspot.com/-X8QsHTeJsLk/TtPFZXqDk3I/AAAAAAAAAv4/yJPe6GEHoRw/s400/xss--successful--2.png" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;span style="font-family: &amp;quot;Calibri&amp;quot;, sans-serif; font-size: 11pt; line-height: 115%;"&gt;Image shows successful script execution when the page was vulnerable CRLF injection&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4663432300421783651-326863930134524375?l=gursevkalra.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gursevkalra.blogspot.com/feeds/326863930134524375/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4663432300421783651&amp;postID=326863930134524375' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4663432300421783651/posts/default/326863930134524375'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4663432300421783651/posts/default/326863930134524375'/><link rel='alternate' type='text/html' href='http://gursevkalra.blogspot.com/2011/11/evading-content-security-policy-with.html' title='Evading Content Security Policy With CRLF Injection'/><author><name>Gursev Kalra</name><uri>http://www.blogger.com/profile/11125392470187170013</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-xmUltf8RPmM/TtPEwSiGgHI/AAAAAAAAAvU/_lvJdZhShHo/s72-c/csp--1st.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4663432300421783651.post-3199082845508900774</id><published>2011-11-17T06:57:00.000-08:00</published><updated>2011-12-02T18:26:55.272-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='new tool'/><category scheme='http://www.blogger.com/atom/ns#' term='CAPTCHA'/><category scheme='http://www.blogger.com/atom/ns#' term='TesserCap'/><category scheme='http://www.blogger.com/atom/ns#' term='hacking'/><category scheme='http://www.blogger.com/atom/ns#' term='web application security'/><title type='text'>CAPTCHA Hax With TesserCap</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;With the goal of creating a tool that can help security professionals and developers to test their CAPTCHA schemes, I conducted a research on over 200 high traffic websites and several CAPTCHA service providers listed on &lt;a href="http://www.quantcast.com/top-sites-1"&gt;Quantcast’s Top 1 Million Ranking Websites&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;During the same time frame, students at the Stanford University also conducted a similar &lt;a href="http://cdn.ly.tl/publications/text-based-captcha-strengths-and-weaknesses.pdf"&gt;research (PDF)&lt;/a&gt;. Both research works concluded the obvious:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;An alarming number of CAPTCHAs schemes are vulnerable to automated attacks.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I looked around, tested and zeroed in on Tesseract-OCR as my OCR engine. To remove color complexities, spatial irregularities, and other types of random noise from CAPTCHAs, I decided to write my own image preprocessing engine. After a few months of research, coding and testing in my spare time, TesserCap was born and is ready for release now. &lt;br /&gt;&lt;br /&gt;TesserCap is a GUI based, point and shoot CAPTCHA analysis tool with the following features: &lt;br /&gt;&lt;ol&gt;&lt;li&gt;A generic image preprocessing engine that can be configured as per the CAPTCHA type being analyzed. &lt;/li&gt;&lt;li&gt;Tesseract-OCR as its OCR engine to retrieve text from preprocessed CAPTCHAs. &lt;/li&gt;&lt;li&gt;Web proxy support&lt;/li&gt;&lt;li&gt;Support for custom HTTP headers to retrieve CAPTCHAs from websites that require cookies or special HTTP headers in requests&lt;/li&gt;&lt;li&gt;CAPTCHA statistical analysis support&lt;/li&gt;&lt;li&gt;Character set selection for the OCR Engine&lt;/li&gt;&lt;/ol&gt;An example TesserCap image preprocessing and run on Wikipedia (Wikimedia’s Fancy CAPTCHA) is shown below:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-09Sh94704BA/TsF2lhFJ-eI/AAAAAAAAAFM/ZTu3N6cW_90/s1600/p1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="238" src="http://3.bp.blogspot.com/-09Sh94704BA/TsF2lhFJ-eI/AAAAAAAAAFM/ZTu3N6cW_90/s320/p1.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Downloads&lt;/h1&gt;TesserCap and it's user manual can be downloaded from one of the following locations:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.opensecurityresearch.com/files/tessercap.zip"&gt;http://www.opensecurityresearch.com/files/tessercap.zip&lt;/a&gt; -- No password protection on this zip file&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.mcafee.com/us/downloads/free-tools/tessercap.aspx"&gt;http://www.mcafee.com/us/downloads/free-tools/tessercap.aspx&lt;/a&gt; -- Use password as "foundstone" without quotes to extract this zip file.&lt;/li&gt;&lt;/ul&gt;&lt;h1&gt;Results&lt;/h1&gt;The two tables below summarize the CAPTCHA analysis performed using TesserCap for few popular websites and some CAPTCHA service providers.  All these tests were performed using TesserCap’s image preprocessing module and Tesseract-OCR’s default training data.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;  &lt;td&gt;&lt;b&gt;Website&lt;/b&gt;&lt;/td&gt;  &lt;td&gt;&lt;b&gt;Accuracy*&lt;/b&gt;&lt;/td&gt;  &lt;td&gt;&lt;b&gt;Quantcast Rank&lt;/b&gt;&lt;/td&gt;  &lt;/tr&gt;&lt;tr&gt;   &lt;td&gt;wikipedia&lt;/td&gt;   &lt;td&gt;20-30%&lt;/td&gt;   &lt;td&gt;7&lt;/td&gt;  &lt;/tr&gt;&lt;tr&gt;   &lt;td&gt;ebay&lt;/td&gt;   &lt;td&gt;20-30%&lt;/td&gt;   &lt;td&gt;11&lt;/td&gt;  &lt;/tr&gt;&lt;tr&gt;   &lt;td&gt;reddit.com&lt;/td&gt;   &lt;td&gt;20-30%&lt;/td&gt;   &lt;td&gt;68&lt;/td&gt;  &lt;/tr&gt;&lt;tr&gt;   &lt;td&gt;CNBC&lt;/td&gt;   &lt;td&gt;50+%&lt;/td&gt;   &lt;td&gt;121&lt;/td&gt;  &lt;/tr&gt;&lt;tr&gt;   &lt;td&gt;foodnetwork.com&lt;/td&gt;   &lt;td&gt;80-90%&lt;/td&gt;   &lt;td&gt;160&lt;/td&gt;  &lt;/tr&gt;&lt;tr&gt;   &lt;td&gt;dailymail.co.uk&lt;/td&gt;   &lt;td&gt;30+%&lt;/td&gt;   &lt;td&gt;245&lt;/td&gt;  &lt;/tr&gt;&lt;tr&gt;   &lt;td&gt;megaupload.com &lt;/td&gt;   &lt;td&gt;80+%&lt;/td&gt;   &lt;td&gt;1000&lt;/td&gt;  &lt;/tr&gt;&lt;tr&gt;   &lt;td&gt;pastebin.com&lt;/td&gt;   &lt;td&gt;70-80%&lt;/td&gt;   &lt;td&gt;32,534&lt;/td&gt;  &lt;/tr&gt;&lt;tr&gt;   &lt;td&gt;cavenue.com&lt;/td&gt;   &lt;td&gt;80+%&lt;/td&gt;   &lt;td&gt;149,645&lt;/td&gt;  &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;   &lt;td&gt;&lt;b&gt;CAPTCHA Provider&lt;/b&gt;&lt;/td&gt;   &lt;td&gt;&lt;b&gt;Accuracy*&lt;/b&gt;&lt;/td&gt;  &lt;/tr&gt;&lt;tr&gt;   &lt;td&gt;captchas.net&lt;/td&gt;   &lt;td&gt;40-50%&lt;/td&gt;  &lt;/tr&gt;&lt;tr&gt;   &lt;td&gt;opencaptcha.com&lt;/td&gt;   &lt;td&gt;20-30%&lt;/td&gt;  &lt;/tr&gt;&lt;tr&gt;   &lt;td&gt;snaphost.com&lt;/td&gt;   &lt;td&gt;60+%&lt;/td&gt;  &lt;/tr&gt;&lt;tr&gt;   &lt;td&gt;captchacreator.com&lt;/td&gt;   &lt;td&gt;10-20%&lt;/td&gt;  &lt;/tr&gt;&lt;tr&gt;   &lt;td&gt;www.phpcaptcha.org&lt;/td&gt;   &lt;td&gt;10-20%&lt;/td&gt;  &lt;/tr&gt;&lt;tr&gt;   &lt;td&gt;webspamprotect.com&lt;/td&gt;   &lt;td&gt;40+%&lt;/td&gt;  &lt;/tr&gt;&lt;tr&gt;   &lt;td&gt;ReCaptcha&lt;/td&gt;   &lt;td&gt;0%&lt;/td&gt;  &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;*This accuracy maybe further increased by training the Tesseract-OCR engine for the CAPTCHAs under test.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Wikipedia&lt;/span&gt;&lt;/h2&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-v7K1GY8qCyM/TsF2uwV39bI/AAAAAAAAAFY/1TNhBjGAmHw/s1600/p2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="239" src="http://2.bp.blogspot.com/-v7K1GY8qCyM/TsF2uwV39bI/AAAAAAAAAFY/1TNhBjGAmHw/s320/p2.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;OpenCaptcha Preprocessing&lt;/span&gt;&lt;/h2&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-GXZ_j5DswGs/TsF2vJwJcqI/AAAAAAAAAFk/bA5WfBuZvzI/s1600/p3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="242" src="http://1.bp.blogspot.com/-GXZ_j5DswGs/TsF2vJwJcqI/AAAAAAAAAFk/bA5WfBuZvzI/s320/p3.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;OpenCaptcha Sample Run&lt;/span&gt;&lt;/h2&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-L_69pn2mBLU/TsF2vnqVNDI/AAAAAAAAAFw/y_oQfb2cGVA/s1600/p4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://3.bp.blogspot.com/-L_69pn2mBLU/TsF2vnqVNDI/AAAAAAAAAFw/y_oQfb2cGVA/s320/p4.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Reddit&lt;/span&gt;&lt;/h2&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-e1JeJiHvspw/TsF2v3xRRBI/AAAAAAAAAF4/weuT6mJnV5E/s1600/p5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="238" src="http://4.bp.blogspot.com/-e1JeJiHvspw/TsF2v3xRRBI/AAAAAAAAAF4/weuT6mJnV5E/s320/p5.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;eBay&lt;/span&gt;&lt;/h2&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-ks1fQNNXFLY/TsF2wDxSklI/AAAAAAAAAGI/z4bZ1O_SDYE/s1600/p6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/-ks1fQNNXFLY/TsF2wDxSklI/AAAAAAAAAGI/z4bZ1O_SDYE/s320/p6.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4663432300421783651-3199082845508900774?l=gursevkalra.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gursevkalra.blogspot.com/feeds/3199082845508900774/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4663432300421783651&amp;postID=3199082845508900774' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4663432300421783651/posts/default/3199082845508900774'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4663432300421783651/posts/default/3199082845508900774'/><link rel='alternate' type='text/html' href='http://gursevkalra.blogspot.com/2011/11/captcha-hax-with-tessercap.html' title='CAPTCHA Hax With TesserCap'/><author><name>Gursev Kalra</name><uri>http://www.blogger.com/profile/11125392470187170013</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-09Sh94704BA/TsF2lhFJ-eI/AAAAAAAAAFM/ZTu3N6cW_90/s72-c/p1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4663432300421783651.post-7297070183775079569</id><published>2011-06-17T00:00:00.000-07:00</published><updated>2011-06-17T00:00:21.835-07:00</updated><title type='text'>Intercepting Blackberry Application Traffic</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;br /&gt;Intercepting mobile traffic is one of the key areas of mobile application penetration testing and Blackberry mobile applicatiosn are no different. In this post, we will look at methods of intercepting blackberry application traffic.&lt;br /&gt;&lt;br /&gt;It is important to note that the standalone blackberry simulator does not offer any mechanism to route HTTP traffic over a web proxy. To use a web proxy for traffic interception, one has to use blackberry device simulator + MDS and email simulator. Assuming you have both installed, following steps will allow you to intercept blackberry web traffic.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Case 1: Routing HTTP traffic via web proxy:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Browse to "\Program Files\Research In Motion\BlackBerry Email and MDS Services Simulators #.#.#\MDS\config"&lt;/li&gt;&lt;li&gt;Open the rimpublic.property file&lt;/li&gt;&lt;li&gt;Under the HTTP HANDLER section, add your web proxy configuration information:&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;application.handler.http.proxyEnabled=true&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;application.handler.http.proxyHost=&amp;lt;your proxy address&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;application.handler.http.proxyPort=&amp;lt;your proxy port&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;The following image shows the rimpublic.property file HTTP HANDLER section for fiddler running on port 8888 on localhost.&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-3M831QG-kRs/Tfr3I-hTmgI/AAAAAAAAAvA/qYNzxHfKa_4/s1600/config--file.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-3M831QG-kRs/Tfr3I-hTmgI/AAAAAAAAAvA/qYNzxHfKa_4/s1600/config--file.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Web Proxy Configuration&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;More details on proxy configuration can be seen &lt;a href="http://www.blackberry.com/knowledgecenterpublic/livelink.exe/fetch/2000/348583/800738/800792/801079/How_To_-_Configure_the_BlackBerry_MDS_simulator_to_work_behind_a_proxy.html?nodeid=800740&amp;amp;vernum=0"&gt;here&lt;/a&gt;. Once you save these settings and launch MDS simulator, you will be able to monitor, intercept and modify all HTTP traffic. However, we still need to put in some extra work for SSL traffic.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-63dtM98q6_I/Tfr5kAaZnCI/AAAAAAAAAvE/FBuQa0EOn4c/s1600/google--via--proxy.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="222" src="http://3.bp.blogspot.com/-63dtM98q6_I/Tfr5kAaZnCI/AAAAAAAAAvE/FBuQa0EOn4c/s640/google--via--proxy.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Image shows HTTP traffic captured for google.com&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Case 2: Routing HTTPS traffic via web proxy:&lt;/b&gt;&lt;br /&gt;The above mentioned configuration was not successful when attempted on SSL traffic. It was time for some workaround and I thought of using a reverse proxy. The idea of using reverse proxy had some limitations but it worked seamlessly and allowed me to intercept SSL traffic for a particular domain. To demonstrate this concept, I will be using Charles Proxy's Reverse Proxy. You can use any reverse proxy of your own choice. Lets configure the Charles proxy now.&lt;br /&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Obtain the IP address to which the application/browser talks&lt;/li&gt;&lt;li&gt;Obtain the IP for the target domain. nslookup for mail.google.com revealed four DNS entries(74.125.226.184, 74.125.226.182, 74.125.226.181, 74.125.226.183) and one of them was chosen to be destination for reverse proxy settings. See the screenshots below for Charles Reverse Proxy settings.&lt;/li&gt;&lt;li&gt;In the hosts file make an entry to forward all the target domain address to the IP at which reverse proxy is hosted. In our case, I entered the following for mail.google.com&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;127.0.0.1&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;mail.google.com&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Now launch your browser and access https://mail.google.com&lt;/li&gt;&lt;li&gt;The blackberry simulator will issue a certificate error. Choose the "Trust Certificate" option, provide certificate store password and &amp;nbsp;the save your settings.&lt;/li&gt;&lt;li&gt;All the traffic will be routed via Charles now. Enjoy!&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;To summarize reverse proxy settings (Two sets of entries):&lt;br /&gt;&lt;b&gt;Entry 1:&lt;/b&gt;&amp;nbsp;To ensure that all SSL traffic is forwarded to mail.google.com:443&lt;br /&gt;Listening on : 127.0.0.1:443&lt;br /&gt;Forwarding to: 74.125.226.181:443 #one&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Entry 2:&amp;nbsp;&lt;/b&gt;To ensure that all plain HTTP is forwarded too&lt;br /&gt;Listening on : 127.0.0.1:80&lt;br /&gt;Forwarding to: 74.125.226.181:80&lt;br /&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-W0OtWu8DE9A/Tfr5w93VMNI/AAAAAAAAAvI/CgLji-74IfI/s1600/reverse--proxy--settings.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-W0OtWu8DE9A/Tfr5w93VMNI/AAAAAAAAAvI/CgLji-74IfI/s1600/reverse--proxy--settings.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Image shows reverse proxy settings in Charles&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-F7Ngcan8jaw/Tfr5yX_JmLI/AAAAAAAAAvM/UWcP7ZPuh-s/s1600/gmail--error.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="272" src="http://3.bp.blogspot.com/-F7Ngcan8jaw/Tfr5yX_JmLI/AAAAAAAAAvM/UWcP7ZPuh-s/s400/gmail--error.png" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Image shows the certificate error issued when https://mail.google.com is access via reverse proxy. Choosing the "Trust Certificate" options allows SSL traffic to be intercepted.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4663432300421783651-7297070183775079569?l=gursevkalra.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gursevkalra.blogspot.com/feeds/7297070183775079569/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4663432300421783651&amp;postID=7297070183775079569' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4663432300421783651/posts/default/7297070183775079569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4663432300421783651/posts/default/7297070183775079569'/><link rel='alternate' type='text/html' href='http://gursevkalra.blogspot.com/2011/06/intercepting-blackberry-application.html' title='Intercepting Blackberry Application Traffic'/><author><name>Gursev Kalra</name><uri>http://www.blogger.com/profile/11125392470187170013</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-3M831QG-kRs/Tfr3I-hTmgI/AAAAAAAAAvA/qYNzxHfKa_4/s72-c/config--file.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4663432300421783651.post-7631696146752110127</id><published>2011-03-19T08:59:00.000-07:00</published><updated>2011-03-20T00:57:37.178-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='break'/><category scheme='http://www.blogger.com/atom/ns#' term='tesseract'/><category scheme='http://www.blogger.com/atom/ns#' term='CAPTCHA'/><category scheme='http://www.blogger.com/atom/ns#' term='ocr'/><title type='text'>Breaking A Weak CAPTCHA implementation</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;A while back I came across a web application that implemented captcha to prevent automated form entries. The captcha was weak and could be easily solved. Below I summarize the steps followed and provide sample ruby scripts that were used to perform automated form submissions. The page names, form fields etc... are&amp;nbsp;fictitious&amp;nbsp;and do not reflect the exact application data/behavior.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;So lets get started. Here is one sample captcha obtained from the website.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh5.googleusercontent.com/-KebR7KKGZSQ/TYS-GW5bU8I/AAAAAAAAAu4/u0c9j4I0FnI/s1600/19.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;img border="0" src="https://lh5.googleusercontent.com/-KebR7KKGZSQ/TYS-GW5bU8I/AAAAAAAAAu4/u0c9j4I0FnI/s1600/19.bmp" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;My first thought was to try the free "OCR to text" conversion service provided by guys at &lt;a href="http://www.free-ocr.com/"&gt;Free-Ocr&lt;/a&gt;. I uploaded few captchas to the website and it could successfully solve almost all of them. One solved capcha is shown below.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-YshNEhsvnlI/TYS-fbWJh1I/AAAAAAAAAu8/JQ43feIGu08/s1600/free--ocr--ss.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;img border="0" height="216" src="https://lh3.googleusercontent.com/-YshNEhsvnlI/TYS-fbWJh1I/AAAAAAAAAu8/JQ43feIGu08/s320/free--ocr--ss.png" width="320" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Now I knew that the CAPTCHA can be solved, and needed a way to automate the process of solving the captcha.&amp;nbsp;I turned to&amp;nbsp;&lt;a href="http://code.google.com/p/tesseract-ocr/"&gt;Tesseract&lt;/a&gt;&amp;nbsp;to do that for me. Tesseact enjoys the reputation of being&amp;nbsp;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; line-height: 16px;"&gt;one of the most accurate open source OCR engines available.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: inherit; line-height: 16px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: inherit; line-height: 16px;"&gt;Tesseact was downloaded and installed on a windows box. The page requiring captcha input was sourcing captcha's from a php script on the web server. Lets say its path is http://www.test.com/get_captcha.php. The following script helped download a sample captcha, stored it on local file system and then solved it.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: 'Courier New', Courier, monospace; line-height: 16px;"&gt;require 'net/http'&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: 'Courier New', Courier, monospace; line-height: 16px;"&gt;tesseract = 'C:\Tesseract-OCR\tesseract.exe'&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: 'Courier New', Courier, monospace; line-height: 16px;"&gt;q = Net::HTTP.new('www.test.com',80)&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: 'Courier New', Courier, monospace; line-height: 16px;"&gt;# Download new captcha&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: 'Courier New', Courier, monospace; line-height: 16px;"&gt;r = q.get("/get_captcha.php")&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: 'Courier New', Courier, monospace; line-height: 16px;"&gt;File.open("captcha.bmp",'wb') do |f|&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: 'Courier New', Courier, monospace; line-height: 16px;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;f.puts r.body&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: 'Courier New', Courier, monospace; line-height: 16px;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: 'Courier New', Courier, monospace; line-height: 16px;"&gt;# Solve the CAPTCHA&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: 'Courier New', Courier, monospace; line-height: 16px;"&gt;system("#{tesseract} captcha.bmp captcha") #Output gets stored in captcha.txt&lt;/span&gt;&lt;br /&gt;&lt;div style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; line-height: 16px;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; line-height: 16px;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Most of the sourced captchas could be successfully solved using the script above. Good!&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; line-height: 16px;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; line-height: 16px;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;The next obvious step was to automate the entire process of form submissions. The application used&amp;nbsp;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; line-height: 15px;"&gt;&lt;em style="font-style: normal;"&gt;PHPSESSIONID&lt;/em&gt;&lt;/span&gt;&amp;nbsp;to associate captchas with sessions. http://www.test.com/home.php was issuing the PHPSESSIONID and the same sesssion value was being sent to &lt;b&gt;/get_captcha.php &lt;/b&gt;to retrieve a captcha. To automated the process, following was required:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ol style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; line-height: 16px; text-align: left;"&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;GET /home.php page and capture the value of PHPSESSIONID.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Retrieve a captcha by accessing /get_captcha.php while using the captured PHPSESSIONID.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Solve the captcha locally&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;POST the form fields along with PHPSESSIONID and the captcha value&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; line-height: 16px;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;A few more lines to the script above would serve our purpose. The final script looked like below:&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;require 'net/http'&lt;br /&gt;tesseract = 'C:\Tesseract-OCR\tesseract.exe'&lt;br /&gt;q = Net::HTTP.new('www.test.com',80)&lt;br /&gt;r = q.get("/home.php")&lt;br /&gt;r['set-cookie'] =~ /PHPSESSIONID=(.*?);/&lt;br /&gt;hdr = {'Cookie' =&amp;gt; "PHPSESSIONID=#{$1}"}&lt;br /&gt;#get a captcha associated with a valid PHPSESSIONID and solve it&lt;br /&gt;r = q.get("/get_captcha.php",hdr)&lt;br /&gt;File.open("captcha.bmp",'wb') do |f|&lt;br /&gt;f.puts r.body&lt;br /&gt;end&lt;br /&gt;system("#{tesseract} captcha.bmp captcha")&lt;br /&gt;#retrive the captcha value and POST the form details along with valid PHPSESSIONID&lt;br /&gt;captcha = File.read("captcha.txt").strip&lt;br /&gt;q.post('/save_details.php', "fname=gursev&amp;amp;lname=kalra&amp;amp;captcha=#{captcha}" , hdr)&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;div style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; line-height: 16px; text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; line-height: 16px;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; line-height: 16px;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Further Analysis:&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; line-height: 16px;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;The captcha implementation appeared to have more issues.&amp;nbsp;During the analysis around 100 captchas were solved and their values analyzed. Here are the&amp;nbsp;the various observations:&lt;/span&gt;&lt;/div&gt;&lt;div style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; line-height: 16px;"&gt;&lt;/div&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Captchas contained only numerals and hence lesser number of possible combinations.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Out of 100 captchas around 4 duplicate captchas were identified. Thats around 4% of total captchas issued.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Captchas had uneven character distribution with 4's and 5's getting the maximum share of captcha characters. The distribution formed a bell curve with a peak at 4 and 5.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4663432300421783651-7631696146752110127?l=gursevkalra.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gursevkalra.blogspot.com/feeds/7631696146752110127/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4663432300421783651&amp;postID=7631696146752110127' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4663432300421783651/posts/default/7631696146752110127'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4663432300421783651/posts/default/7631696146752110127'/><link rel='alternate' type='text/html' href='http://gursevkalra.blogspot.com/2011/03/breaking-weak-captcha-implementation.html' title='Breaking A Weak CAPTCHA implementation'/><author><name>Gursev Kalra</name><uri>http://www.blogger.com/profile/11125392470187170013</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='https://lh5.googleusercontent.com/-KebR7KKGZSQ/TYS-GW5bU8I/AAAAAAAAAu4/u0c9j4I0FnI/s72-c/19.bmp' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4663432300421783651.post-5642422159277560</id><published>2011-02-14T09:55:00.000-08:00</published><updated>2011-07-02T02:34:26.717-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='enumeration'/><category scheme='http://www.blogger.com/atom/ns#' term='cipher'/><category scheme='http://www.blogger.com/atom/ns#' term='SSLSmart'/><title type='text'>SSLSmart v1.0 Released</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Back in 2009, I went to local OWASP chapter meet and presented on SSL Cipher enumeration script that I was using to enumerate SSL Ciphers for my assessments. Feedback was good but soon other things piled up and the script got burried. Later I realized the need for evolving the concept into an open source and cross platform free tool; named it SSLSmart.&lt;br /&gt;&lt;br /&gt;SSLSmart was released last month and tool can be downloaded from &lt;a href="http://packetstormsecurity.org/files/98035/SSLSmart-SSL-Testing-Tool-1.0.html"&gt;here&lt;/a&gt; (Packetstorm). If you are interested to look at the whitepaper before downloading the entire zip file, you can obtain it from &lt;a href="http://dl.packetstormsecurity.net/papers/general/SSLSmart_WhitePaper_V1.0.pdf"&gt;here&lt;/a&gt; (Packetstorm).&lt;br /&gt;&lt;br /&gt;Here is how a sample SSLSmart run looks like:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-M-51cvxpr_I/TVlv37T9MFI/AAAAAAAAAug/9GegCvvrmy0/s1600/linux_screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://3.bp.blogspot.com/-M-51cvxpr_I/TVlv37T9MFI/AAAAAAAAAug/9GegCvvrmy0/s640/linux_screenshot.png" width="619" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4663432300421783651-5642422159277560?l=gursevkalra.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gursevkalra.blogspot.com/feeds/5642422159277560/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4663432300421783651&amp;postID=5642422159277560' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4663432300421783651/posts/default/5642422159277560'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4663432300421783651/posts/default/5642422159277560'/><link rel='alternate' type='text/html' href='http://gursevkalra.blogspot.com/2011/02/sslsmart-released.html' title='SSLSmart v1.0 Released'/><author><name>Gursev Kalra</name><uri>http://www.blogger.com/profile/11125392470187170013</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-M-51cvxpr_I/TVlv37T9MFI/AAAAAAAAAug/9GegCvvrmy0/s72-c/linux_screenshot.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4663432300421783651.post-7726177851919619364</id><published>2011-02-13T05:30:00.000-08:00</published><updated>2011-02-13T21:47:07.001-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='passwords'/><category scheme='http://www.blogger.com/atom/ns#' term='entropy'/><category scheme='http://www.blogger.com/atom/ns#' term='JTR'/><category scheme='http://www.blogger.com/atom/ns#' term='rbkb'/><category scheme='http://www.blogger.com/atom/ns#' term='password analysis'/><category scheme='http://www.blogger.com/atom/ns#' term='rootkit.com'/><title type='text'>Rootkit.com Password Analysis</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;rootkit.com succumbed to a social engineering attack and more than 42000 of its user's passwords were made available on internet in clear (&lt;a href="http://dazzlepod.com/site_media/txt/rootkit_people_cleartext.txt"&gt;here&lt;/a&gt;). John the Ripper was used to recover the passwords. Out of curiosity, I analyzed certain aspects of passwords. The results of that analysis are shared below:&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Password Lengths: &lt;/b&gt;The shortest password in the list was 1 character long and longest was 20 characters in length. A whopping 38.74% passwords were 6 characters in length. Here is the distribution of password lengths:&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: -webkit-auto;"&gt;&lt;span class="Apple-style-span" style="border-collapse: collapse;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;b&gt; Length &lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt; Occurences &lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt; Percentage &lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1 &lt;/td&gt;&lt;td&gt;16 &lt;/td&gt;&lt;td&gt;0.04% &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2 &lt;/td&gt;&lt;td&gt;20 &lt;/td&gt;&lt;td&gt;0.05% &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3 &lt;/td&gt;&lt;td&gt;270 &lt;/td&gt;&lt;td&gt;0.64% &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4 &lt;/td&gt;&lt;td&gt;1444 &lt;/td&gt;&lt;td&gt;3.41% &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5 &lt;/td&gt;&lt;td&gt;2646 &lt;/td&gt;&lt;td&gt;6.24% &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;6 &lt;/td&gt;&lt;td&gt;16424 &lt;/td&gt;&lt;td&gt;38.76% &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;7 &lt;/td&gt;&lt;td&gt;8258 &lt;/td&gt;&lt;td&gt;19.49% &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;8 &lt;/td&gt;&lt;td&gt;9786 &lt;/td&gt;&lt;td&gt;23.09% &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;9 &lt;/td&gt;&lt;td&gt;2029 &lt;/td&gt;&lt;td&gt;4.79% &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10 &lt;/td&gt;&lt;td&gt;971 &lt;/td&gt;&lt;td&gt;2.29% &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;11 &lt;/td&gt;&lt;td&gt;250 &lt;/td&gt;&lt;td&gt;0.59% &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;12 &lt;/td&gt;&lt;td&gt;157 &lt;/td&gt;&lt;td&gt;0.37% &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;13 &lt;/td&gt;&lt;td&gt;62 &lt;/td&gt;&lt;td&gt;0.15% &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;14 &lt;/td&gt;&lt;td&gt;23 &lt;/td&gt;&lt;td&gt;0.05% &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;15 &lt;/td&gt;&lt;td&gt;8 &lt;/td&gt;&lt;td&gt;0.02% &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;16 &lt;/td&gt;&lt;td&gt;3 &lt;/td&gt;&lt;td&gt;0.01% &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;17 &lt;/td&gt;&lt;td&gt;1 &lt;/td&gt;&lt;td&gt;0.00% &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;18 &lt;/td&gt;&lt;td&gt;0 &lt;/td&gt;&lt;td&gt;0.00% &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;19 &lt;/td&gt;&lt;td&gt;2 &lt;/td&gt;&lt;td&gt;0.00% &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;20 &lt;/td&gt;&lt;td&gt;4 &lt;/td&gt;&lt;td&gt;0.01% &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;b&gt;Password Entropy:&lt;/b&gt;&lt;br /&gt;Entropy of various cracked passwords was calculated using Eric Monti's&amp;nbsp;&lt;a href="http://emonti.github.com/rbkb/"&gt;rbkb&lt;/a&gt;'s entropy function that performs chi-square calculation. Clearly, higher the entropy, lesser chances that your password will be guessed or cracked. Having said that, how easy is to remember and key in the passwords that are extremely random and are more than 16 characters in length?&lt;br /&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;b&gt; Entropy &lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt; Count &lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;0 to &amp;lt;1 &lt;/td&gt;&lt;td&gt;1620 &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1 to &amp;lt;2 &lt;/td&gt;&lt;td&gt;7388 &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2 to &amp;lt;3 &lt;/td&gt;&lt;td&gt;32071 &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3 to &amp;lt;4 &lt;/td&gt;&lt;td&gt;1292 &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4 to &amp;lt;5 &lt;/td&gt;&lt;td&gt;3 &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5 to &amp;lt;6 &lt;/td&gt;&lt;td&gt;0 &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;6 to &amp;lt;7 &lt;/td&gt;&lt;td&gt;0 &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Cracked Passwords with Highest Entropy:&amp;nbsp;&lt;/b&gt;&lt;br /&gt;Certain cracked passwords had entropy in excess of 4 bits. Table below lists down the cracked passwords with highest entropy. A good dictionary allowed JTR to crack most of the passwords.&lt;br /&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;b&gt; # &lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt; Entropy &lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt; Password &lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1 &lt;/td&gt;&lt;td&gt;4.321928095 &lt;/td&gt;&lt;td&gt;q1w2e3r4t5y6u7i8o9p0 &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2 &lt;/td&gt;&lt;td&gt;4.321928095 &lt;/td&gt;&lt;td&gt;1234567890qwertyuiop &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3 &lt;/td&gt;&lt;td&gt;4.321928095 &lt;/td&gt;&lt;td&gt;1q2w3e4r5t6y7u8i9o0p &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4 &lt;/td&gt;&lt;td&gt;4 &lt;/td&gt;&lt;td&gt;1234qwerasdfzxcv &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5 &lt;/td&gt;&lt;td&gt;3.807354922 &lt;/td&gt;&lt;td&gt;abcdefg1234567 &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;6 &lt;/td&gt;&lt;td&gt;3.700439718 &lt;/td&gt;&lt;td&gt;qwertyuiop123 &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;7 &lt;/td&gt;&lt;td&gt;3.700439718 &lt;/td&gt;&lt;td&gt;superman12345 &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;8 &lt;/td&gt;&lt;td&gt;3.700439718 &lt;/td&gt;&lt;td&gt;1qazxcvbnm,./ &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;9 &lt;/td&gt;&lt;td&gt;3.664497779 &lt;/td&gt;&lt;td&gt;kingoftheworld &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10 &lt;/td&gt;&lt;td&gt;3.664497779 &lt;/td&gt;&lt;td&gt;qwertyuiop[]\\ &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;11 &lt;/td&gt;&lt;td&gt;3.584962501 &lt;/td&gt;&lt;td&gt;!@#$%^&amp;amp;*()_+ &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;12 &lt;/td&gt;&lt;td&gt;3.584962501 &lt;/td&gt;&lt;td&gt;fucktheworld &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;13 &lt;/td&gt;&lt;td&gt;3.584962501 &lt;/td&gt;&lt;td&gt;1q2w3e!Q@W#E &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;14 &lt;/td&gt;&lt;td&gt;3.584962501 &lt;/td&gt;&lt;td&gt;qazxswedcvfr &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;15 &lt;/td&gt;&lt;td&gt;3.584962501 &lt;/td&gt;&lt;td&gt;123qweasdzxc &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;16 &lt;/td&gt;&lt;td&gt;3.584962501 &lt;/td&gt;&lt;td&gt;1qazxsw23edc &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;17 &lt;/td&gt;&lt;td&gt;3.584962501 &lt;/td&gt;&lt;td&gt;q1w2e3r4t5y6 &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;18 &lt;/td&gt;&lt;td&gt;3.584962501 &lt;/td&gt;&lt;td&gt;asdfghjkl;\' &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;19 &lt;/td&gt;&lt;td&gt;3.584962501 &lt;/td&gt;&lt;td&gt;qwerty123456 &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;20 &lt;/td&gt;&lt;td&gt;3.584962501 &lt;/td&gt;&lt;td&gt;4rfv5tgb6yhn &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;21 &lt;/td&gt;&lt;td&gt;3.584962501 &lt;/td&gt;&lt;td&gt;qwe123rty456 &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;22 &lt;/td&gt;&lt;td&gt;3.584962501 &lt;/td&gt;&lt;td&gt;1qaz2wsx3edc &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;23 &lt;/td&gt;&lt;td&gt;3.584962501 &lt;/td&gt;&lt;td&gt;1a2b3c4d5e6f &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;24 &lt;/td&gt;&lt;td&gt;3.584962501 &lt;/td&gt;&lt;td&gt;123456qwerty &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;25 &lt;/td&gt;&lt;td&gt;3.584962501 &lt;/td&gt;&lt;td&gt;1q2w3e4r5t6y &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Password Distribution:&lt;/b&gt;&lt;br /&gt;Finally, I looked at password distribution. An overwhelming 51% of cracked passwords were only in&amp;nbsp;lowercase, this was followed by only numeric passwords close to 24%. Passwords using uppercase alphabets along with numerics were least&amp;nbsp;favorite.&lt;br /&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;b&gt; Password Type &lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt; Percentage Share &lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Only Lowercase &lt;/td&gt;&lt;td&gt;51.81 &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Lowercase AND Numerals &lt;/td&gt;&lt;td&gt;23.92 &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Only Numeric &lt;/td&gt;&lt;td&gt;19.9 &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Alphabets (Uppercase AND Lowercase) &lt;/td&gt;&lt;td&gt;1.32 &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Alphanumeric &lt;/td&gt;&lt;td&gt;1.25 &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Passwords With Special Characters &lt;/td&gt;&lt;td&gt;1.11 &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Only Uppercase &lt;/td&gt;&lt;td&gt;0.45 &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Uppercase AND Numerals &lt;/td&gt;&lt;td&gt;0.24 &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4663432300421783651-7726177851919619364?l=gursevkalra.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gursevkalra.blogspot.com/feeds/7726177851919619364/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4663432300421783651&amp;postID=7726177851919619364' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4663432300421783651/posts/default/7726177851919619364'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4663432300421783651/posts/default/7726177851919619364'/><link rel='alternate' type='text/html' href='http://gursevkalra.blogspot.com/2011/02/rootkitcom-password-analysis.html' title='Rootkit.com Password Analysis'/><author><name>Gursev Kalra</name><uri>http://www.blogger.com/profile/11125392470187170013</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4663432300421783651.post-7208972994604902785</id><published>2009-09-12T00:33:00.000-07:00</published><updated>2009-09-14T10:34:27.216-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tlsv1'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='enumeration'/><category scheme='http://www.blogger.com/atom/ns#' term='cipher'/><category scheme='http://www.blogger.com/atom/ns#' term='openssl'/><category scheme='http://www.blogger.com/atom/ns#' term='sslv3'/><category scheme='http://www.blogger.com/atom/ns#' term='sslv2'/><title type='text'>Ruby and OpenSSL Based SSL Cipher Enumeration</title><content type='html'>In this post, we will write our bare bones Ruby based SSL cipher enumerator to enumerate SSL cipher suites supported by a webserver. Without further delay, lets get started.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Basics:&lt;/span&gt;&lt;br /&gt;The first step of every SSL communication is SSL handshake. During SSL handshake, both client and server settle on a common cipher suite to be used for communication. Client initiated "Client Hello" provides server with all the cipher suites it supports. The server responds with the cipher suite it wants to use for communication in the Server Hello message. Image below shows list of cipher suites sent out to the webserver during Client Hello request.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_pJMGfPG0yL8/SquXsUpO3XI/AAAAAAAAAsk/-bBFLG7m0Vc/s1600-h/OpenSSL_All_Ciphers.png"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5380560967535877490" src="http://1.bp.blogspot.com/_pJMGfPG0yL8/SquXsUpO3XI/AAAAAAAAAsk/-bBFLG7m0Vc/s1600/OpenSSL_All_Ciphers.png" style="cursor: hand; height: 474px; margin: 0px auto 10px; text-align: center; width: 640px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;To successfully enumerate supported SSL ciphers, we need to initiate SSL connection with only one cipher suite (for one protocol version) at a time and observe its response.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Initial housekeeping&lt;/span&gt;&lt;br /&gt;===============================&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;require 'net/https'&lt;/li&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;target_url = "mail.google.com" # Target website&lt;/span&gt;&lt;span style="font-family: courier new;"&gt; &lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;port = 443 # Target Port&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;protocol_versions = [:SSLv2, :SSLv3, :TLSv1] # Protocol versions support&lt;/span&gt; &lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Extending the HTTP Class&lt;/span&gt;&lt;br /&gt;===============================&lt;br /&gt;We will now extend the HTTP class to include two methods that will help us request application home page with one cipher suite at a time. Since classes in Ruby are not closed, we will extend the existing HTTP class. &lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;module Net&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;class HTTP&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;def set_context=(value)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;@ssl_context = OpenSSL::SSL::SSLContext.new &lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;@ssl_context &amp;amp;&amp;amp;= OpenSSL::SSL::SSLContext.new(value) &lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;end&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;ssl_context_accessor :ciphers&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;end&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;end&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-weight: bold;"&gt;Lines 3-6:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;def set_context=(value)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;@ssl_context = OpenSSL::SSL::SSLContext.new &lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;@ssl_context &amp;amp;&amp;amp;= OpenSSL::SSL::SSLContext.new(value) &lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;end&lt;br /&gt;&lt;/span&gt;The &lt;span style="font-family: courier new;"&gt;set_context= &lt;/span&gt;method helps us set context for one HTTP request. By setting context for a HTTP request, we enforce use of cipher suites and protocol version of our choice.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Line 8:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;ssl_context_accessor :ciphers&lt;/span&gt;&lt;br /&gt;It creates two methods:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;ciphers : Return the cipher suite values used.&lt;/li&gt;&lt;li&gt;ciphers= : Set cipher suite for current request.&lt;/li&gt;&lt;/ol&gt;For more information about ssl_context_accessor, please refer to please refer to net/https.rb in you ruby installation directory.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Getting it work:&lt;/span&gt;&lt;br /&gt;===============================&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;protocol_versions.each do |version| &lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;cipher_set = OpenSSL::SSL::SSLContext.new(version).ciphers&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;puts "\n======================================="&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;puts version&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;puts "========================================="&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;cipher_set.each do |cipher_name, ignore_me_cipher_version, bits, ignore_me_algorithm_bits| &lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;request = Net::HTTP.new(target_url, port)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;request.use_ssl = true&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;request.set_context = version&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;request.verify_mode = OpenSSL::SSL::VERIFY_NONE&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;request.ciphers = cipher_name&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;beginresponse = request.get("/")&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;puts "[+] Accepted\t #{bits} bits\t#{cipher_name}"&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;rescue OpenSSL::SSL::SSLError =&amp;gt; e&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;puts "[-] Rejected\t #{bits} bits\t#{cipher_name}"&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;rescue #Ignore all other Exceptions&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;end&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;end&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;end&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;strong&gt;Line 1:&lt;/strong&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;protocol_versions.each do |version|&lt;/span&gt;&lt;br /&gt;Loop through the cipher versions we are testing and pass on the value to the code block.&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;Line 2:&lt;/strong&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;cipher_set = OpenSSL::SSL::SSLContext.new(version).ciphers&lt;/span&gt;&lt;br /&gt;Create new context for a give protocol version and return all the ciphers supported by OpenSSL version with which your ruby installation was compiled. The returned value is an array of array. Each element of the returned array is of following format: [name, version, bits, alg_bits]. Here &lt;span style="font-weight: bold;"&gt;name&lt;/span&gt; is cipher suite name, &lt;span style="font-weight: bold;"&gt;version &lt;/span&gt;is the protocol version (SSLv2, TLSv1/SSLv3), &lt;span style="font-weight: bold;"&gt;bits&lt;/span&gt; is key length in bits and &lt;span style="font-weight: bold;"&gt;alg_bits&lt;/span&gt; is the supported key length for the encryption algorithm.&lt;br /&gt;&lt;br /&gt;An example cipher suite array for SSLv2 protocol:&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;[&lt;br /&gt;["DES-CBC3-MD5", "SSLv2", 168, 168],&lt;br /&gt;["IDEA-CBC-MD5", "SSLv2", 128, 128],&lt;br /&gt;["RC2-CBC-MD5", "SSLv2", 128, 128],&lt;br /&gt;["RC4-MD5", "SSLv2", 128, 128],&lt;br /&gt;["DES-CBC-MD5", "SSLv2", 56, 56],&lt;br /&gt;["EXP-RC2-CBC-MD5", "SSLv2", 40, 128],&lt;br /&gt;["EXP-RC4-MD5", "SSLv2", 40, 128]&lt;br /&gt;]&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;strong&gt;Line 7 and 8:&lt;/strong&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;request = Net::HTTP.new(target_url, port)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;request.use_ssl = true&lt;/span&gt;&lt;br /&gt;Creates a new HTTP object and enables use of SSL for communication.&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;Line 9: &lt;/strong&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;request.set_context = version&lt;/span&gt;&lt;br /&gt;Sets context of current request to protocol vesion provided. It is very important to set the right context when we want to restrict the cipher suites used. An example should be able to demonstrate it with more clarity.&lt;br /&gt;&lt;br /&gt;Consider following two code snips and corresponding packet capture in wireshark. For purpse of experimentation, a connection request was initiated to mail.google.com and "Client Hello" was observed using Wireshark for both the snips. It can be clearly seen in the screenshots that when context is not provided, it is possible that multiple cipher suites for a given cipher name can be chosen. In this case, "RC4-MD5" cipher suite is present in both TLSv1/SSLv3 and SSLv2. When context is not set to SSLv2 or TLSv1/SSLv3, the "Client Hello" will include two cipher suites; one for TLSv1/SSLv3 and other for SSLv2. This results in incorrect enumeration.&lt;br /&gt;&lt;br /&gt;For example, certain websites may not allow use of SSLv2. When connection attemps are made using "RC4-MD5" cipher without setting proper context, connection attempts might be successful because the "Client Hello" now contains an additional cipher suite for SSLv3/TLSv1. &lt;br /&gt;&lt;br /&gt;# == SNIP 1 Begins ===&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;request = Net::HTTP.new("mail.google.com", 443)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;request.use_ssl = true&lt;/span&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="font-family: courier new;"&gt;request.set_context = :SSLv2&lt;/span&gt; &lt;/strong&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;request.verify_mode = OpenSSL::SSL::VERIFY_NONE&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;request.ciphers = "RC4-MD5"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;response = request.get("/")&lt;/span&gt;&lt;br /&gt;# == SNIP 1 ENDS ===&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_pJMGfPG0yL8/SquZCm7qxOI/AAAAAAAAAs0/RSS6CmKp2Z8/s1600-h/RC4-MD5_with_context.png"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5380562449913791714" src="http://2.bp.blogspot.com/_pJMGfPG0yL8/SquZCm7qxOI/AAAAAAAAAs0/RSS6CmKp2Z8/s320/RC4-MD5_with_context.png" style="cursor: hand; float: left; height: 147px; margin: 0px auto 10px; text-align: center; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;br/&gt;&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;# == SNIP 2 Begins ===&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;request = Net::HTTP.new("mail.google.com", 443)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;request.use_ssl = true&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;request.verify_mode = OpenSSL::SSL::VERIFY_NONE&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;request.ciphers = "RC4-MD5"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;request.get("/")&lt;/span&gt;&lt;br /&gt;# == SNIP 2 Ends ===&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_pJMGfPG0yL8/SquZhXiBw0I/AAAAAAAAAs8/T6eDoK6Xh7Q/s1600-h/RC4-MD5_without_context.png"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5380562978355659586" src="http://4.bp.blogspot.com/_pJMGfPG0yL8/SquZhXiBw0I/AAAAAAAAAs8/T6eDoK6Xh7Q/s320/RC4-MD5_without_context.png" style="cursor: hand; float: left; height: 147px; margin: 0px 10px 10px 0px; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;The only difference in Snip 1 and Snip 2 is context assignment call, &lt;strong&gt;request.set_context = :SSLv2&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Line 10:&lt;br /&gt;&lt;/strong&gt;&lt;span style="font-family: courier new;"&gt;request.verify_mode = OpenSSL::SSL::VERIFY_NONE&lt;br /&gt;&lt;/span&gt;Prevents certificate verification. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Line 11:&lt;/strong&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;request.ciphers = cipher_name&lt;br /&gt;&lt;/span&gt;Sets request ciphers to provided cipher suite.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Line 12 to 17:&lt;/strong&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;beginresponse = request.get("/")&lt;br /&gt;puts "[+] Accepted\t #{bits} bits\t#{cipher_name}"&lt;br /&gt;rescue OpenSSL::SSL::SSLError =&amp;gt; e&lt;br /&gt;puts "[-] Rejected\t #{bits} bits\t#{cipher_name}"&lt;br /&gt;rescue #Ignore all other Exceptions&lt;br /&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Attempt connection to the remote host and fetch the home page. &lt;strong&gt;OpenSSL::SSL::SSLError&lt;/strong&gt; exception is raised when connection attempts fail due to cipher suite mismatch. All other exceptions are ignored. Success and failure of connection combined with exception decides if the cipher suite was supported or rejected.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Putting it all together:&lt;br /&gt;&lt;/strong&gt;===============================&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;require 'net/https'&lt;br /&gt;target_url = "mail.google.com"&lt;br /&gt;port = 443&lt;br /&gt;module Net &lt;br /&gt;class HTTP &lt;br /&gt;def set_context=(value) &lt;br /&gt;@ssl_context = OpenSSL::SSL::SSLContext.new #Create a new context &lt;br /&gt;@ssl_context &amp;amp;&amp;amp;= OpenSSL::SSL::SSLContext.new(value) &lt;br /&gt;end &lt;br /&gt;ssl_context_accessor :ciphers &lt;br /&gt;end&lt;br /&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;protocol_versions.each do |version|&lt;br /&gt;cipher_set = OpenSSL::SSL::SSLContext.new(version).ciphers &lt;br /&gt;puts "\n============================================" &lt;br /&gt;puts version &lt;br /&gt;puts "============================================" &lt;br /&gt;cipher_set.each do |cipher_name, ignore_me_cipher_version, bits, ignore_me_algorithm_bits|&lt;br /&gt;request = Net::HTTP.new(target_url, port) &lt;br /&gt;request.use_ssl = true &lt;br /&gt;request.set_context = version &lt;br /&gt;request.ciphers = cipher_name &lt;br /&gt;request.verify_mode = OpenSSL::SSL::VERIFY_NONE &lt;br /&gt;begin &lt;br /&gt;response = request.get("/") &lt;br /&gt;puts "[+] Accepted\t #{bits} bits\t#{cipher_name}" &lt;br /&gt;rescue&lt;br /&gt;OpenSSL::SSL::SSLError =&amp;gt; e &lt;br /&gt;puts "[-] Rejected\t #{bits} bits\t#{cipher_name}" &lt;br /&gt;rescue #Ignore all other Exceptions &lt;br /&gt;end &lt;br /&gt;end&lt;br /&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;A Sample Run &lt;/b&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_pJMGfPG0yL8/Squcj-LkrOI/AAAAAAAAAtU/aduA7hBLvjc/s1600-h/SSLEnum_Sample_Run.png"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5380566321625083106" src="http://1.bp.blogspot.com/_pJMGfPG0yL8/Squcj-LkrOI/AAAAAAAAAtU/aduA7hBLvjc/s400/SSLEnum_Sample_Run.png" style="cursor: hand; height: 400px; margin: 0px auto 10px; text-align: center; width: 270px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Let me know if you have any queries or comments. Thanks for stopping by..&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4663432300421783651-7208972994604902785?l=gursevkalra.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gursevkalra.blogspot.com/feeds/7208972994604902785/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4663432300421783651&amp;postID=7208972994604902785' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4663432300421783651/posts/default/7208972994604902785'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4663432300421783651/posts/default/7208972994604902785'/><link rel='alternate' type='text/html' href='http://gursevkalra.blogspot.com/2009/09/ruby-and-openssl-based-ssl-cipher.html' title='Ruby and OpenSSL Based SSL Cipher Enumeration'/><author><name>Gursev Kalra</name><uri>http://www.blogger.com/profile/11125392470187170013</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_pJMGfPG0yL8/SquXsUpO3XI/AAAAAAAAAsk/-bBFLG7m0Vc/s72-c/OpenSSL_All_Ciphers.png' height='72' width='72'/><thr:total>2</thr:total></entry></feed>
