I’ve decided to share one of my favorite flaws in facebook.com. This flaw essentially let me take over any Facebook account. To do this, I had to steal unique access tokens that grant me full access over the accounts. To be clear, the victim’s account does not need to have any installed apps for this to work. The bug works on every browser.
In order for me to exploit this flaw, the victim only needed to visit a particular webpage.
OAuth is used primarily to facilitate communication between Apps and Facebook users. Generally users need to allow the application to gain access to their account before communication can really begin.
Facebook applications generate a number of different access or permission warnings.
Diamond Dash and Texas Hold’em Poker are only allowed to post basic information on the user’s wall.
I discovered a way to gain full access to the user’s account (i.e. gain the ability to read inbox/outbox, manage pages, see private photos, etc.) even if they have not installed a single app. With this flaw, there is also no “expired date” for the token. The token in my attack never expires unless the victim changes their password.
The URL of the OAuth dialog looks like this:
All applications on Facebook have different “app IDs.” For instance, Diamond Dash is designated as “app_id=2” while Texas Hold’em Poker is “app_id=3.”
The next and redirect_uri parameters (next=, redirect_uri=) only allows the owner app domain. Thus, “app_id=3” belong to Texas Hold’em Poker and the “next” parameter will only allow the zynga.com domain (next=http://zynga.com). But, if the domain is different (e.g. nirgoldshlager.com) in the “next” and “redirect_uri) parameters, Facebook will not allow this action to be performed.
Facebook links up your app_id and the next parameter. They also send an access token through GET request to the owner application after the user permitted access. Now that we’ve got a dea of how Facebook OAuth works, let’s take a look at my findings. I thought over my options and I wondered if I could redirect the application OAuth request to a different “Next” URL. I first tried to change the “next” parameter to a different domain, but they blocked that action. Then, I attempted to change the “next” parameter to the actual facebook.com domain, but, again, I was thwarted with a general error message.
I discovered that subdomains (a la xxx.facebook.com) will permit this action, but trying to access folders or files in x.facebook.com (x.facebook.com/xx/x.php) will result in a block from Facebook. Then I noticed that facebook.com uses a Hash sign and an exclamation point in their URL (x.facebook.com/#!/xxxx). So, I attempted to carry out this action in the “next” parameter (next=x.facebook.com/%23!/). But, Facebook blocked me yet again! Then I tried to put something in between the hash sign and the exclamation point (%23x!), and Facebook let this action through.
It seemed as though there was Reg-ex protection.
If we use something like this—(https://beta.facebook.com/#xxx!/messages/)—then the action won’t treat it in the same way as it might with the hash sign and the exclamation point. It will also not redirect us to the message screen. I needed to find a way around it so I just started to fuzz characters in between the exclamation point and the hash tag so that my browsers (IE, Chrome, Safari, and Firefox) treat it like the actual symbols: #!.
Now, for the fuzzing!
%23~! (Works on all browsers)
%23%09! (Works on all browsers)
So, I was then able to redirect the victim to any files or directories in any Facebook subdomain. After that, I created a Facebook application that redirects the victim to an external website used for collecting the access_token of the victim.
For Example: (Zynga Texas Holdem OAuth Bypass):
Using the “next” parameter will redirect the user to my Facebook application (touch.facebook.com/apps/testestestte). My Facebook application will then redirect them to files.nirgoldshlager.com where the victim’s access_token will be saved in a log file (files.nirgoldshlager.com/log.txt).
Amazing! I am now able to steal access tokens for any Facebook application.
In order for the attack to be successful, the victim needs to use a Facebook application (e.g. Diamond Dash, etc.). These apps really only have basic permissions. Luckily, we can change the scope of those permissions by setting a new permission. Unfortunately, this method is not that powerful as the victim still needs to accept the terms of the new permission.
I wanted to be able to gain access to inbox/outbox, ad management, photos, videos, and everything else on the victim’s account without the victim having to install an application.
So, I started to think. How is this possible? What if I used a different app_id? Maybe I can use the app_id for Facebook Messenger, for example. Do users need to actively permit the Facebook Messenger app within the contexts of their Facebook account?
Facebook has built-in applications with terms that users never need to accept. These applications have complete access to any account. The access_token also never expires in Facebook messenger.
The access_token only expires when the victim changes their password, but that almost never happens.
PoC (Works on all browsers and doesn’t require an installed application on the victim’s account):
The Facebook Security Team repaired this bug.
Full description of permission for Facebook messenger app:
ads_management create_event create_note email export_stream manage_friendlists manage_groups manage_notifications manage_pages offline_access photo_upload publish_actions publish_checkins publish_stream read_friendlists read_insights read_mailbox read_page_mailboxes read_requests read_stream rsvp_event share_item sms status_update video_upload xmpp_login
This also works on 2-step verification accounts. But, when it comes to the access_token, the 2-step verification will fail.
Cya Next time!