I want to preface this post by noting that I have plenty of respect for the engineers at Facebook, and I realize they face many challenges maintaining the security of such a complex website. However, given Facebook’s current status and reach, I also think it important to keep the site accountable when it comes to issues that risk unwanted information disclosure or other problems for end users.
Facebook’s faced criticism for several security issues over the last few weeks. In April I reported on a vulnerability that allowed applications to be hijacked for stealing data or spreading malware. More recently, a glitch allowed users to spy on Facebook Chat sessions and problems with Yelp showed the risks of cross-site scripting in “instant personalization” sites.
Unfortunately, I have a few other holes to report. I first notified Facebook of these new issues last month, but I wanted to give time for patches before I published details on the problems. Facebook has since made several changes that address some of the issues I raised. However, some of the problems appear to remain. Given the updates and length of time since my reports, I decided to go ahead and post about these issues, but I’m withholding technical details on issues that are still active.
Weak Session Secrets
On April 19, I notified Facebook of a behavior I was observing in applications and Facebook Connect websites. Prior to the new OAuth 2.0 model, the required parameters for a Facebook API request included a session key (identifying the user’s session with the application) and a session secret (a code to verify the authenticity of the request’s source). If an application used an <fb:iframe> or <fb:swf> tag to load content from another domain (such as an advertisement), the request to the other site would include the session key, but not the session secret.
The problem I saw, however, was that the session secrets being issued were part of the session key. For example, suppose Facebook issued this session key: 2.sNXhV4G1ILRKkvdBHoIbTg__.3600.1271682500-00000000. The session secret would then simply be the first set of characters between periods: sNXhV4G1ILRKkvdBHoIbTg__. This meant that any site which acquired a valid session key could extract the session secret and make API requests. While harvesting the session key is not necessarily trivial, the code is passed around more freely than a session secret (such as the advertising example noted above) and vulnerabilities listed below could be combined with this behavior.
I’m not sure exactly when Facebook started issuing weak session secrets, but when I made the report I had observed several of them and tested that I could extract session secrets from session keys. After about a week, I once again saw session secrets issued that bore no relation to the session key, and I could no longer extract a string from the session key and use it to issue API requests.
Arbitrary FBML/FBJS on Facebook.com
On April 14, I noted an even more worrisome issue, and on April 29 I sent a similar problem using a different URI. In both cases, I’d uncovered a way to render arbitrary FBML/FBJS in the context of a facebook.com page without any typical UI chrome. Such a vulnerability presents a range of possible attacks.
First, this could enable the same sort of data harvesting I had demonstrated with the Facebook Platform vulnerability published last month. I could load a Facebook page that included inline frames pulling content from other websites. While <fb:iframe> did not appear to include the session secret in requests, it did include enough information to identify the current user, as well as the session key. Also, the <fb:swf> tag for loading Flash content did include the session secret as a parameter when loading content, even from other domains.
One could also combine the new OAuth 2.0 flow with this issue to harvest a user’s Facebook ID and access public information about them. Essentially, you could imitate the behavior of an “instant personalization” partner on any website, with or without notice. This happened because the OAuth redirect parameters allows facebook.com URIs.
Second, since the page would render on facebook.com, I could load other Facebook pages in iframes and they would not have clickjacking protection enabled. This would allow previously described clickjacking attacks to be launched once again.
Third, it was unclear to me if the vulnerability enabled some further application hijacking by a failure to check a parameter for cross-domain communications. This aspect could have been nothing, but I’ve not done enough testing to make sure.
Finally, the problem presents a dream situation for phishing. Once could easily load a convincing Facebook login form that sends the information to another server – and the URI for the page would appear to be on facebook.com.
Over the last few weeks, Facebook has altered these pages so that they no longer render all FBML or FBJS code. Specifically, iframes and Flash content will no longer work. This prevents many of the attacks described above, especially those that allow automatic data harvesting.
However, one can still render a range of code using these pages, including form elements. That means the phishing scenario described above is still an active possibility. To make matters worse, the parameters necessary to render code can be included in a POST request, meaning the URI in the user’s address bar for an attack page could be a short facebook.com address.
Below is a screenshot of this website loaded in the context of a facebook.com page using the original vulnerability reported on April 14. The second method uses a www.facebook.com page, resulting in an even shorter URI on the address bar.
This particular issue actually came from a Facebook feature that was implemented without much security. I knew that fixing it might take some time, since a number of developers depended on the feature involved. I’m glad that some of the threats have been removed, but more still needs to be done before this feature can be considered secure.
Update: Since this post I’ve found a third implementation of the feature, and this method provides an even shorter URI.
Update 2: It appears the feature involved in this FBML/FBJS issue was deployed in July 2008, so it’s quite possible the problems I noted in April have been active for almost two years.
Share with your friends!