← Alle checks
BeveiligingTypische ernst: Gemiddeld

Scanner voor onveilige cookies

Detecteert cookies zonder de attributen Secure, HttpOnly of SameSite die tegen diefstal en CSRF beschermen.

Wat het checkt

Deze scanner bekijkt de cookies die je site aan de browser geeft en controleert of de attributen Secure, HttpOnly of SameSite ontbreken. Die attributen beperken hoe en wanneer elk cookie gebruikt mag worden. Hij kijkt alleen naar de beschermingsvlaggen, niet naar de inhoud van het cookie.

Waarom het belangrijk is

Een sessiecookie zonder deze attributen kan door kwaadaardige scripts worden gestolen of onversleuteld reizen, waardoor iemand zich als je gebruikers kan voordoen. Het maakt ook CSRF-aanvallen mogelijk waarbij een derde namens de gebruiker handelt. In de praktijk kan dat een volledige accountovername betekenen.

Hoe je het oplost

Zet bij het aanmaken van cookies Secure zodat ze alleen over HTTPS reizen, HttpOnly zodat JavaScript ze niet kan lezen en SameSite (Lax of Strict) om cross-site gebruik te beperken. De meeste frameworks en sessiebibliotheken bieden deze opties in hun configuratie. Let vooral goed op je login- of sessiecookie.

Hoe deze controle werkt

Scanaris leest de Set-Cookie-headers die je server stuurt bij het laden van de homepage en bekijkt de attributen van elke cookie. Het controleert drie dingen: dat hij Secure draagt (alleen vereist als de site via HTTPS gaat), dat hij HttpOnly draagt en dat hij SameSite declareert. Suggereert de cookienaam een sessie of authenticatie (session, auth, token, sid en dergelijke), dan heeft de bevinding gemiddelde ernst; anders laag. Er is één speciaal geval met een eigen gemiddelde ernst: SameSite=None zonder Secure, dat moderne browsers ronduit weigeren, waardoor de cookie niet werkt en bovendien een configuratie verraadt die voor cross-site-gebruik bedoeld is. Alleen de cookies in dat eerste antwoord worden gezien; die na het inloggen worden aangemaakt controleer je beter met het commando hieronder of met de geauthenticeerde scan.

Wat elk attribuut betekent

  • Secure: de cookie reist alleen over HTTPS. Zonder stuurt een HTTP-verzoek (een oude link, een publiek netwerk) hem onversleuteld en leest iedereen op het netwerk hem.
  • HttpOnly: JavaScript kan hem niet lezen. Het is het verschil tussen een XSS die de sessie steelt en een die dat niet kan.
  • SameSite: wanneer hij vanaf een andere site wordt meegestuurd. Lax stuurt hem bij normale navigaties maar niet bij verzoeken die een andere website start; Strict nooit van buitenaf; None altijd, en vereist Secure. Het is de belangrijkste verdediging tegen CSRF.

Wat een aanvaller doet met een sessiecookie zonder deze attributen

Zonder HttpOnly leest elk geïnjecteerd script document.cookie, stuurt de waarde naar zijn server en logt in met jouw sessie. Zonder SameSite kan een vreemde pagina een formulier naar je site sturen met de cookie erbij en namens de gebruiker een bestelling plaatsen of een e-mailadres wijzigen. Zonder Secure volstaat het dat de gebruiker op een gedeeld netwerk een http://-link naar je domein opent. In alle drie de gevallen is het resultaat hetzelfde: iemand handelt als jouw gebruiker.

Hoe je het oplost, afhankelijk van je framework

// Express met express-session
app.use(session({
  cookie: { secure: true, httpOnly: true, sameSite: 'lax' }
}));

// Next.js (Route Handler of Server Action)
cookies().set('session', value, { httpOnly: true, secure: true, sameSite: 'lax', path: '/' });

// Nuxt (server/api)
setCookie(event, 'session', value, { httpOnly: true, secure: true, sameSite: 'lax', path: '/' });

Met Supabase in een app met een server bewaart de bibliotheek @supabase/ssr de sessie in cookies met deze attributen; in een pure SPA gaat de sessie naar localStorage, wat de controle tokens in storage meet. In Django, Rails of Laravel worden de attributen in de sessie-instellingen geconfigureerd en zijn ze standaard redelijk; controleer dat niemand ze heeft verlaagd om een ontwikkelprobleem "op te lossen".

Controleer of het is opgelost

curl -sI https://jouwdomein.com | grep -i "set-cookie"
curl -sI -X POST https://jouwdomein.com/api/login -d "..." | grep -i "set-cookie"

Elke sessiecookie moet Secure; HttpOnly; SameSite=Lax (of Strict) tonen. Is je login een formulier, bekijk dan het antwoord in de browsertools, tabblad Netwerk, antwoordheaders.

Veelgestelde vragen

Mijn cookie wordt door JavaScript aangemaakt (analytics, voorkeuren). Hij kan niet HttpOnly zijn.

Klopt, en dat is geen probleem: die cookies geven nergens toegang toe. De controle markeert hem met lage ernst voor het ontbrekende attribuut; wat telt is dat de sessiecookies het wél hebben.

Ik heb SameSite=None nodig omdat mijn app in een iframe op een ander domein draait.

Dan is het legitiem, altijd met Secure. Zorg dat de andere CSRF-verdedigingen (tokens in formulieren, controle van de Origin) actief zijn, want SameSite beschermt je niet meer.

Lax of Strict?

Lax voor de meeste gevallen: het behoudt de sessie wanneer de gebruiker via een externe link binnenkomt. Strict als de cookie toegang geeft tot iets heel gevoeligs en je accepteert dat de gebruiker opnieuw moet inloggen als hij van buiten komt.

Check het op je site

Scan je site gratis en zie of deze en 44 andere checks slagen, met een fixprompt voor elk probleem.

Mijn site gratis scannen

Uit de blog

Gerelateerde checks