Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Facebook Vulnerability: Like Clickjacking (erickerr.com)
48 points by erickerr on July 13, 2010 | hide | past | favorite | 25 comments


This is Matt Jones, an engineer on the site integrity team at Facebook. We're the ones who address issues like this one on Facebook.

Ultimately clickjacking / UI redress is a browser vulnerability - it shouldn't be possible to display one thing and have another receive user interactions. As some people have pointed out, Firefox's NoScript plugin does a pretty good job of preventing it. But that isn't to say victim web sites shouldn't do anything about it.

In the case of Like buttons, they inherently run in an iframe so our protection on the rest of facebook.com (http://theharmonyguy.com/2010/03/13/facebook-adds-code-for-c...) can't apply. However, Facebook knows the urls these buttons point to and generally knows or can infer the urls where they are embedded. When we detect a likejacking site on one of these urls, we block its url or domain from being liked and prevent future clicks on facebook.com from going to it.


Hi Matt. First off, thank you for coming forth to make a statement about this vulnerability. It's nice to see that fb is responding to these incidents, and since you care, I'll work with you to solve the problem.

But first, let me express how disconcerting I find it for facebook to "pass the buck" on the blame of this vulnerability. It's not a browser vulnerability to have personal information be shared by implementing a "1 click publishing" button via a cross-domain iframe that (often times unknowingly) has a user logged into another site -- it's a privacy vulnerability that you need to take care of. As of late, I see no way that I can disable "liking" stuff, and I'm aware of the vulnerability, so I stay logged out of Facebook as often as I can.

It's facebook's decision to use an iframe, to publish content to user's news streams in 1 click, and to allow any website to implement the like button. It's your decision in spite of knowing that the means of doing so are open to "vulnerabilities" such as linkjacking. I put "vulnerability" in quotes because it's not really a vulnerability, now is it? It's a fundamental possibility based on how HTML works -- links can be invisible! Calling "linkjacking" a vulnerability is like calling tracking pixels, sessions in URLs, or anything that can be used for ill purposes, a "vulnerability" that browsers need to take care of. I'm not buying it. It's part of the design of HTML and you need to work with it.

You could easily remedy the situation by ensuring the user really means to publish something. However, I realize you aren't going to change anything about the "liking" process because it will disincentivize publishers from including it if it's not as effective. Business first, I understand.

Luckily, I will share with you, for free, how to fix this issue.

You can detect whether or not an iframe is being invisibly dragged by polling the cursorX and cursorY (which are relative to the browser window itself, not just the iframe) in conjunction with whether or not the user's mouse is over the "like" button (simple onmouseover/onmouseout).

If the user's mouse is over the "like" button even as X and Y dramatically change (optionally, over some unit of time) then the iframe is being positioned according to the mouse movements. A click on the "like" button should be disabled, and you should discretely notify your server that the URL/domain is suspect.

If the attackers were smarter, they'd position the "like" button below the mouse only on an onmousedown event so that your detection script wouldn't catch on to the one sudden movement of the "like" button in time for when the user lifts the button of their mouse.

But, luckily, you'd have me to tell you to ensure that both onmousedown and onmouseup are fired before actually having the "like" button signal a click.

So, there you have it. A free solution to your problem. That worked out much easier than posting a puzzle on your jobs page and waiting for people to solve your problems that way.

PS: For some reason as I read my post I realize that I come off as quite arrogant and perhaps a bit angsty. I apologize for that... it's almost embarrassing. I think it's just really late and I felt like being really frank about the issue. At any rate, you guys should hire me.


The idea of detecting if X and Y are changing while the cursor is over the button is a good one and actually something we thought about. While it does help mitigate the case where the attacking site dynamically moves the iframe, it's relatively easy to position the like button statically and just trick the user into clicking on its particular location, which would bypass this strategy (albeit at the cost of a slightly lower clickthrough rate). So I don't think this is a robust enough fix.

I think it's reasonable to say that clickjacking / UI redressing attacks are a browser bug - it's addressed in Google's browser security handbook: http://code.google.com/p/browsersec/wiki/Part2#Arbitrary_pag.... But regardless - we as a victim site are mitigating the problem.

Do you think there's a better way to offer the one-click liking experience without an iframe?


Fair point about the statically placed and baited frames. Well, detecting X and Y would solve the movable case of this, so that's better than nothing.

After reading that handbook link, I'd agree that it is very reasonable to consider it a browser bug. I suppose I considered it more of an oversight in terms of iframe specifications, and now am more sympathetic to your situation.

I'm not sure there's a better way to offer a one-click liking experience. If I'm not mistaken, you have two options: more than 1 click, or be vulnerable to these attacks.

Personally, I'd use the feature more if it behaved the same way that pasting a URL into my status does. In this case, it would be 1 click to open some sort of floating dialog (or a small window like in fbConnect), and another click to change the title, add a description, or just click "ok".

... pause for 10 minutes ...

Perhaps this might be a solution. An embedded javascript (sourced to your server) returns a code with a unique key for that user/URL combination (along with whether or not they have already pressed it), stored in javascript in a private data structure (an anonymous function, for example). You then embed whatever HTML you need to display your button onto that page, along with code to ensure it is being intentionally clicked. On click, you load another js file, where the unique key is passed via the get parameter. Your server will process the like, and this file will return the javascript to set the button as depressed, or to request the user login, or whatever.

The reason that the key is stored in an anonymous function is so the host URL cannot retrieve this bit. Otherwise, they could simply call the second js file to automate the user "liking" their page. The calls to your js file, however, still allow you to get the user's session data. And, of course, you can execute JS on the host's end to ensure that the click is legitimate..

Is this flawed? What do you think?

Edit: I just realized that "legitimate click detection" would be very involved. But, still possible.


I think that in the current state we have pretty robust protection against these attacks. If we see people bypassing it, we'll have to change our tactics :-).

Both of your suggestions are good, but require us being able to run javascript on the embedding (parent) page. (To have a floating dialog, we need more than a small iframe, and both this and a full pop-out go against the 1-click nature of things.)

While we could do the sort of elementAtXY trickery you suggest in the case of sites running our javascript, it's also possible to use the like widget just as an iframe, which breaks anything that requires that the parent site is running our js.

Even assuming we have parent-page js running, we'd also have to avoid anything that requires a (high-latency) roundtrip to fb servers just to verify if a click can happen, as this makes for a very bad user experience for those on slower connections. I think that could be avoided by generating and sending the user-url key to the fb javascript in the parent page as you describe, and communicating that to the like button iframe when it's being clicked (after determining that it's not hidden) by setting it in a fragment on the iframe, having the iframe grab it from that fragment, and pass it along for verification on the server. Though I don't know how the parent frame would be able to know when a click was happening in the iframe, since only the iframe contents would receive the onclick, not anything the parent page's dom... Regardless, it's a moot point because the bare iframe can't be protected this way.


You're probably right. It's easiest just to investigate any alarmingly high impressions:liking ratio and see if something phishy is happening.

Then again... the fact that I could unwillingly goatse all of my contacts (even if you prevent it from happening to too many people afterwards) makes me not want to stay signed in, at least until I can opt out of "liking" things.

It's late and I'm going to sleep... I'll reply in full tomorrow. Specifically, I think requiring javascript might not be that much of a detriment, especially if it alleviates any possibility and concern of fb getting embarrassed by a surge of clickjacking attacks.

As per the user experience concerns... the js solution wouldn't result in any worse UX for slow users than the iframe currently does. Either way, it's 1 round trip request needed to display the button, and 1 round trip request to ensure the button click goes through. In your case it's a round trip to load the iframe, a round trip once it's clicked. In my case, 1 round trip to get the JS, which displays the button, and 1 round trip to send the click event (the changing of the button can be client side and appear instant).

The main concern with a non-iframe solution is that the host page can really try to screw with your button.. you'd need to make it an image and ensure it's being displayed correctly (correct size, correct src, etc). But, again, I think it's entirely possible with not-too-much code.

Alright, I'm going to sleep for real.


It seems I can't reply to your post (max HN thread depth = 5?), so I'll do it here...

I believe the like:impression ratio for clickjacking sites isn't different enough from the (noisy) norm to make it a usable metric for identifying malicious sites.

We should detect clickjacking sites before you get a chance to goatse your friends. I'm pretty sure our the current state of things does that. At least in Firefox, you always have the option to disable third party cookies, which will disable the like button along with a slew of other, much sketchier, stuff that ad networks and the like tend to do.

You're right that it's possible to do the cross frame stuff without an extra ui-stalling roundtrip - that's what I meant to describe in the above post. I think the bigger issue in this case is determining in the parent page when a click is happening so you can determine if it's legitimate.

I don't believe it's possible for the parent page (or fb's javascript in the parent page) to screw with the button in the iframe - cross-domain policy forbids any access to its dom.

EDIT: Also, in case it wasn't clear, as soon as we identify a domain or url to be bad, it's impossible to reach it via any click on facebook, so even if something becomes bad after people have liked it, we still retroactively protect users. So as long as we've detected that something's bad, you can't accidentally goatse your friends with it even if you do get in a like before we identify it to be bad or before it turns bad.


I am pretty sure the users will come after facebook for the bug and not IE or firefox.

It seems making the like button an iFrame is not the best idea coz of this bug.

I don't go around submitting stuff to reddit/digg/HN/Twitter when I click somewhere on some site, so why facebook?


Since the browser behavior existed before Facebook implemented this feature, the responsibility is Facebook's.


http://vinhboy.com/blog/2010/05/31/facebook-man-with-the-big... I also wrote about this like 2 months ago, and they still haven't done anything about it...

=(. Facebook CTO guy, are you around today?


Yes, I am here, and so is someone who is more knowledgable than I am: http://news.ycombinator.com/item?id=1513470


I'm not sure if this is even possible to fix, given the same-origin policy on iframes. Facebook can't tell where the iframe is placed on the page, and I don't think they can tell if it's 'position:absolute'd. It's a tough problem.


Without testing, I suggest maybe making the iframe do an "alert" -- "Are you sure you want to Like this page?"

One more step, a lot more security.

Or at the very least make it easier to find things that you have liked ( I am speaking without actually going to look if its easy to find it... I just remember it was very hard to find the last time I tried )


Alert boxes tend to be horrible in terms of usability, but it is the only way to actually require a second step, since anything else you do will be constrained to the iframe and you can just clickjack a second time.

I think the solution they'll end up implementing (if they do anything) is an "I didn't Like this" link that users can click to report false clicks. If a company gets more than x% of those they get taken down. It's not a legit solution but should be fairly effective.


They can change the like to a 'pending like' and confirm it next time you check facebook.


And for "trusted" fan pages they could automatically bypass that.


Yes, but perhaps this is a sign of iframe abuse on the part of Facebook and the 3rd party site developers? Placing blame on the browser is pretty lame.

The solution to this problem is to not mislead users by embedding one domain's content within another site in the first place.


Sadly, you're right that there isn't a known solution to this yet. If you see my post below, it shows how even if they weren't in an iframe, there are still ways around current framebusting techniques.


My other post describes the fix. I don't have a fancy blog to put up a demo, though.


I'm happy to upvote your comment. This is way old news, its funny because even my tech friends are getting ensnared by it.


Items like this will always be a never ending battle. Each time one side has to update their technology to stop something from the other they normally must gain more authority from the other. In the case of Facebook that will be asking for more rights into each website that wants to use the 'Like' button and with the recent privacy issues this will just kick the hornets nest all over again.


I see it as a battle between "the browser is a reliable tool for reading and navigating documents on the web" and "the browser is just another UI toolkit for trusted desktop applications". It can't be both, because any seamless UI will always be powerful enough for untrustworthy code to find other malicious tricks like this.


Unfortunately, the twitter clickjacking attack still isn't fixed. See http://seclab.stanford.edu/websec/framebusting/index.php for an overview of how that type of defense still can be defeated.


Its especially bad because of the way profile pages are organized. When you're viewing your own profile wall posts and status updates float to the top, while Likes, new friends, and other such ambient updates are further down. However, other people see the Like front and center on their News Feed.

I noticed this after several friends were liking "10 WORST construction mistakes", or similar. I asked several about it, and none of them had any idea it had happened.


Anything in an iframe or under an iframe is susceptible to clickjacking. Firefox + NoScript does a pretty good job of preventing this.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: