Sitemap

Account Takeover with OAuth Misconfiguration.

3 min readJun 10, 2025

--

Hello folks,

I’m matitanium, a security researcher working across multiple domain from web applications to Android security, and active in red teaming engagements. I love digging into authentication logic, hunting for creative bugs, and exploring overlooked corners of complex systems.

This one’s a fun ride, so let’s jump right in.

From 2 Click to ATO :D

Mindset: From Duplicates to Discovery

I spent two weeks testing this private bug bounty program. During that time, I submitted five different vulnerabilitie from HTML injection inside emails to XSS but unfortunately, all of them were marked as duplicates. The program had launched back in 2021, so most of the low-hanging fruit had already been picked.

It was a bit frustrating, but also a clear signal:
> It’s time to go deeper and smarter.

So I shifted focus to what often gets overlooked: authentication flows.

I started by digging into the login mechanics. Tried the usual suspects:
. Brute-force attacks? Tested. Nothing.
. Password reset flow? Looked clean.
. Session handling? Pretty standard.

Eventually, I discovered a section inside the account settings called Login Methods, where users could link external accounts via OAuth. The supported providers were:
- Apple
- Google
- Microsoft
- Facebook

Make program private if you know from UI

I tested them one by one.

Apple? No issues.
Google? Solid.
Microsoft? Nothing.
Facebook? Eh, probably secure too… so I skipped it.

Fast-forward two days later I came back, just to make sure.

> That decision paid off.

Discovery: The Subtle Behavior That Opened the Door

While observing the Facebook OAuth flow, I noticed something interesting:

When you click Add Facebook Account, the application silently sets a random session cookie in the browser. This cookie is essential for the OAuth flow to work.

Without it, the app rejects any response from Facebook.
But with it? Even if the user never completes the flow the app will still process a valid OAuth code, as long as that cookie is present.

And here’s the kicker:
> There was no state parameter used in the OAuth flow.
> No CSRF protection.
> No binding between the request and the user.

This meant one thing:
> If I could get a victim to click a crafted OAuth response URL while they had that cookie set I could bind my Facebook account to their profile.

Boom. Account takeover.

How It Works ?

1. User clicks Add Facebook Account → app sets a cookie
2. User closes the tab (doesn’t finish flow) cookie still stays
3. Attacker links their Facebook account to their own profile
4. Attacker intercepts the final callback URL:

https://[REDACTED]/Facebook/AccessResponse?code=...

5. Attacker sends this link to the victim (e.g., phishing, redirect)
6. Victim clicks → the app completes the flow using attacker’s code
7. Attacker’s Facebook gets linked to the victim’s account
8. Now attacker can log in via Facebook and they’re in.

Make program private if you know from UI

This vulnerability allows an attacker to:

- Hijack any account with minimal interaction
- Access personal or sensitive data
- Cause reputational damage to the platform
- Circumvent standard login protections

Even though the victim had not completed the flow, a crafted URL could silently connect their account to a Facebook owned by the attacker.

Fix Recommendations

To prevent this:
- Implement the state parameter in all OAuth flows
- Reject any callback that lacks proper session binding
- Validate origin and integrity of each OAuth request
- Optionally: tie Facebook codes to a user session using server-side state

Thanks for reading!

--

--

Responses (12)