Facebook has paid a researcher $33,500 for finding and reporting a critical remote execution bug.
Brazilian computer engineer Reginaldo Silva reported the issue to Facebook in November. The bug is tied to OpenID, an authentication standard that allows people to centralize the authentication process across multiple sites so that they do not continuously have to log in.
According to Silva, the find came out of work he had done previously.
"September 22nd, 2012 was a very special day for me, because it was the day I found a XML External Entity Expansion bug affecting the part of Drupal that handled OpenID," he explained in a blog post. "XXEs are very nice. They allow you to read any files on the filesystem, make arbitrary network connections, and just for the kicks you can also DoS the server with the billion laughs attack."
"I was so naive at the time that I didn't even bother to check if anyone else was vulnerable. I reported it immediately," he continued. "I wanted to start putting CVEs on my resume as soon as possible, and this would be the first (it eventually got CVE-2012-4554 assigned to it). Only five days later it occurred to me that OpenID was pretty heavily used and so maybe other places were vulnerable as well."
He reported the bug to Google, which awarded him $500 as a bug bounty.
"Well, I knew Facebook allowed OpenID login in the past," he blogged. "However, when I first found the OpenID bug in 2012 I couldn't find any endpoint that would allow me to enter an arbitrary OpenID URL. From a Google search I knew that in the past you could do something like https://www.facebook.com/openid/consumer_helper.php?openid.mode=checkid_..., but now the consumer_helper.php endpoint is gone. So for more than a year I thought Facebook was not vulnerable at all, until one day I was testing Facebook's Forgot your password? functionality and saw a request to https://www.facebook.com/openid/receiver.php."
"That's when I began to suspect that Facebook was indeed vulnerable to that same XXE I had found out more than a year ago," he continued. "I had to work a lot to confirm this suspicion, though. Long story short, when you forget your password, one of the ways you can prove to Facebook that you own an @gmail.com account is to log into your Gmail and authorize Facebook to get your basic information (such as email and name). The way this works is you're actually logging into Facebook using your Gmail account, and this login happens over OpenID."
This is where he got stuck. For his bug to work, the OpenID Relying Party – in this case, Facebook - has to make a Yadis discovery request to an OpenID Provider (OP) under the attacker's control. He made a request to https://www.facebook.com/openid/receiver.php that caused Facebook to perform a Yadis discovery on a URL under his control, and the response to that request would contain malicious XML
"I knew I had a XXE because when I told Facebook's server to open /dev/random, the response would never come and eventually a request killer would kick in after a few minutes," he blogged. "But I still couldn't read any file contents. I tried everything on the XXE back of tricks (including weird combinations involving parameter entities, but nothing."
After fixing a bug in his code however, he was able to get his attack to work.
"That's right, the response contained Facebook's /etc/passwd," he blogged. "Now we were going somewhere. By then I knew I had found the keys to the kingdom. After all, having the ability to read (almost) any file and open arbitrary network connections through the point of view of the Facebook server, and which doesn't go through any kind of proxy was surely something Facebook wanted to avoid at any cost."
He wanted next to escalate the bug to full remote code execution, but choose to follow the rules of Facebook's bug bounty program before going any further. After exchanging emails with Facebook, he went ahead with his plans.
According to Facebook, a short-term fix was live just 3.5 hours after Silva reported the bug.
"After debugging, we concluded that libxml_disable_entity_loader(true) was indeed the correct final fix," Facebook noted in a blog post. "Because we want to leave the code in a better state than we found it (rewrite old code, write tests, etc), writing the long term fix is often the step in the lifecycle of a bug that takes the longest. We wanted this line to run before anything else, so we put it in the lowest level of the callstack in our request initialization code."
"In the process, we came across another endpoint using the vulnerable code and ensured it was protected by the same Takedown rule we deployed previously, as well as our permanent fix," Facebook continued. "In parallel, other members of the Security team investigated the logs corresponding to this issue and confirmed that it had not been previously exploited or used maliciously."
"At this point, we wrote back to Reginaldo to applaud him for his file read vulnerability," Facebook added. "We discussed the matter further, and due to a valid scenario he theorized involving an administrative feature we are scheduled to deprecate soon, we decided to re-classify the issue as a potential RCE (remote code execution) bug."
The payout is the biggest one the social network has ever issued, the company said.