Thursday, March 15, 2007

Steal Browser History Without JavaScript

'We all know there are still people out there who think turning off JavaScript protects them from everything.'

See also : https://www.indiana.edu/~phishing/browser-recon/

Research by RSnake
----------------------------------
Well, the server is back up and running (big thanks to id - during our upgrade there was a drive failure causing us to have to switch machines), and to celebrate I didn’t want to come back with a boring post that would make you question why you read this site. So instead I decided to play around with some CSS tricks - bare with me for a minute. I don’t know why, but I really think CSS is going to get worse over time. Anyway, as I was poking around I happened across one of the missing pieces of the puzzle to solve a simple problem in using CSS to hack - the lack of conditional logic.

Jeremiah and I spent at least an hour on the phone several months back when he was coming up with browser port scanning without JavaScript. One of the key problems with that technique, which he later overcame, was that he was unable to find any good way to do conditional logic in CSS, so instead he leaned on a browser quirk that delays the rendering of images. Watching the timing differences can help an attacker derive which ports are open and which aren’t. While very cool, it’s caused some headaches and only solved one of our problems.

Before that Jeremiah also came up with the original CSS history hack as you may or may not remember. Later on pdp came up with another variant of the same issue using a very different technique (Firefox caching). Both of those techniques were cool, but both of them also required that you have JavaScript turned on. We all know there are still people out there who think turning off JavaScript protects them from everything.

Keeping this in mind it would be great if you could create a form of conditional logic in CSS. Well I finally figured out a way. Using a hybrid of a:visited and display: attribute you can detect that the user has visited a page and more importantly perform an action based on that fact. The actions are somewhat limited if you can’t use JavaScript, however, one action is enough. The reason being, when something is set to display:none it will actually cause the HTML tag that it references to not render. Setting the background: image attribute for the visible tag to use a URL of a logging CGI script allows you to send a request to a remote webserver based on the conditional logic as mentioned above.

Now, the only lacking part is the state management, and that can easily be tied together using a unique cookie, and/or an IP address in the QUERY_STRING or anything else you want to use to identify the user. In this way, the remote website can steal history information from the user without ever once using JavaScript, or any client side programming. Click here for a proof of concept of the CSS history theft without using JavaScript. This works nearly instantly, so it is far better than the JavaScript-less intranet hacking and pdp’s version of the JavaScript CSS history hack in terms of speed. The only latency is the time it takes your browser to request the images associated with each URL you’ve visited - which is nearly instant since I don’t return any data (and thanks to browser threading). The other nice thing about this is that it works beautifully in both Internet Explorer 7.0 and Firefox 2.0.0.2 (although it doesn’t work in Opera 9.22).

I haven’t experimented much with this yet, but I also believe this could be expanded to do another form of intranet port scanning as well. Using a series of iframes and forced browsing it may be possible to detect which pages the user can access. I’m not in love with this technique because the CSS will fire too quickly so you’d have to delay the CSS from loading or make it reload with a meta refresh or something equivalent, but I also haven’t put much thought into it yet.

The ramifications of the CSS history hacking stuff is that it allows the attacker to steal information about the client, which can be useful to identify a target, to find information about the user, for use in targeted attacks, to know trending information for use in targeted advertizements or other forms of private information theft.

So now we’ve eliminated the JavaScript pre-requisite from Intranet port scanning, cross site request forgeries, session riding and of course CSS history hacking. The only thing we can’t yet do without JavaScript is read cross domain (and I stress the word yet). What else is left? I don’t mean to sound ho-hum about this, but really, what else do we have to do? Are there any nay-sayers left?

Labels: , ,