Contents

The OAuth Happy Path Was a Lie: One-Click Account Takeover via Facebook

/images/blog2.png

The target in this case was a mainstream e-commerce platform with Facebook login enabled. While reviewing their OAuth integration, I noticed the flow relied on Facebook as the identity provider (IdP) — and that immediately triggered a reflex.

Whenever I see Facebook or Google OAuth on a target, I always test the Jayesh trick:

Remove the email scope during the social login → wait to see if the app lets you manually input an email after OAuth completes.

This technique fails 99% of the time — as it should — because most properly built systems only trust verified emails returned directly by the OAuth provider. But here, it didn’t.

If you’re new to OAuth or want a quick visual refresher, here’s a super simple diagram of how the standard OAuth 2.0 flow works (Authorization Code grant): 👉 View interactive diagram


TL;DR

  • Bug class: OAuth misconfiguration → full account takeover (ATO).
  • Attack cost: < 2 minutes, one throwaway Facebook account.
  • User interaction: Victim only clicks their own confirmation email – no phishing.
  • Reach: Any account whose email is ever unverified. Exploit is repeatable even after verification or address change (persistence).
  • Root cause: App relies on post‑OAuth self‑reported email, not provider‑verified email / UID binding.

Full Attack Narrative

Step Attacker Action Server Behaviour
1 Click “Login with Facebook” Redirects to FB OAuth
2 Uncheck email scope FB returns with no email claim
3 App asks for email → type [email protected] App stores email + temp token
4 App sends normal confirmation link to victim Victim inbox
5 Victim clicks (looks 100% legit) Email gets marked verified
6 OAuth flow completes → attacker receives session cookies Dashboard shows orders, PII, etc.

Choosing log-in with facebook:

/images/oauth-ato-1.png

We can see that we can change the scope selection:

/images/oauth-ato-2.png

Removing email:

/images/oauth-ato-3.png

Victims click verfication email been set to him, then ATO:

/images/oauth-ato-4.png

Raw Request/Response

After attacker supplies the victim’s email:

POST /oauth/facebook/email HTTP/2
Host: target.com
Content-Type: application/x-www-form-urlencoded

[email protected]

Server response:

HTTP/2 200 OK
Set-Cookie: session=…; Secure; HttpOnly
Location: /verify-email-sent

After the victim clicks the confirmation link:

GET /signin/term_accept/verify_email/abc123 HTTP/2

This results in:

→ 302 /dashboard  (already logged in as victim)

Persistence Check

  • Victim verifies email? Still owned.
  • Victim changes email/password? Still owned. The binding is FB UID ↔ local account; email no longer matters.

Business Impact

  • Full read/write access to personal data, order history, saved addresses, loyalty points.
  • Possible stored‑card misuse if “one‑click reorder” exists.
  • Highly automatable → credential‑less mass takeover campaign.

Root‑Cause

  • Trusting user‑supplied email after OAuth fallback.
  • No server‑side ownership check against existing unverified accounts.
  • Email confirmation endpoint doesn’t verify that the session requesting the send owns the address.
  • Persisted binding of FB UID to account without re‑verification on profile changes.

Takeaways

  • Always untick mandatory scopes in social logins.
  • Test both pre and post email verification states.
  • Re‑run after profile edits – persistence is an extra bounty line.

Timeline

Date Event
24 May 2025 Bug discovered during routine OAuth fuzzing
25 May 2025 PoC recorded; report filed
TBD Vendor triage / fix