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.
Back in October 2011 I found a clickjacking vulnerability at the Google main page http://www.google.com. At that time, they just introduced their new navigation menu at the top of the page. By clicking on the “Share” button, you can directly post to Google+. This functionality could be abused by an attacker to let victims unintentionally post to their Google+ profile. Since www.google.com didn’t defend against clickjacking at all, it was pretty easy to place the page in a frame and launch the attack. An attacker could let his victim post arbitrary text messages including spam and fishy links. But the really scary thing about this is that the attacker could even let the victim post his private photos taken with his android smartphone. The only prerequisite for doing this is that the victim uses the instant upload feature. I wrote a PoC which illustrates the attack. See the video below.
What the user sees:
Whats actually happening:
The vulnerability was reported to Google and was fixed by adding the HTTP Header X-Frame-Options. I got into the Google Security Hall of Fame under the section honorable mentions for reporting this vulnerability. Also visit Aditya Gupta’s blog, he found the same vulnerability on the subdomain translate.google.com.