Je bekijkt nu Cross site scripting (XSS) uitgelegd

Cross site scripting (XSS) uitgelegd

  • Laatste wijziging in bericht:oktober 4, 2026
  • Bericht auteur:

Wat is cross site scripting (XSS)?

cross site scripting, vaak afgekort als XSS, is een kwetsbaarheid waarbij een aanvaller JavaScript laat uitvoeren in de browser van een bezoeker. De website lijkt dan vertrouwd, maar de browser voert toch code uit die niet van de eigenaar komt. Daardoor kan een aanvaller cookies lezen, sessies misbruiken, formulieren aanpassen of een gebruiker naar een valse actie sturen.

XSS hoort bij de bredere groep van aanvallen waarbij invoer code wordt. Bij cross site scripting ontstaat de fout meestal niet in de browser zelf. Meestal verwerkt de website gebruikersinvoer verkeerd en toont die invoer daarna als actieve code. Daarom is XSS vooral gevaarlijk op plekken waar bezoekers zelf tekst, zoektermen, namen, reacties of URL-waarden kunnen aanleveren.

Deze gids legt uit hoe XSS werkt, welke hoofdvormen bestaan en welke schade aanvallers zoeken. Ook zie je veilige proof-of-concept voorbeelden. Die voorbeelden tonen het principe zonder schade aan te richten. Zo herken je het risico beter, terwijl je geen echte aanval nadoet op systemen die niet van jou zijn.

Cross-site scripting in de browsercontext

Een browser voert JavaScript uit binnen de context van een website. Daardoor heeft een script toegang tot onderdelen van die pagina, zoals formulieren, knoppen, schermtekst en soms cookies. Als een aanvaller eigen JavaScript in die context krijgt, lijkt die code voor de browser bij de website te horen.

Toch betekent cross site scripting niet dat de aanvaller meteen de server beheert. De aanval richt zich vooral op de gebruiker die de pagina opent. Daardoor kan de schade per gebruiker verschillen. Een gewone bezoeker loopt risico op gegevensdiefstal. Een ingelogde beheerder kan, daarentegen, onbedoeld beheeracties uitvoeren met hogere rechten.

Hoe werkt cross site scripting in de browser?

Bij een XSS-aanval zoekt de aanvaller eerst een plek waar de website invoer terugplaatst in de pagina. Denk aan een zoekveld, profielnaam, contactformulier, foutmelding of parameter in de URL. Als de applicatie die invoer niet goed encodeert, kan tekst veranderen in uitvoerbare code.

Laptop met browservenster en code op het scherm

Daarna levert de aanvaller een payload aan. Een payload is het stukje invoer dat het gedrag aantoont. In een veilige test gebruikt iemand bijvoorbeeld een onschuldig script dat alleen een melding toont. Een schadelijke aanvaller gebruikt echter code die sessies, tokens of formuliergegevens probeert te stelen.

Vervolgens opent een slachtoffer de pagina of link. De browser bouwt de pagina op en voert de ingevoegde code uit. Hierdoor kan de aanvaller acties laten plaatsvinden alsof de gebruiker die zelf uitvoert. Dit maakt cross site scripting extra verraderlijk, want de aanval misbruikt het vertrouwen tussen gebruiker, browser en website.

Veilige proof-of-concept payloads voor cross-site scripting

Een proof-of-concept moet veilig en beperkt blijven. Gebruik daarom alleen payloads die aantonen dat JavaScript draait, zonder gegevens te verzamelen. Een bekende demonstratie is <script>alert('XSS-test')</script>. Deze payload toont een melding, maar stuurt niets door.

Een nog veiligere test is tekstueel. Plaats bijvoorbeeld <b>test</b> in een veld en controleer of de pagina dit als tekst of als opmaak toont. Als de tekst vet verschijnt, verwerkt de pagina HTML als actieve inhoud. Dat is geen volledig bewijs van XSS, maar het is wel een waarschuwingssignaal.

Test alleen systemen waarvoor je toestemming hebt. Gebruik bovendien geen payloads die cookies uitlezen, sessies doorsturen of externe scripts laden. Zulke tests kunnen schade veroorzaken en vallen buiten normale foutopsporing. Voor een veilige aanpak helpt het om bevindingen te koppelen aan concrete beveiligingsmaatregelen.

Drie vormen van cross-site scripting

Er zijn drie hoofdvormen van Cross-Site Scripting: reflected XSS, stored XSS en DOM-based XSS. Ze lijken op elkaar, maar de route van de payload verschilt. Daarom vraagt elke vorm om een andere manier van herkennen.

Reflected XSS

Bij reflected XSS komt de payload meestal binnen via een URL, zoekterm of formulier. De server neemt die invoer direct op in de reactie. Daarna ziet de browser de invoer als onderdeel van de pagina. De code blijft dus niet opgeslagen in de database.

Een typisch scenario begint met een link naar een zoekpagina. De link bevat een afwijkende zoekterm met scriptcode. Als het slachtoffer klikt, toont de website die zoekterm terug. Wanneer de site niet goed encodeert, voert de browser de code uit. Daardoor kan een simpele link genoeg zijn voor misbruik.

Stored XSS

Bij stored XSS slaat de applicatie de payload op. Dat kan in een reactie, profieltekst, supportticket, productreview of bericht. Later krijgen andere bezoekers die opgeslagen inhoud te zien. Daardoor treft één kwaadaardige invoer mogelijk veel gebruikers.

Deze vorm is vaak ernstiger dan reflected XSS. De aanvaller hoeft namelijk niet elke gebruiker apart een link te sturen. De website verspreidt de payload zelf zodra bezoekers de besmette pagina openen. Vooral beheerpanelen, klantportalen en forums lopen hierdoor extra risico.

DOM-based XSS

DOM-based XSS ontstaat in de browser. JavaScript op de pagina leest dan bijvoorbeeld een waarde uit de URL en plaatst die waarde onveilig in de DOM. De server hoeft de payload niet eens terug te sturen. Hierdoor missen serverlogs soms de duidelijke sporen.

Deze variant vraagt extra aandacht bij moderne webapps. Veel pagina’s bouwen inhoud dynamisch op met JavaScript. Als ontwikkelaars waarden uit location, fragmenten of querystrings direct in innerHTML plaatsen, kan code ontstaan waar tekst bedoeld was.

Cross-site scripting stap voor stap: reflected XSS herkennen

Een veilige analyse begint met observeren. Zoek eerst naar pagina’s die jouw invoer letterlijk teruggeven. Dat kan een zoekresultaat zijn, maar ook een foutmelding of bevestigingspagina. Noteer waar de invoer verschijnt: in HTML-tekst, in een attribuut, in JavaScript of in een URL.

Vul daarna een onschuldige testwaarde in, zoals XSS-TEST-123. Kijk in de paginabron of ontwikkelaarstools waar deze waarde terechtkomt. Hierdoor zie je welke context bescherming nodig heeft. HTML-tekst vraagt andere encoding dan een JavaScript-string of URL-parameter.

Test vervolgens met veilige tekens, zoals <, >, aanhalingstekens en apostrofs. Als de website die tekens ongewijzigd terugplaatst, kan dat wijzen op een kwetsbare plek. Gebruik echter geen datadiefstal of externe scripts. Het doel is bewijs verzamelen, niet schade veroorzaken.

Leg de bevinding vast met de URL, de invoer, de reactie en een schermafbeelding. Beschrijf ook welke gebruiker getroffen raakt. Een fout in een openbaar zoekveld heeft een andere impact dan een fout in een beheerdersscherm. Daardoor kun je prioriteit geven aan de juiste oplossing.

Accountimpact bij cross-site scripting

De bekendste schade is sessiediefstal. Als cookies niet goed beschermd zijn, kan JavaScript proberen sessiewaarden uit te lezen. Met zo’n sessie kan een aanvaller soms handelen alsof hij de gebruiker is. Dit kan leiden tot accountovername, vooral wanneer extra controles ontbreken.

Moderne cookies met HttpOnly beperken dit risico, omdat JavaScript ze dan niet kan lezen. Toch blijft XSS gevaarlijk. Een script kan nog steeds formulieren invullen, knoppen activeren of gevoelige scherminformatie kopiëren. Daarom stopt cookiebeveiliging niet alle aanvalspaden.

Andere doelen zijn phishing, gegevensdiefstal en misbruik van rechten. Een aanvaller kan een nep-inlogvenster tonen binnen een echte website. Ook kan hij acties uitvoeren onder het account van een gebruiker. Bij een beheerder kan dat gevolgen hebben voor klantdata, instellingen en toegangsrechten. Dit raakt ook aan risico’s rond rechten die te ruim staan.

  • Sessiecookies of tokens buitmaken wanneer bescherming ontbreekt.
  • Accounts kapen via bestaande browsersessies.
  • Formulieren aanpassen of betalingen omleiden.
  • Gebruikers naar valse meldingen of nep-loginvensters sturen.
  • Beheeracties uitvoeren namens een ingelogde medewerker.

Cross-site scripting veilig verwerken in invoer

Voorkomen begint bij de juiste output encoding. Valideer invoer waar mogelijk, maar vertrouw daar niet alleen op. De applicatie moet gegevens veilig tonen in de context waarin ze verschijnen. Tekst in HTML vraagt andere regels dan tekst binnen JavaScript of een attribuut.

Gebruik in HTML-tekst bijvoorbeeld escaping voor tekens zoals <, > en &. In een HTML-attribuut moet je ook zorgvuldig omgaan met aanhalingstekens. In JavaScript-strings is contextspecifieke encoding nodig. Daardoor voorkom je dat gebruikersinvoer uit de tekstcontext breekt.

Veilige frameworks helpen, omdat ze standaard veel uitvoer escapen. Toch kan een ontwikkelaar die bescherming omzeilen met functies die ruwe HTML plaatsen. Gebruik zulke functies alleen als de invoer strikt gecontroleerd is. Anders verandert een handige functie snel in een vorm van code-injectie.

Een Content Security Policy kan schade beperken. Een strikte policy staat alleen scripts toe uit vertrouwde bronnen en blokkeert inline scripts. Toch is CSP geen vervanging voor veilige code. Zie het als extra vangnet. Als de applicatie onveilige uitvoer blijft maken, blijft het onderliggende probleem bestaan.

Detectie in logs en meldingen

XSS laat niet altijd duidelijke sporen achter. Toch kun je signalen herkennen. Let in logs op opvallende tekens in querystrings, zoals <script, onerror=, javascript: of lange gecodeerde waarden. Zulke signalen betekenen niet altijd misbruik, maar ze verdienen onderzoek.

Beveiligingsanalist bekijkt serverlogs op een monitor

Gebruikersmeldingen zijn ook waardevol. Meldingen over vreemde pop-ups, onverwachte uitlogmomenten of aangepaste formulieren kunnen wijzen op cross site scripting. Daarnaast kunnen beheerders afwijkende acties zien, zoals wijzigingen die niemand bewust deed. Combineer daarom browserinformatie, serverlogs en applicatielogs.

Bij incidentonderzoek moet je snel bepalen welke pagina kwetsbaar is en welke gebruikers de pagina bezochten. Trek verdachte content tijdelijk terug. Verwijder daarna de oorzaak in de code. Informeer getroffen gebruikers als sessies, persoonsgegevens of accounts geraakt kunnen zijn. Koppel dit aan breder zicht op digitale dreigingen binnen de organisatie.

Risico inschatten bij een XSS-vinding

Niet elke XSS-vinding heeft dezelfde ernst. Kijk eerst naar bereik. Een openbare pagina met veel bezoekers heeft meer impact dan een interne testpagina. Kijk daarna naar rechten. Een kwetsbaarheid in een adminportaal is meestal kritieker dan een fout op een anonieme zoekpagina.

Beoordeel ook of de payload opgeslagen blijft. Stored XSS krijgt vaak een hogere prioriteit, omdat de aanval vanzelf terugkeert bij nieuwe bezoekers. Reflected XSS vraagt meestal een klik op een link. DOM-based XSS kan lastig te vinden zijn, omdat de fout in client-side code zit.

Een praktische risicomatrix voor cross site scripting kijkt naar vier vragen: wie kan de payload plaatsen, wie ziet de payload, welke rechten heeft het slachtoffer en welke gegevens zijn zichtbaar. Als meerdere antwoorden ongunstig zijn, pak de vinding snel op. Daardoor voorkom je dat een klein invoerprobleem uitgroeit tot accountmisbruik.

Wat te doen bij een XSS-aanval?

Handel gestructureerd. Verwijder eerst de kwaadaardige inhoud of schakel de kwetsbare functie tijdelijk uit. Beperk daarna actieve sessies door tokens te vernieuwen of gebruikers opnieuw te laten inloggen. Zo verklein je de kans dat gestolen sessies bruikbaar blijven.

Onderzoek vervolgens de oorzaak. Controleer de kwetsbare template, API-respons of client-side code. Pas encoding toe in de juiste context en voeg tests toe die herhaling voorkomen. Herstel niet alleen de zichtbare payload, want de fout kan op meerdere plekken zitten.

Communiceer helder als gebruikers risico liepen. Vermeld welke gegevens mogelijk zichtbaar waren en welke stappen je neemt. Dwing wachtwoordwijzigingen alleen af als daar reden voor is. Monitor daarna op nieuwe pogingen, omdat aanvallers vaak terugkomen zodra ze een ingang vonden.

Veelgestelde vragen

Deze vragen helpen om de kern van XSS snel te begrijpen.

Is XSS hetzelfde als malware?

Nee. XSS is een kwetsbaarheid of aanvalstechniek waarbij scripts in de browser draaien. Malware is schadelijke software. Toch kan XSS malware helpen verspreiden, bijvoorbeeld door bezoekers naar een besmette pagina te sturen of door schadelijke scripts in een vertrouwde website te tonen.

Waarom zijn sessiecookies belangrijk bij XSS?

Sessiecookies bewijzen vaak dat iemand is ingelogd. Als een aanvaller zo’n waarde kan misbruiken, kan accountovername volgen. HttpOnly-cookies beperken uitlezen via JavaScript, maar ze stoppen niet elke actie. Een script kan soms nog steeds handelingen uitvoeren in de actieve sessie.

Hoe herken je een veilige XSS-demonstratie?

Een veilige demonstratie toont alleen dat code kan draaien. Ze verzamelt geen gegevens, stuurt niets door en gebruikt geen externe scripts. Een melding met alert('XSS-test') of een tekstuele HTML-test is geschikt. Test bovendien alleen met toestemming van de eigenaar.

Welke XSS-vorm is het gevaarlijkst?

Stored XSS is vaak het gevaarlijkst, omdat de payload opgeslagen blijft en meerdere bezoekers kan raken. Toch kan reflected of DOM-based XSS ook ernstig zijn. De echte ernst hangt af van bereik, gebruikersrechten, zichtbare gegevens en de mogelijkheid tot accountovername.

Kan CSP XSS volledig oplossen?

Nee. CSP kan misbruik beperken door ongewenste scripts te blokkeren. Toch moet de applicatie invoer veilig verwerken en uitvoer correct encoden. Gebruik CSP daarom als extra laag, niet als vervanging voor veilige templates, goede validatie en contextspecifieke escaping.

Conclusie

XSS blijft gevaarlijk omdat de aanval plaatsvindt op een plek die gebruikers vertrouwen: de website in hun eigen browser. Een kleine fout in uitvoer of templatecode kan daardoor leiden tot sessiediefstal, phishing, accountovername en misbruik van rechten.

Beperk het risico met contextspecifieke escaping, veilige frameworks, HttpOnly-cookies, strikte CSP-regels en goede logging. Gebruik daarnaast alleen veilige proof-of-concept payloads wanneer je test. Zo toon je het probleem aan zonder schade te veroorzaken.

Wie cross site scripting serieus neemt, beschermt niet alleen code, maar ook bezoekers, sessies en vertrouwen.