Ga naar hoofdinhoud

XSS (DOM) — High

Dit level bevat een fascinerende eigenschap van internetbrowsers waar de backend geen enkel verweer tegen heeft.

1. Predict (Voorspel)

De backend PHP server probeert nu met een keiharde 'whitelist' te werken. De URL parameter mag simpelweg geen vreemde karakters bevatten, anders wordt de boel afgebroken.

switch ($_GET['default']) {
case "French":
case "English":
case "German":
case "Spanish":
break;
default:
exit("Taal niet toegestaan!");
}

Vraag: De server staat letterlijk alleen de woorden "French, English, German, Spanish" toe in de adresbalk. Toch is deze applicatie nog kwetsbaar voor DOM XSS. Dit heeft te maken met het # (hekje/hash) symbool in een URL. Weet je (of kun je raden) wat dit symbool doet?

Antwoord

Het # symbool in een URL (bijv. website.nl/#contact) is bedoeld voor ankerlinks op een pagina (scrollen naar een kopje). Een heel belangrijke regel van het internet: Alles wat ná het # symbool komt, wordt door de webbrowser lokaal bewaard en wordt nooit meegestuurd in het HTTP request naar de webserver! De server kan dit dus ook nooit controleren of blokkeren!

2. Run & Investigate

Start het lab.

Laden...

⚠️ Labbeperking: De # hash-truc vereist directe toegang tot de URL-balk van je browser, wat niet mogelijk is in het embedded lab. Het lab toont de server-side logica (de whitelist), maar om de aanval daadwerkelijk uit te voeren heb je een lokale DVWA-installatie nodig.

3. Modify & Make (Aanpassen & Maken)

Omdat de backend English in de parameter verwacht, geef je hem dat. Maar je plakt stiekem via de hash je payload erachter!

Tip

Bouw de URL op, waarbij je éérst aan de whitelist voldoet (default=English), en sluit direct daarna de payload aan die niet naar de server gaat.

Antwoord

Gebruik de waarde: English#<script>alert(1)</script>

Wat er gebeurt:

  1. Je vraagt aan de backend server de pagina op: ?default=English.
  2. De backend checkt de whitelist. "English" klopt! De pagina wordt veilig doorgestuurd.
  3. De JavaScript in je lokale browser leest wél de volledige adresbalk inclusief de hash! De JS schrijft de ongefilterde string direct in de pagina en triggert het script!

4. ✓ Wat moest je zien?

Controle
  • In een lokale DVWA-installatie: na het laden van ?default=English#<script>alert(1)</script> verschijnt een popup. De server zag alleen English in zijn whitelist en liet de pagina door; de hash werd nooit verstuurd.
  • In het iframe-lab hier: je kunt de hash niet in de adresbalk zetten, maar via Bekijk broncode zie je dat de PHP-whitelist alleen default= controleert en niets weet van wat na # komt.
  • Concept-check: in F12 Network zie je dat de request naar de server uitsluitend ?default=English bevat — de hash blijft volledig client-side.

Geen popup in je lokale install? Controleer dat je het volledig in de adresbalk plakt (de browser knipt de #-payload niet weg) en dat je daarna op Enter drukt om de pagina te herladen.

5. Er gaat iets mis...

Je probeert dit op een andere website en het werkt opeens niet. De truc met # is het perfecte voorbeeld van échte DOM XSS (gebaseerd op Location Fragments). Echter, de frontend JavaScript moet maar nét onhandig genoeg geschreven zijn dat het de volledige adresbalk uitleest (inclusief hashes) en deze blind print.