Intro: Why Clickjacking matters
Clickjacking is a vulnerability that is often underestimated, despite Clickjacking potentially affecting the confidentiality, integrity, and availability of the application to a high degree.
The impact of a successful attack can be privilege escalation (eg changing permissions from regular user to full admin), weakening of security mechanisms (eg disabling 2FA), deletion of data, or making data publicly accessible.
I have previously shown that it is even possible to control text input via Clickjacking (at least in Firefox), giving Clickjacking (almost) the full power of CSRF.
But compared to CSRF, Clickjacking requires more user interaction than simply visiting an attacker-controlled page. For simple one-click attacks such as like-stealing, this is negligible, but for multi-click attacks (eg checking the “is admin” box, followed by a click on “save”), this seems to prevent real-world exploitation. Who is going to click 5 times in exactly the right position? Nobody.
But users click on webpages all the time! If we can intercept and redirect these clicks to where they are needed, multi-click attacks suddenly become much more realistic.
With advanced Clickjacking techniques such as automatically tracking the mouse cursor and directing the click exactly where it’s needed, it is possible to exploit multi-click Clickjacking vulnerabilities in the wild. The user simply has to click somewhere - anywhere - a couple of times.
Details: How to perform advanced, multi-click Clickjacking attacks
The idea of an advanced Clickjacking script is simple: We put the iframe that frames the vulnerable page inside a tiny div, hide the overflow, and do two things:
- track the mouse cursor to keep the div under it so all clicks go to the framed site
- after each click, shift the iframe inside the div so that the part of the iframe that should be clicked by the user is “visible” in the div.
Positioning the div and iframe are easy. Tracking the div can be achieved via onmousemove
and the positioning of the iframe inside the div with overflow: hidden
and margin-left
/margin-top
.
Registering a click is more complicated, because it can’t be done directly. What can be done though is to observe side effects from a click in the framed site such as the loss of focus on the framing site. After a click is registered, we can steal the focus back to observe the next click.
Now a multi-stage clickjacking attack involves these simple steps:
- setup the tiny div and iframe inside it, track the div under the mouse cursor at all times.
- position the iframe so that the part that should be clicked is in the div. The rest of the iframe overflows and can be ignored.
- whenever the framing site looses focus, assume a click was performed. Steal focus back, and reposition the iframe inside the div as seen in 2.
Limitations of the script
- the click-tracking mechanism sometimes catches false-positive clicks because some framed pages steal focus for non-click reasons. Currently, that means that the user has to click through the whole clickchain and restart from the beginning (hoping that none of the clicks eg redirected the user to a different page). In my experiences, not many pages steal focus, but when they do, the script becomes severely less effective.
- no overlay (yet). The problem with creating an overlay is that the original page ignores the click. So we can’t simply overlay a normal webpage, because a user would notice their clicks being ignored (at least if the clicks were meant to do something and not just nervous clicks). The framing page does know when a click was performed because of the loss of focus, and it knows where the mouse cursor is, so simulating clicks is certainly feasible.
Usage of the script
- While setting up the script, set
debug
to true so that the div and iframe are visible. - Set vulnerable URL as
victimURL
. - Get approximate positions for the clicks, eg using the Firefox “ruler” functionality and create preliminary clicks via
createClick
inclickChain
. - Reposition the iframe inside the div so that only the part that should be clicked is visible.
trackerDiv.setFramePosition(xPos, yPos)
can be used in the browser console for repositioning (this avoids the need to have to reload). The height and width of the div can be adjusted to make this part easier (trackerDiv.setHeight(200)
/trackerDiv.setWidth(200)
); in the end, it’s best to keep the div as small as possible. - Adjust the values in
createClick
in theclickChain
, setdebug
to false, and test the script.
Advanced Clickjacking Script
The script is available at github