# DOM Based XSS via postMessage at https://inventory.upserve.com/login/

Insecure postMessage origin check on inventory.upserve.com login page allowed a lookalike-domain attacker to inject JS via eval and steal credentials.

- Payout: $2,500
- Severity: high
- Program: Upserve
- Credited: gamer7112
- Disclosed: 2019-06-25
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/603764
- Library page: https://bugbountylibrary.com/r/h1%3A603764
- Tags: domain:web impact:ato impact:data-leak kind:bounty platform:hackerone sev:high technique:chained technique:source-review vuln:xss

**Target:** inventory.upserve.com/login/ postMessage handler
**Root cause:** Origin validated with substring match `~e.origin.indexOf("https://hq.upserve.com")`, so any origin containing that string (e.g. https://hq.upserve.com.mydomain.com) passes; message data is then passed to eval().
**Steps:**
1. Register/control a domain like `hq.upserve.com.mydomain.com` and host `upserve_xss.html` that opens/embeds https://inventory.upserve.com/login/ and posts `{exec:"alert(document.domain)"}` via `postMessage`
2. Victim visits attacker page and clicks the link
3. Child frame's message listener sees origin containing `https://hq.upserve.com`, passes check, and `eval(e.data["exec"])` executes
**How found:** Code review of the postMessage listener revealed the origin check used `indexOf` substring matching rather than strict equality, and that message data flowed into `eval`.
**Exploitation:** Attacker page frames or opens the login page, then sends a postMessage with an `exec` property containing arbitrary JS. Because the substring origin check accepts the attacker's lookalike domain, eval runs in the inventory.upserve.com origin, letting the attacker keylog the login form and exfiltrate credentials.
**Insight:** When auditing postMessage handlers, grep for `indexOf`/`includes`/regex on `e.origin` instead of `===`; any substring match is bypassable by a domain that embeds the trusted string as a prefix or suffix. Also flag any `eval(e.data...)` sink reachable after the check.
