Sessie-identificatie in de URL
CWE-598CWE-200OWASP A07:2021Bijgewerkt 3 september 20264 min leestijd
Staat de sessie-identificatie in de URL, dan wordt ze meegeschreven in serverlogs, proxylogs, browsergeschiedenis en bladwijzers, en gaat ze via de referrer-header mee naar externe sites. Eén gedeelde link is dan genoeg om iemand anders toegang tot het account te geven, zonder dat er een wachtwoord aan te pas komt.
Een sessie-identificatie is functioneel gelijk aan een wachtwoord: wie de waarde heeft, is de gebruiker. Toch komt het voor dat die waarde gewoon zichtbaar in de adresbalk staat, waar hij vervolgens op een verrassend aantal plaatsen wordt vastgelegd. Hieronder leest u langs welke wegen dat lekt en waarom het probleem niet met HTTPS is opgelost.
Waarom hoort een sessie-ID niet in de URL?
Een applicatie moet bij elk verzoek weten wie de gebruiker is. Daarvoor stuurt de browser een sessie-identificatie mee, normaal gesproken in een cookie. Staat die identificatie in de URL, als queryparameter of als onderdeel van het pad, dan wordt ze onderdeel van het adres van de pagina, en daarmee van alles wat met dat adres gebeurt.
Dat is het wezenlijke verschil. Een cookie is een stukje verborgen huishouding tussen browser en server: hij verschijnt nergens in beeld, wordt niet gedeeld en belandt niet in de geschiedenis. Een URL is juist bedoeld om zichtbaar, kopieerbaar en deelbaar te zijn. Een geheim in een URL is een geheim in een structuur die is ontworpen om te worden doorgegeven.
Dat komt neer op het schrijven van uw pincode op de buitenkant van uw bankpas. Het werkt uitstekend zolang niemand kijkt, maar u hebt de bescherming verplaatst naar precies de plek waar iedereen hem kan zien.
Waar lekt de sessie naartoe?
Het aantal wegen waarlangs een URL wordt vastgelegd, is groter dan de meeste ontwikkelaars vermoeden.
Kwetsbaar:
https://portaal.example/dossier/overzicht?jsessionid=A3F91C7D4B2E8056
Deze ene URL komt onder meer terecht in het toegangslog van de webserver, in de logbestanden van elke tussenliggende proxy of loadbalancer, in de browsergeschiedenis van de gebruiker, in zijn bladwijzers als hij de pagina bewaart, en in monitoring- of foutrapportagesystemen die verzoeken meeschrijven. Bevat de pagina daarnaast een externe bron of een link naar buiten, dan vertrekt het volgende naar die derde partij:
GET /analytics.js HTTP/1.1
Host: statistiek.example
Referer: https://portaal.example/dossier/overzicht?jsessionid=A3F91C7D4B2E8056
De sessie van deze gebruiker staat nu in de logbestanden van een partij die er niets mee te maken heeft. Bovendien het meest alledaagse scenario vraagt helemaal geen aanvaller: de gebruiker kopieert de link uit de adresbalk en stuurt hem een collega, om “even deze pagina” te laten zien. Die collega opent daarmee het account van de afzender.
Veilig:
HTTP/1.1 200 OK
Set-Cookie: sid=A3F91C7D4B2E8056; HttpOnly; Secure; SameSite=Strict; Path=/
https://portaal.example/dossier/overzicht
De identificatie zit nu in een cookie en verdwijnt uit het adres. De URL kan zonder bezwaar worden gedeeld, opgeslagen en gelogd. HttpOnly houdt de waarde bovendien buiten bereik van JavaScript, Secure voorkomt verzending over een onversleutelde verbinding en SameSite=Strict zorgt dat de cookie niet meegaat bij verzoeken die vanaf een vreemde site vertrekken.
Bij een framework dat dit gedrag standaard aanbiedt, schakelt u het expliciet uit:
<!-- Java Servlet: uitsluitend cookies, nooit URL-rewriting -->
<session-config>
<tracking-mode>COOKIE</tracking-mode>
<cookie-config>
<http-only>true</http-only>
<secure>true</secure>
</cookie-config>
</session-config>
Referrer-Policy beperkt één van die routes, maar lost het onderliggende probleem niet op.Wat is de impact van een sessie-ID in de URL?
De ernst loopt van middelzwaar tot hoog, en dat hangt af van hoe eenvoudig een derde bij de URL kan komen. Anders dan bij veel andere sessieproblemen is hier geen aanvaller met een netwerkpositie of een injectie nodig: de meest waarschijnlijke oorzaak is een gebruiker die zelf een link doorstuurt.
Slaagt iemand erin een geldige sessie-identificatie te bemachtigen, dan is de overname volledig. De ontvanger is voor de applicatie niet te onderscheiden van de rechtmatige gebruiker: hij heeft dezelfde rechten, ziet dezelfde gegevens en kan dezelfde handelingen uitvoeren. Er komt geen wachtwoord aan te pas en tweefactorauthenticatie wordt niet opnieuw gevraagd, omdat de authenticatie al heeft plaatsgevonden.
Er is ook een lastig te herstellen kant. Sessie-identificaties die in logbestanden zijn beland, staan daar vaak jarenlang, verspreid over systemen met een ruimere toegang dan de applicatie zelf: beheerders, leveranciers en analyseplatforms. Zelfs na het oplossen van de kwetsbaarheid blijven die sporen bestaan, en ze moeten met dezelfde zorg worden behandeld als opgeslagen wachtwoorden.
Hoe spoor je een sessie-ID in de URL op?
Een tester let bij het doorlopen van de applicatie op elke parameter die op een identificatie lijkt: namen als sid, sessionid, jsessionid, phpsessid, token of auth in de query of in het pad. Het meest opvallende signaal is een sessiewaarde die bij het inloggen in de URL verschijnt en daarna blijft meelopen.
Vervolgens wordt gecontroleerd of de waarde daadwerkelijk toegang geeft: de tester opent dezelfde URL in een schone browser zonder cookies. Werkt dat, dan is de sessie volledig in de URL vervat. Ook wordt gekeken naar frameworks die bij afwezigheid van cookies automatisch terugvallen op URL-rewriting, dat gedrag is soms alleen zichtbaar als u cookies uitschakelt. Verder worden de foutpagina’s, PDF-exports en e-mails bekeken, omdat daar nogal eens volledige URL’s in terechtkomen. AssistSec beoordeelt daarbij ook de referrer-configuratie en de aanwezigheid van externe bronnen, omdat die samen bepalen hoe ver een gelekte identificatie werkelijk reist.
Hoe voorkom je een sessie-ID in de URL?
- Draag sessie-identificaties uitsluitend over in cookies, en schakel URL-rewriting in uw framework expliciet uit.
- Zet op het sessiecookie de attributen
HttpOnly,SecureenSameSite. - Plaats nooit tokens, herstelcodes of API-sleutels in een queryparameter of in het pad.
- Gebruik voor het delen van inhoud een aparte, expliciete deelfunctie met een eigen, beperkt token.
- Stel
Referrer-Policy: strict-origin-when-cross-originof strikter in als aanvullende laag. - Filter sessie-identificaties uit logbestanden en monitoringgegevens, of log alleen het pad zonder query.
- Trek alle bestaande sessies in wanneer u deze fout herstelt, omdat eerdere identificaties als gelekt moeten gelden.
- Vernieuw de sessie-identificatie bij het inloggen, zodat een eerder gedeelde waarde geen rechten meer geeft.
Bronnen
Veelgestelde vragen
Is het veilig als de URL alleen over HTTPS gaat?
Nee. HTTPS beschermt de URL onderweg, maar niet op de plaatsen waar hij daarna terechtkomt: het toegangslog van de webserver, de browsergeschiedenis, bladwijzers, een gedeelde schermafbeelding en de referrer-header naar externe bronnen. Versleuteling lost geen van die routes op.
Waarom deden applicaties dit vroeger?
Als terugvaloptie voor bezoekers die cookies hadden uitgeschakeld, wat rond de eeuwwisseling nog regelmatig voorkwam. Veel frameworks konden dat automatisch en dat gedrag zit soms nog steeds in oude configuraties. Tegenwoordig is er geen legitieme reden meer voor; cookies zijn universeel beschikbaar.
Geldt dit ook voor API-tokens in de URL?
Ja, en het probleem is identiek. Een toegangstoken in een queryparameter belandt in dezelfde logbestanden en geschiedenis. Stuur tokens altijd mee in een Authorization-header of een cookie, nooit als onderdeel van het adres.
Hoe herstel ik dit als het al is gebeurd?
Trek alle bestaande sessies in, zodat gelekte identificaties waardeloos worden. Schakel daarna het gedrag uit, en beoordeel of er logbestanden zijn waarin oude sessie-identificaties staan; die moeten met dezelfde zorg worden behandeld als wachtwoorden en zo mogelijk worden opgeschoond.
Verwante artikelen
- KwetsbaarhedenCWE-200A01:2021Information disclosureInformation disclosure uitgelegd: hoe stack traces, .git-mappen, source maps en te ruime API-responses gegevens lekken, en hoe u dat voorkomt.
- KwetsbaarhedenCWE-200A05:2021Ontbrekend Referrer-PolicyZonder Referrer-Policy geeft de browser de volledige URL van uw pagina door aan elke externe site. Lees welke gegevens daarbij weglekken en hoe u dat stopt.
- KwetsbaarhedenCWE-613A07:2021Sessie blijft geldig na uitloggenUitloggen dat alleen de cookie wist, laat het token aan serverzijde intact. Lees hoe een buitgemaakte sessie dan gewoon bruikbaar blijft.
- KwetsbaarhedenCWE-1004A07:2021Onbeschermd authenticatiecookieEen sessiecookie zonder HttpOnly, Secure en SameSite is uitleesbaar, onderschepbaar en misbruikbaar. Lees wat elk attribuut precies afdekt.
- KwetsbaarhedenCWE-384A07:2021Session fixationSession fixation uitgelegd: hoe een aanvaller vooraf een session id vastlegt, waarom die na het inloggen geldig blijft en hoe sessierotatie het stopt.