# How I bypassed Facebook CSRF Protection

Facebook AsyncDialog auto-attached a valid fb_dtsg CSRF token to a POST to an attacker-controlled show_dialog_uri path, enabling CSRF bypass to add emails and disable login approvals.

- Payout: $15,000
- Severity: high
- Program: Meta / Facebook
- Credited: Pouya Darabi
- Disclosed: 2015-09-04
- Write-up quality: 8/10
- Original: https://blog.darabi.me/2015/04/bypass-facebook-csrf.html
- Library page: https://bugbountylibrary.com/r/blog%3Ablog-darabi-me-2015-04-bypass-facebook-csrf-html
- Tags: domain:web impact:ato kind:bounty platform:blog sev:high tech:rest technique:incomplete-fix technique:param-pollution vuln:account-takeover vuln:auth-bypass vuln:csrf

**Target:** Facebook Ads Manager AsyncDialog flow (show_dialog_uri parameter)
**Root cause:** AsyncDialog built an internal POST to the path supplied in show_dialog_uri and automatically injected the valid fb_dtsg anti-CSRF token, letting an attacker direct an authenticated token-bearing request to arbitrary Facebook endpoints.
**Steps:**
1. Load `https://www.facebook.com/ads/manage/home/?account_id=XXXX&show_dialog_uri=/ads/manage/error/graydisabled/?account_id=XXXX` and observe the auto-generated POST containing fb_dtsg.
2. Rename the query param inside show_dialog_uri to `?aaaa=XXXX` and confirm the generated POST body/URL reflects the attacker-controlled parameter.
3. Point show_dialog_uri at a sensitive endpoint, e.g. `/settings/email/add/submit/[email protected]`, `/ajax/settings/security/approvals.php?just_enabled_approvals=0`, `/ajax/settings/security/sessions/stop_all.php`.
4. After the fix requiring prefix `/ads/manage/error/graydisabled/?`, bypass with double-encoded question mark `%253F` plus `../` traversal: `show_dialog_uri=%2Fads%2Fmanage%2Ferror%2Fgraydisabled%2F%253F%2F..%2F..%2F..%2F..%2F..%2Fsettings%2Femail%2Fadd%2Fsubmit%2F%3Fnew_email%3Dpouya%40darabi.me`.
**How found:** Noticed account_id appeared both in the requested URL and POST body, hypothesized the parameter was reflected into the internal request, then renamed it to confirm attacker control over the generated request path and params.
**Exploitation:** Attacker lures a logged-in victim to a crafted facebook.com URL; AsyncDialog fires an authenticated POST carrying the victim's fb_dtsg to the attacker-chosen endpoint, performing state-changing actions such as adding an attacker email (account takeover via recovery flow), disabling login approvals, or terminating sessions.
**Escalation:** Chained email-add with account recovery to reach account takeover; also disabled login approvals and killed sessions to lock out the victim.
**Insight:** When a feature auto-attaches an anti-CSRF token to a request whose destination is derived from a user-supplied parameter, that parameter is a CSRF-token oracle; test whether renaming/reflecting params into the generated request lets you retarget the token-bearing POST, and probe fixes for double-encoding (%253F) to escape prefix restrictions.
