Hijacking Innocent Frames

Thu, 11 Dec 2008 21:39:16 GMT

Magic tricks are all about suggestion, psychology, misdirection and showmanship (see Tricks of the Mind), or as Cutter) perhaps will say, every magic trick has tree parts: the pledge (where the magician shows you something ordinary), the turn (where the ordinary becomes something extraordinary), and the prestige (where the extraordinary turns into something you have never seen before).

In a similar way, real world information security breaches are combination of the characteristics you will often find in the performance of skillful magicians. Therefore, allow me introduce you to a simplistic form of an attack, perhaps so simple that in fact it may work far more often than we would like to admit, which skillfully uses suggestion, psychology, misdirection and a great doze of showmanship.

So, we've all heard of clickjacking and we know that it is a design bug and therefore it is very hard to deal with. However, are there other flawed areas of modern browsers design which can be abused? Of course there are. It just takes time to find them all because they are often well hidden underneath our common believes, ignorance and prejudice. Here is some code:

            function clickme() {
                var w = window.open('http://www.google.com');

                setTimeout(function () {
                    w.location = 'http://www.gnucitizen.org';
                }, 5000);
        <input type="button" value="click me" onclick="clickme(this)"/>

"Quite boring! I agree." First of all the user clicks on a button/link. Then a new tab/window opens which loads the content of http://www.google.com. Five seconds later, the newly created tab is preloaded with the content of http://www.gnucitizen.org. Do you find this code disturbing? I do. It is disturbing because it breaks the trust relationship that is going on between the user and google.com in this specific example. Call it surfjacking, framejacking, tabjacking or whatever you want to call it, but at the end of the day, I believe that this is just yet another form of bad design.

Here is another example. You browse the web, you click to digg a story, you get redirected to digg.com to login. SSL looks fine. The browser lights up all green. It is OK to type your username/password and you do. In the background, the page which initially took you to digg.com waits for you to login. It subsequently queries the digg.com login page for changes in the DOM structure by using script tags and error handlers to capture different error code offsets (check AttackAPI), and as such it tries to detect when you are fully logged on. It does these checks every half a second. Once a successful login is detected, it simply fires w.location = "some evil url here"; which will force the browser to render something else, perhaps something malicious, instead of the page that should have came after a successful authentication. Perhaps, the evil caller could even fire just a simple alert('Hey there!'); message as a form of misdirection and than return back the control with another w.focus().

Would you check the address bar again? Perhaps not, because the page which was forced onto you now contains similarly looking digg.com login page accompanied with some red and quite scary looking text which tells you that your login was unsuccessful. This is the psychology. The attacker uses the red color to distract your from the address bar so that you put all of your attention into the login form. You cannot escape your instincts. The forms screams at you that all you have to do is to fill in your username and password and everything will be fine again. You rush to fill in your credentials again. Your request is recorded. A 302 redirect fires back and the browser redirects you to your digg.com account like nothing has ever happened. This is the prestige.

As far as I know, although I might be wrong, this form of an attack is new. It is definitely not devastating and it wont break the Web. However, my honest opinion is that it does break a lot of things. For example, it breaks the user's normal surfing experience. The good news is that there is an easy fix. Simply put, do not allow pages to redirect windows which are preloaded with content from a different origin! We fix this, we save the Web again.

i bet someone will call it a feature ;)
Good point, nice hack and solution that sounds like something that should have been a reasoable rule from the beginning. Regarding the AttachAPI and detecting signatures to check if someone is online: that seems to be fixed at least in moderately modern versions of FF - I tried to get a demo working of that earlier this summer, but the error messages accessible from the DOM are not as verbose anymore.
Add-on like "secure login" for Firefox or the "magic wand" connection of Opera could prevent such hack. As one doesn't enter his credentials but they are fetch by the add-on if and only the page is the right one, the second login-dialogbox would not be filled .... Or did i miss something ???
Of course, using such a trick for other malicious purpose would work .... :o(
I forgot to mention that there are other ways to detect when a user is logged on. think of dynamically generated css, image, swf and js files. all of them can be used to find the current user's state.
Intresting post! I think other vectors also exist since same-origin-policy doesnt apply for the location object here. window.location normally returns the current URL of the window, so all data in URL can be stolen this way. I tried this in firebug:
w = window.open("http://gmail.com")
w.location = "https://gmail.com"
w.location = "https://gmail.com"
The second time I call w.location, it returns - https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=https%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ss=1&ltmpl=default&ltmplcache=2 So even without redirecting to another fake website, we can get the session IDs if they are in the URL(even over SSL). Also most CSRF countermeasures add the unquie nonce to the URL (including ESAPI), this can also be used to bypass the anti-CRSF measures in selective cases.
Good write up; it seems like in principle our issue is that scripts from a previous page are running on the current one. The solution may be something along the lines of my understanding of the Google Chrome model. When you leave a site, that page dies with the executable and a new one is created for your new site; no residual triggers are left to be fired.
This attack isn't new. In fact, it's used in a standard called SCORM. SCORM requires a javascript API to be loaded in a parent frame (or window.opener if a pop-up). The javascript API must make calls in behalf of the SCORM module. The javascript API could do what it wants, including changing the location.href of another frame (or pop-up).
lavakumar, yes you can do that from Firebug but it wont work from a HTML page as far as I know, unless you are looking into some kind of a bug.
Hello, yes you are right, there are many not discovered bugs, or just not released, design bugs in web browsers as you said. I think that the best way to detect/discover them all is just makeing more and more fuzzers, i am almost sure that there are many specific bugs :)
hmmmmm, I don't think that fuzzers will work for finding design bugs... overflows yes, but not design bugs.
Your are right, looks like it only works from firebug...my bad.
Why is not there a decent online iFrame vulnerability scanner? We had Jutaky's iFrame Detektor, but that has gone offline somehow... Now we have to construct our own queries like feed this to Google, and see how your firekeeper flags this... polonus
The Rook (Michael Brooks)The Rook (Michael Brooks)
Hey PDP people are ripping off your research! I guess its a complement of your visionary hacks :) http://www.azarask.in/blog/post/a-new-type-of-phishing-attack/
I've long realised that research should stay as a hobby. :) rather than means for making money. There are other more practical ways of earning your living.