Multiple bugs chained to takeover Facebook Accounts which uses Gmail ($44625 USD)

We discussed this vulnerability during Episode 145 on 16 May 2022

A chain of bugs starting with a “third party” information disclosure, and leading to an account takeover. The third-party aspect can be argued but as a vuln classification it feels like the best fit for the root of this issue.

Starting off, the issue is within Facebook’s Checkpoint system. Kinda like a captive portal for a web-application. Make any request to Facebook, and it gets redirects to Checkpoint if the account is in a state requiring it like MFA, temporary ban enforcement, or for this issue, displaying a captcha before the user can continue to use Facebook.

On the Captcha page, an iframe is loaded to display the captcha. This iframe’s URL points to Facebook’s Sandbox domain, and has a parameter referer which contains the URL for the page hosting the iframe. As Checkpoint pages may include a next parameter used to indicate the original page the user tried to access (and where to go after the Checkpoint has been completed). This next parameter can leak potentially sensitive information, if for example a user were redirected to the Checkpoint following an Oauth flow, the code for that user may be exposed to the Facebook Sandbox

Despite this cross-context leak it is not yet usable by an attacker. They would still a couple things:

  1. They need to be able to read that URL somehow, the iframe is not a page they control, nor is the page loading the iframe. To do this the author started off by finding an XSS within the Facebook Sandbox domain. This was effectively a non-issue as there was a intended feature for developers to upload HTML files and have them served within the sandbox. This places their malicious code in a similar context to the target information.

For this attack, if you could have an iframe with attacker controlled javascript in the Facebook Sandbox on the same page as a iframe containing the Facebook Checkpoint. The attacker iframe, would be able to go through the window.opener to access the parent page, then access its iframes (the Checkpoint iframe), and since they are on the same domain, it would be able to read the location.href of the iframe inside that Checkpoint frame. I’ll admit this setup is a little-bit confusing and I’m not 100% sure I’ve got it right, but the author got it to work, so trust the process I suppose.

  1. Most accounts will not be redirected to the Checkpoint system so an attacker would need a way to target users and get them into the Checkpoint. For this, the fact that the Login and Logout systems were CSRF-able was used to log a victim out of their own account and into the attacker’s account which would be in the Checkpoint state.

Putting everything together you’ve got your attack page with two iframes, one pointing to the Facebook Sandbox and the other we will call target.

  • Logout the victim using the Logout CSRF
  • Login the victim to an account that will be redirected to the Checkpoint using the Login CSRF
  • Have the target frame open the Google OAuth flow. – As the victim should have already approved the Facebook app, they should almost immediately be redirected back to the Facebook oauth reciever with the code parameter.
  • Checkpoint will catch this request, and redirect them
  • The Checkpoint page will load the Facebook Sandbox iframe with the code as part of the referer parameter.
  • The attacker can then try to read the target.frames[0].location.href and get the code from the URL.