Of course, compared to other attack vectors the threat imposed by Clickjacking is rather low. Right? … Not quite. Clickjacking can be a scary beast, which the following attack depicts.
Paypal recently launched a facebook app to send money to your Facebook friends. The app is embedded via an iframe in the usual Facebook UI and the whole process of sending money happens within the Facebook UI … or should at least.
How it takes place
The app is located at http://apps.paypal-sendmoney.com/paypal_sendmoney. It seems like the developers were aware of Clickjacking and deployed some defenses. Opening the URL directly in the address bar yields a 302 HTTP status code and forwards to http://apps.facebook.com/paypal_sendmoney/. So it’s not as easy as putting the URL in an iframe’s
src-attribute. Let’s see how Facebook delivers the app:
Facebook inserts a token called
signed_request and delivers everything to the client. As you can see from the markup above a form is utilized to send a POST request to http://apps.paypal-sendmoney.com/paypal_sendmoney and the response is loaded into an iframe. Note that the token
signed_request is send along with the request. Depending on the value of
signed_request the app’s web server decides whether to send the actual app or forward to http://apps.facebook.com/paypal_sendmoney. This should prevent framing from untrusted third parties.
And here is the vulnerability: There is no check if the user who’s requesting the token from Facebook is the same as the one requesting the actual app using the token. An attacker can request the token from Facebook, extract it and let another user request the app using the previously loaded token. Thus, the attacker is able to embed the app in an iframe and doing some tricky Clickjacking stuff. I’ve implemented a PoC, have a look here:
The attack works with any browser. The user has to be logged in to Facebook and the sendmoney app.
One might say “Ok, it’s a bug, just fix it” but this scenario shows the limitations of current client-side defenses against Clickjacking (see X-Frame-Options and Framebusting). Those defenses deny framing from foreign origins completely, but in this case certain pages should be able to frame while others are not. Paypal doesn’t have any other choice as coming up with a custom server-side solution like the one shown here. And, as often with custom solutions involving multiple parties, they are error-prone. Clickjacking takes place in the user’s browser, and I think this is where it should be circumvented. To fend of Clickjacking a standardized client-side mechanism is needed that allows to whitelist certain origins (and by the way: reducing clickjacking to invisible iframes doesn’t work, see here and here). To date, there is no such mechanism but new drafts of the HTTP Header Frame-Origin and From-Origin Header are looking promising.
The vulnerability was reported to PayPal and is fixed.