# Insufficient OAuth callback validation which leads to Periscope account takeover

Periscope's OAuth callback locking accepted path-only callback_urls, so path traversal plus a Twitter open redirect leaked the OAuth token and allowed Periscope account takeover.

- Payout: hidden
- Severity: high
- Program: X / xAI
- Found by: filedescriptor
- Disclosed: 2019-04-10
- Write-up quality: 9/10
- Original: https://hackerone.com/reports/110293
- Library page: https://bugbountylibrary.com/r/h1%3A110293
- Tags: area:web domain:web impact:ato kind:bounty platform:hackerone sev:high tech:oauth technique:chained technique:reverse-engineering vuln:account-takeover vuln:auth-bypass vuln:open-redirect vuln:path-traversal

**Target:** OAuth callback validation in Periscope mobile app / Twitter OAuth flow
**Root cause:** Periscope's callback locking only checked the protocol of callback_url and assumed a complete URI; a path-only value like `a/../home` passed validation and allowed path traversal to any Twitter path.
**Steps:**
1. Reverse engineer the Periscope mobile app to recover the embedded Twitter consumer_key and consumer_secret.
2. Use the key/secret to generate a request token.
3. Set callback_url to a path-traversal value such as `a/../../login?redirect_after_login=https://cards.twitter.com/card_id`.
4. Create a Twitter ads generation card whose fallback URL points to attacker-controlled site, yielding a cards.twitter.com URL that passes the *.twitter.com whitelist.
5. Send victim a tweet containing a player card with the payload so the OAuth flow triggers automatically.
6. Victim is redirected to the open redirector, then to attacker site with `#&oauth_token=...` in the fragment.
7. Attacker exchanges the stolen oauth_token for an access_token and logs into the victim's Periscope account.
**How found:** Noticed Periscope's callback locking only forbade certain protocols rather than requiring a full URI, hypothesized a path-only callback_url would pass, then searched for an open redirect on Twitter and found the ads generation card fallback URL as a *.twitter.com redirector.
**Exploitation:** Attacker recovers embedded consumer key/secret, generates a request token, and crafts a path-only callback_url that traverses to Twitter's login redirect_after_login endpoint pointing at a cards.twitter.com generation card that redirects to attacker's site. Victim authorizes (silently if previously logged in via Login with Twitter), token lands in the URL fragment on attacker's site, attacker exchanges it for an access_token and takes over the Periscope account.
**Escalation:** Chained OAuth callback validation bypass with a Twitter open redirect (via ads generation card fallback URL) and Login with Twitter auto-authorization for a stealthy, no-interaction takeover.
**Insight:** When an OAuth callback allowlist checks only scheme or host, try path-only or relative callback_url values with `../` traversal to reach other endpoints on the trusted host; then hunt for any open redirect on that host (including ad/card fallback URLs) to exfiltrate the token via the URL fragment.

## Proof of concept (copied exactly from the original report)

**PoC tweet with embedded player card payload**

```
Go to https://twitter.com/attackerfoobar/status/686936815945789440
3. Wait for a moment
4. Your Periscope account will then be renamed as "Pwn3d"
```

**Callback URL path traversal to open redirector**

```
callback_url = a/../../login?redirect_after_login=https://cards.twitter.com/card_id
2. https://cards.twitter.com/card_id
3. https://attacker.com
```

