# [oauth token leak] at oauth.semrush.com

Semrush OAuth success page postMessages the authorization code to any opener origin, letting an attacker site steal OAuth codes and exchange them for victim tokens.

- Payout: hidden
- Severity: high
- Program: Semrush
- Found by: nikitastupin
- Disclosed: 2018-04-17
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/314814
- Library page: https://bugbountylibrary.com/r/h1%3A314814
- Tags: area:web domain:web impact:ato impact:data-leak kind:bounty platform:hackerone sev:high tech:oauth technique:source-review vuln:account-takeover vuln:auth-bypass vuln:info-disclosure

**Target:** OAuth authorization endpoint oauth.semrush.com/oauth2/success
**Root cause:** The OAuth success page calls opener.postMessage with targetOrigin '*' and no origin check, so any site that opened the popup receives the full redirect URL containing the authorization code.
**Steps:**
1. Host `postmessage.html` on attacker.com that opens `https://oauth.semrush.com/oauth2/authorize?response_type=code&scope=user.info,projects.info,siteaudit.info&client_id=seoquake&redirect_uri=https%3A%2F%2Foauth.semrush.com%2Foauth2%2Fsuccess&state=636e7bae-22ed-407d-8d62-1d49b49ec962` and registers a `message` listener.
2. Victim (logged into www.semrush.com) visits attacker.com/postmessage.html and clicks 'Approve' on the SEOquake consent page.
3. The success page runs `opener.postMessage({ type: 'semrush:oauth:success', url: location.href }, '*')`, delivering the code to attacker.com.
4. Attacker POSTs to `/oauth2/access_token` with `client_id=seoquake&client_secret=...&grant_type=authorization_code&code=[CODE]&redirect_uri=https%3A%2F%2Foauth.semrush.com%2Foauth2%2Fsuccess`.
5. Response returns victim `access_token` and `refresh_token`.
**How found:** Noticed the success page's postMessage used targetOrigin '*' with no opener origin validation, then tested whether an attacker-opened popup could receive the code from location.href.
**Exploitation:** Attacker lures a logged-in Semrush user to a page that opens the OAuth consent popup; after the user approves, the leaked code is exchanged using the public seoquake client credentials for the victim's access and refresh tokens, granting access to user, project and Site Audit data.
**Insight:** OAuth success/redirect pages that postMessage their own location.href to window.opener with '*' leak the authorization code to any opener; check postMessage targetOrigin on OAuth callback pages, not just the authorize endpoint.

