3 ms·
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 mit
by mkjones 16y ago
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_page_mashups_%28UI_redressing%29 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?
- photon_off 16y agoFair 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.
- mkjones 16y agoI 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.
- photon_off 16y agoYou'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.