RatXSS Dojo

Get alert(document.domain) to fire in every context below, then push at least one level to real impact by stealing the session cookie to the exfil collector.

Probe ideas from the deck: <img src=x onerror=alert(document.domain)>, <svg onload=alert(document.domain)>, "><script>alert(document.domain)</script>

NEW RatWire Daily - realistic range
A full fake newspaper. 9+ XSS bugs hidden in real features - comments, search, tip line, author bios, newsletter, share, tags, draft preview, language. Hunt it like a real app.

→ open level

N1 News: article comments (stored)
Reader comments are stored and shown to every visitor.

→ open level

N2 News: search results
The results heading echoes your query verbatim.

→ open level

N3 News: tip line
The 'tip received' page reflects your name.

→ open level

N4 News: author bio
Profile name + editable ?bio= both reflected.

→ open level

N5 News: newsletter
The confirmation greets your exact email.

→ open level

N6 News: share widget
Blurb sits inside value="..." - break out.

→ open level

N7 News: tag/category page
Section heading reflects the tag name.

→ open level

N8 News: draft preview
Author studio renders your HTML as it would publish.

→ open level

N9 News: language pref
Locale code lands in a lang="..." attribute.

→ open level

N10 News: unknown story (404)
Missing slug reflected into the not-found notice.

→ open level

1 Reflected XSS (body)
Input echoed straight into the page body.

→ open level

2 Reflected XSS (attribute)
Input lands inside an HTML attribute value.

→ open level

3 Reflected XSS (404 page)
The error page reflects the URL path - barriers are your friend.

→ open level

4 Reflected XSS (Referer)
The page reflects the Referer header you control.

→ open level

5 DOM XSS (never hits server)
Client JS reads location.hash into an innerHTML sink.

→ open level

6 Stored XSS (guestbook)
Your comment is saved and served to every visitor.

→ open level

7 Blind XSS (admin inbox)
Feedback fires later in the admin panel you can't normally see.

→ open level

F1 Filter: case blocklist
Blocks lowercase <script - vary the case.

→ open level

F2 Filter: keyword strip
Strips 'script' once, non-recursively - nest it.

→ open level

F3 Filter: script+onerror dead
script & onerror blocked - reach for alternate handlers.

→ open level

F4 Filter: attribute breakout
< and > are stripped - break out of the attribute.

→ open level

C1 Context: JS string
Reflected inside var q='...' - break the string.

→ open level

C2 Context: JS template literal
Inside backticks `...` - ${} runs, no quotes needed.

→ open level

C3 Context: JSON in <script>
Inside inline JSON - </script> closes it anyway.

→ open level

C4 Context: HTML comment
Inside <!-- ... --> - close the comment first.

→ open level

C5 Context: <textarea>
RCDATA - markup is text until </textarea>.

→ open level

C6 Context: <style>/CSS
Inside a style block - escape to markup.

→ open level

C7 Context: href scheme
You own the whole href - javascript: URI.

→ open level

C8 Context: unquoted attr
Value has no quotes - a space adds a handler.

→ open level

C9 Context: single-quoted attr
value='...' - break the single quote.

→ open level

C10 Context: event handler JS
Inside onclick="greet('...')" - already in JS.

→ open level

D1 DOM: document.write
document.write(location.search) sink.

→ open level

D2 DOM: eval(hash)
eval(location.hash) - never hits the server.

→ open level

D3 DOM: href from hash
link.href = hash - javascript: on click.

→ open level

D4 DOM: localStorage sink
localStorage value -> innerHTML.

→ open level

D5 DOM: window.name
window.name -> innerHTML, cross-page source.

→ open level

D6 DOM: clobbering
Script trusts window.CONFIG.url - forge it.

→ open level

W1 WAF: scheme strip
Strips javascript: once - nest/case it.

→ open level

W2 WAF: no parentheses
( ) blocked - call without them (backticks).

→ open level

W3 WAF: no quotes
Quotes stripped - svg onload needs none.

→ open level

W4 WAF: alert blocked
Build the call dynamically / use print().

→ open level

W5 WAF: no spaces
Spaces gone - use / as separator.

→ open level

W6 WAF: handler strip
on...= stripped once - SVG <script> or nest.

→ open level

W7 WAF: half-encoded attr
< > encoded but quotes are not - break value="".

→ open level

W8 WAF: double URL-decode
App decodes twice - double-encode the payload.

→ open level

W9 WAF: length limit
24 chars only - golf it or load remote.

→ open level

W10 WAF: tag blocklist
script/img/svg blocked - use details/marquee.

→ open level

W11 WAF: recursive strip
Loops on exact <script> token - case/space it.

→ open level

A1 Adv: AngularJS CSTI
Client-side template injection -> JS.

→ open level

A2 Adv: multi-context polyglot
One input, two sinks - one polyglot fires both.

→ open level

A3 Adv: CSP + JSONP bypass
script-src 'self' beaten via same-origin JSONP.

→ open level

A4 Adv: iframe srcdoc
HTML-in-attribute nested context.

→ open level

A5 Adv: mutation XSS (mXSS)
Sanitize-then-innerHTML - the re-parse mutates it.

→ open level

A6 Adv: postMessage sink
onmessage -> innerHTML, no origin check.

→ open level

A7 Adv: no charset (UTF-7)
Legacy charset sniffing - always set utf-8.

→ open level

A8 Adv: markdown render
Raw HTML + javascript: links pass through.

→ open level

A9 Adv: prototype pollution
?__proto__[html]=... gadget -> innerHTML.

→ open level

A10 Adv: Trusted Types bypass
TT on, but the default policy is identity.

→ open level

A11 Adv: SVG context
SVG script/xlink/animate handler surface.

→ open level

A12 Adv: service-worker persist
Turn momentary XSS into origin persistence.

→ open level

I Impact: keylogger
Beyond alert() - ship keystrokes to the collector.

→ open level

B Bonus: {{7*7}} SSTI sniff
Two birds: the same probe flushes template injection.

→ open level


RatXSS Dojo · HackXpert Coaching · The XSS Rat · authorized lab use only