Security researcher Stephen Sclafani discovered a massive API-based security vulnerability at Facebook. Facebook rewarded him with $20,000 and fixed the years-old problem within hours.
Facebook's security mistake is one from which all API developers can learn. Most Facebook users were vulnerable to spying, spamming and hacking because of lax security on an old API. Sclafani's story of how he discovered the API's security flaws and a great explanation of the technical details can be read on his Facebook security research blog. The Facebook API bug is summarized below.
Facebook's Legacy API Security Vulnerability
Facebook had left its original "REST API" active internally, closed off from the Internet but still accessible to Facebook's own servers.
The company's "Facebook Mobile" application still communicated with this legacy REST API server, to maintain backward compatibility.
Facebook Mobile is a powerful internal application that has access to most of Facebook's user accounts, because it powers the Facebook platform on their phones. Facebook Mobile has permission to access users' data, post to their feeds and send messages to the users as "Facebook."
Sclafani used a proxy REST endpoint available via a live URL to access Facebook's original REST API. POST requests could be sent to "touch.facebook.com/api," a mobile web address used by Facebook. Sclafani discovered that these requests were then relayed to "api.facebook.com/restserver.php"—the URL of Facebook's original REST API, which was fully deprecated and was not supposed to still be accessible to third-party Facebook apps.
Any Facebook app could exploit this vulnerability.
It gets worse.
Facebook did not use proper authentication to secure internal communications between these two APIs. Sclafani used this second vulnerability to hijack Facebook's internal Facebook Mobile application. Sclafani should only have been able to use his proxy API attack on the accounts of the users who had installed his Facebook app. Facebook apps can only access their own users; that is is the way Facebook app permissions were designed and how they still work. However, the original REST API could be tricked into thinking requests came from the Facebook Mobile application itself. Instead of requiring session IDs that proved that a user had granted permissions to a specific third-party Facebook app, the REST API happily accepted API calls as if they were coming from Facebook Mobile. And Facebook Mobile could access most accounts on Facebook.
Facebook's legacy REST API made available powerful API methods: "stream.publish" wrote posts to the News Feed and Timeline, and "users.setStatus" updated a person's profile status. In other words, this hack made it possible write to anybody's profile on Facebook, and then friends would see it in the person's stream as if those posts and updates were coming from that user's phone. The "message.getThreadsInFolder" gave access to every message a user had sent on Facebook, and "users.getInfo" returned lots of information, including email addresses.
The privacy and security implications are staggering.
Spies, spammers and hackers could gain control of user accounts without interacting with users directly. Private communications could be monitored. Personal information could be used to guess account passwords. Facebook messaging channels could be used trick friends into clicking on malicious links. Posts in the News Feed could be used to spread spam. The list of potential problems is endless.
The severity of the security problem is evident by how fast Facebook fixed it. Here is Sclafani's timeline for Facebook's response:
April 23, 4:42 p.m. – Initial report sent
April 23, 5:50 p.m. – Request for clarification from Facebook
April 23, 6:08 p.m. – Clarification sent
April 23, 6:49 p.m. – Acknowledgment of issue by Facebook
April 23, 7:38 p.m. – Notification of temporary fix by Facebook
April 23, 8:39 p.m. – Confirmation of temporary fix sent
April 29, 11:03 p.m. – Notification of permanent fix by Facebook
April 30, 12:58 a.m. – Confirmation of permanent fix sent
April 30, 8:35 p.m. – $20,000 Facebook Bug Bounty awarded
Lessons for API Developers
Facebook's REST API was not RESTful, despite Facebook's naming convention for it. Method calls were buried inside POST request parameters made to a just a single API endpoint: "api.facebook.com/restserver.php." This could explain why a security problem with so much breadth and depth could go unnoticed for so long.
API developers and enterprises should remember to fully turn off deprecated API functionality. Facebook does know the importance of this; it recently showed its willingness to completely deprecate past APIs, even if it breaks apps in production. ProgrammableWeb covered how Facebook's new Graph API v2.0 will replace Graph API v1.0 functionality. Facebook apparently forgot to turn off or properly secure its legacy REST API after the Graph API launched in 2010.
Facebook's API servers trusted each other too much. Because API requests were supposed to be internal, Facebook did not use the same level of security it uses when working with external developers. Also, this REST API was a product that had worked for years. Facebook must not have had the same level of security focus on its old API as it did on its newer ones.
Apparently Facebook never discovered any spies, spammers or crackers using this exploit, given that it was fixed within hours.
One has to wonder what nefarious uses of this bug might have been happening worldwide, all published "via Facebook Mobile"...