If you were looking for vulnerabilities on a website, you might open up the original page source looking for commented-out code, javascript source, hidden forms, etc. If you suspected an XSS attack on your own site, chances are you might right-click on the page and view source to check for unwanted scripts. If you needed to register for CTP, hack this site, or read the snarky comments in the HTML of www.defcon.org, you would probably need to view the page source.
This is all based on your assumption that when you right-click on the page and select "View Source" the text you see is the HTML source that the server sent to your browser when it requested the URL in your address bar. Unfortunately if you assumed this, you would be wrong. Like me; I always expected that Javascript method calls could only change the appearance of the page, like DOM manipulation, and the "Original Source" window would display the original source of the page. Silly me!
When you use document.write outside of a script tag embedded inline in the page, it replaces the current document content with the new content, which becomes active when document.close is called. This is normal, documented behavior. Surprisingly, at this point if you right-click on the page and click view source in Internet Explorer, it will show the new content, not the old content. And it still displays the original page URL! The original page source has effectively changed.
This technique could be used in any of the above scenarios. For example, in a persistent or type 2 cross site scripting attack, the ability to erase the injected script tags from the page would be very convenient. To see this in action, visit the basic page (normal) and compare to the new page (obvious XSS) or the alt page (hidden XSS - adds an iframe) In Win7+IE8, this is what you see:
If you can find the javascript in the "Original Source" in that screenshot, see a specialist, because it is not there. IE is the worst of the browsers here, because there is no visible indication that the source has been changed. It lies and says that the displayed source is the source of the URL you visited. In reality, it could have been pulled or generated from anywhere.
I have not seen this behavior documented, but I assume it is not a secret among browser developers. For example, let's see how this page looks in Firefox:
Once again, the script has been erased from the page, the address in the browser bar is unchanged, no popup windows have been opened, etc. However there is one small difference, the address in the title bar of the source window is prefixed by "wyciwyg" - no this is not a typo of wysiwyg, it means "what you cache is what you get." Normally these URLs are not visible to the user, but they are used for local cached copies of pages. Nevertheless, the modification is complete; the original source has been completely rewritten and the address bar is unchanged.
So what can you do? I was not able to test every browser, but Chrome displays the actual original source:
Alternatively, you can try to catch the pages via Wireshark but Wireshark will not work with HTTPS. Certain Firefox addons can capture the original source as well, such as the Net panel of Firebug.
#1 by alirobe on September 8, 2011 - 6:04 am
Fortunately, IE9’s ‘F12 inspector’ (which is what I always use to view source anyway) shows the exploit.
#2 by mixis on September 8, 2011 - 3:52 pm
interesting! it looks like other browsers should be able to show it out of the box, too: view-source:http://en.wikipedia.org/wiki/View-source_URI_scheme
this is what i got with vimperators :viewsource, which imho is the most handy way to have a look at the source anyway
#3 by Benjamin Flesch on September 8, 2011 - 10:43 pm
Thanks for your elaborate research. This should definitely filed as a bug with the Firefox devs. In case this technique is currently used in the wild, it can be used for data collection and statistics as well – without any of the visitors noticing it.
#4 by Robert Augustin on September 9, 2011 - 1:05 pm
You can see the original script in FF when you disable JS – or if you’re using NoScript… so it’s not 100% fool-proof. Still, a very interesting find!
#5 by mshenrick on September 9, 2011 - 8:12 pm
i wgetted then catted the page and there was no javascript. I was like ‘WTF? it affects cat and its not even a html viewer!?’ then i relaised i donwloaded the non XSS version! doh!
#6 by scriptjunkie on September 10, 2011 - 5:31 am
Yeah, it’s some pretty sweet javascript; even includes an 0-day for cat.
#7 by Steve on September 10, 2011 - 1:26 am
Safari and Chrome on Mac OS X both show the actual source. FireFox redirects me to youtube.
#8 by kro on September 10, 2011 - 3:30 am
Someone already filed the bug?
#9 by scriptjunkie on September 10, 2011 - 5:32 am
I don’t know. Bugzilla is stuck pondering for me when I try to search for “View Source” and I haven’t tried contacting Microsoft.
And in the bigger picture, this doesn’t really have to be a big bug; it could just be better documented. Maybe there could be a clearer message at the top saying that it was displaying the last generated source. But I would prefer the chrome style of just displaying the real original source, possibly with an option of viewing the last-written source.
#10 by t3st on September 10, 2011 - 10:24 am
Very interesting finding. Great article ;D
However, as I tried, even without document.close, FF & IE were still showing new content instead of old one. I’m not sure if others’ browsers show that same behavior as mine.