Full Report
Facebook's payments and billing flows use third-party financial services providers. To perform these bank payments, Facebook embeds external services via iFrames that perform cross-window communication. One integration that exists is the ACH Direct Debt flow; this embeds a third-party iframe into m.facebook.com with strict origin verification. The cross-window message-handling mechanism allows direct HTML injection, which is assumed to be safe because it's from a trusted domain. The reality is that all messages originating from this domain were trustworthy. Practically, origin validation is only as strong as the security of the trusted origin. The handler for direct_debit_ach_initialization's learnMore event injects HTML directly into the DOM. This creates an XSS opportunity, if we can find more bugs. On one of the third-party providers, they found code that loads a remote configuration file via a URL and calls eval() on the cmd parameter. Since we can control a message from the third-party domain, we can communicate with Facebook to trigger the XSS sink. All it takes is a postMessage from the iFrame and we have XSS in Facebook! This is actually self-XSS because the endpoint has a nonce that is not guessable. So, how is this useful? With XSS on the page, it's possible to initiate the OAuth flow. By reading the iframe of the page with the OAuth flow for the user, it's possible to extract the OAuth codes from location.href of the iframe and compromise the account. Here's the full exploit chain: Login CSRF is used to get a valid account setup. Attacker loads the ACH page with the vulnerable third-party provider. XSS is triggered on the third party iframe that calls postMessage to get XSS on Facebook. Attacker initializes the OAuth flow in an iFrame to steal the OAuth codes. By itself, the XSS isn't bad enough to warrant an account takeover. So, they found some quirks to make this possible via the Save Login and the ability to keep a malicious page alive using Blob URL. Facebook has a GraphQL endpoint for account switching. With XSS on the site, this API can be called. By loading the payload via a Blob URL, Facebook cannot reload from the compromised execution context. So, the XSS remains persistent. If there are no device-switchable accounts, there's an additional way. Trigger a Google OAuth flow for Facebook. Capture the authorization code after the redirect to Facebook and use it to link the attacker's account to theirs. This works without user interaction but requires that only one Google account is open in their browser. To make the impact worse, third-party payment providers were able to execute arbitrary code within Facebook remotely. To target all users, it would have been simple for a threat actor to compromise these. After this bug, they were rewarded $62K. Great work!
Analysis Summary
# Vulnerability: Account Takeover via PostMessage Logic Flaw in Facebook Payments
## CVE Details
- **CVE ID:** Not Assigned (Meta Bug Bounty Program)
- **CVSS Score:** 9.0 (Estimated)
- **Severity:** Critical
- **CWE:** CWE-79 (Cross-site Scripting), CWE-449 (The UI Message Flow is Not Validated)
## Affected Systems
- **Products:** Facebook (m.facebook.com), Instagram, Workplace
- **Versions:** All versions prior to November 19, 2024
- **Configurations:** Systems utilizing the ACH Direct Debit payment flow and third-party financial service integrations.
## Vulnerability Description
The flaw exists in the cross-window message-handling mechanism used by `m.facebook.com` during the ACH Direct Debit initialization flow. Facebook embeds a third-party iframe (`ThirdPartyPaymentProvider.com`) and listens for `postMessage` events.
While Facebook performs origin verification, it fails to sanitize the data payload. The handler for the `learnMore` event unsafely injects attacker-controlled HTML directly into the DOM. By chaining this with a weakness in the third-party provider (which allows remote configuration loading and execution via `eval()`), an attacker can send a malicious `postMessage` from the trusted origin to trigger XSS in the Facebook context.
## Exploitation
- **Status:** PoC available (demonstrated by researcher)
- **Complexity:** High (requires multi-stage chaining: Login CSRF -> Third-party XSS -> Facebook XSS -> OAuth Hijacking)
- **Attack Vector:** Network
## Impact
- **Confidentiality:** High (Full access to user account data, OAuth codes, and session tokens)
- **Integrity:** High (Ability to modify account settings, link attacker accounts, and execute actions as the user)
- **Availability:** Medium (Persistent XSS via Blob URLs prevents execution context reloads)
## Remediation
### Patches
- **Meta (Facebook/Instagram):** A server-side patch was deployed on November 19, 2024, to sanitize incoming `postMessage` data and harden the `billing_interfaces` endpoints.
### Workarounds
- There are no viable user-side workarounds other than avoiding the specific "ACH Direct Debit" payment flow on mobile browsers while unpatched.
## Detection
- **Indicators of Compromise:**
- Unexpected redirects to `m.facebook.com/billing_interfaces/direct_debit_ach_initialization`.
- Presence of malicious scripts originating from `blob:` URLs in the Facebook context.
- Unauthorized OAuth authorizations for Facebook/Instagram apps.
- **Detection Methods:** Security teams should monitor for anomalous `postMessage` traffic originating from third-party iframes that contain HTML-like strings or script tags.
## References
- **Researcher Blog:** [https://ysamm.com/](https://ysamm.com/)
- **Target Endpoint:** `https://m[.]facebook[.]com/billing_interfaces/direct_debit_ach_initialization`
- **OAuth Callback:** `https://business[.]facebook[.]com/business/loginpage/igoauth/callback/`