Gisteren kwam ik een presentatie tegen van Ilia Alshanetsky over beveiliging in PHP. Daar kwamen een aantal punten in voor die ik graag met jullie wil delen en benieuwd ben naar jullie mening/aanpak.
Punt 1: Session Fixation
Session fixation is een manier om een sessie te stelen waarbij de aanvaller vooraf weet welk session id het slachtoffer krijgt. (Dus niet zoals bij session hijacking waarbij het session id achteraf gestolen wordt.) Dit is toe te passen met bijvoorbeeld een link als:
jouw.bank.com/?PHPSESSID=foobar
Als het slachtoffer nu op de link klikt denkt de website dat het sessie id foobar is en gaat hier alle gegevens aan koppelen, de aanvaller kan nu simpelweg dat sessie id ook gebruiken.
De oplossing die hierbij gegeven wordt is door simpelweg na het inloggen een nieuw sessie id toe te wijzen waardoor de aanvaller geen kans meer heeft:
<?php
session_start();
// some login code
if ($login_ok) { // user logging in
session_regenerate_id(); // make new session id
?>
Punt 2: Session Hijacking
Een veel toegepaste techniek om [google]session hijacking[/google] (en ook helpt om session fixation) te voorkomen is een sessie koppelen aan een gebruiker. Maar hoe kan je nu een sessie aan een gebruiker koppelen? Een veelgebruikte manier daarvoor is om de sessie aan het IP adres van de gebruiker te koppelen, maar dit heeft een paar nadelen waaronder:
- Er kunnen meerdere mensen met het zelfde ip adres zijn (denk aan thuis- of sommige bedrijfsnetwerken).
- Een IP adres kan vaak wisselen.
- Een IP adres is te spoofen.
In de presentatie wordt ook een voorbeeld met een alternatief gegeven voor het koppelen van een sessie aan een ip adres, namelijk het koppelen aan de browser signature:
Ook dit is niet helemaal water dicht omdat het vaker voor kan komen en door de gebruiker aan te passen is. Maar misschien is het een idee om ook nog het IP adres in de md5-hash mee te nemen?
Ik hoop dat iemand hier wat aan heeft of misschien zelfs wel andere manieren heeft om deze problemen te voorkomen/beveiligen.
@Lode
Om, allereerst die cookie/sessie te hijacken moet je d.m.v. een lek de cookie/sessie hijacken. Vervolgens moet je achter het IP, de host en de user-agent komen van de ingelogde persoon. Dan moet je het IP adres spoofen, host vervalsen en de useragent namaken.
Dan moet je zo ver komen, en dan nog, hoe zou je dat hele plan kunnen tegengaan...
Verbinden met netwerk -> vanaf router ip-adres van de ISP, zelfde dus als dat van het slachtoffer -> IP adres 'gespoofd'
IP adres wordt via de dns-servers van de isp omgezet in een hostname, dus wanneer je hetzelfde ip-adres hebt, heb je automatisch ook dezelfde hostname. Ik denk niet dat het nut heeft om apart op de hostname te controleren.
Wat ik me wel afvraag: hoe spoof je dan het ip-adres wanneer je niet op hetzelfde netwerk zit? IP-adres zit niet in een van de headers, maar is een eigenschap van het onderliggende TCP/IP protocol. Hoe ga je ervoor zorgen dat wanneer jij iets via TCP/IP verstuurt met een 'foutief' IP-adres, het ook weer bij jouw aankomt? Het lijkt mij dat je dan tussen slachtoffer en server moet zitten om het verkeer op te vangen. Als je al zover bent, is het dan niet veel makkelijker om gewoon de login-request, het formuliertje waar je je gebruikersnaam & wachtwoord intikt af te vangen, of desnoods te vervalsen? Phishing? Dan heb je het wachtwoord, en kan je ongestoord doen wat je wilt. "Je beveiliging is zo sterk als de zwakste schakel" of zoiets..
De gebruiker is volgens mij het grootste lek in een applicatie, ze hebben makkelijke wachtwoorden of gaan er niet altijd even goed mee om.
Maar mijn vraag is ook, hoe kunnen mensen IP-adressen spoofen, want als dat zo is dan is het feitelijk onmogelijk om session/cookie-hijacking goed tegen te gaan omdat je dan eigenlijk alles wel kan faken. Maar alsnog wordt het moeilijk want je moet het IP, de host en de useragent(in mijn geval dan) weten om die dingen te kunnnen spoofen en daar kom je ook niet altijd zomaar achter. Dan zou je ook nog een de sessie moeten kunnen hijacken.
Ik heb even vlug door alle post heen gelezen.
Maar ik hoor niemand "garbag collector" zeggen.
Als een sessie bijvoorbeeld een uur niet actief is dan wordt deze of door de "garbag collector" verwijderd of door een hit op die sessie. Ook kun je cookies aan maken die na het sluiten van de browser ongeldig worden. In de cookie staat alleen het sessie id (MD5 of SHA1 hash), meer niet.
Neem daarbij IP, browsernaam en eventueel x-forwarder controle en je hebt een redelijke veilig sessie systeem.
Met IP controle moet je oppassen dat je alleen de eerste 3 delen van het IPv4 controleert. Voor mensen met een dynamisch IP. Uiteraard geld dit ook voor IPv6.
?
Onbekende gebruiker
10-03-2008 18:50
@Martijn!, maar je kunt toch niet checken of een browser is gesloten? Of bedoel je dat een cookie na x aantal minuten verouderd is?
yep, 3e parameter setcookie op 0 zetten.
Maar ik weet niet of dit dan ook weer is te omzeilen.
Of bedoel je niet de cookie?
Als je naar een andere pagina gaan of je ververst de pagina na een x aantal seconden dan worden de sessie in de database veranderd, hierbij wordt de tijd ook opgeslagen. Als die tijd bijvoorbeeld een uur niet veranderd dan kun je de sessie niet meer gebruiken.
Dat betekent alleen maar dat de cookie niet blijvend wordt opgeslagen door de browser. Het zegt niets over de duur van je sessie zelf. Bij iedere request wordt de inhoud van het koekje over het netwerk gestuurd. Je server kan geen verschil zien of de browser tussen request 1 en request 2 is gesloten. Normaal gesproken zou request 2 geen cookie bevatten wanneer de browser gesloten is, maar wel wanneer dat niet gebeurt is. Maar wat nu als request 2 door de kwaadwillende wordt uitgevoerd, dan wordt het koekje braaf meegestuurd, en lijkt het net alsof het de oude browser is die gewoon niet is gesloten.
Uiteraard loont het om een sessie te laten verlopen (tijd tussen de requests meten, groter dan een uur? Weg sessie) maar dat komt met een grote valkuil: Stel dat ik een post van 10 pagina's aan het typen ben, en ondertussen koffie haal. Het zou zomaar kunnen dat ik langer dan een uur nodig heb om die post te typen. Hoe frustrerend is het dan wanneer blijkt dat ik eerst opnieuw mag inloggen en dan weer opnieuw mijn post mag typen. (dit is een ervaring, helaas :/ ) Dus wanneer je sessie-verloop implementeert, of wat voor beveiliging dan ook waarbij een sessie kan verlopen en de gebruiker opnieuw in moet loggen, zorg er alsjeblieft voor dat daarna de gestarte actie gewoon compleet hervat wordt, en mijn post dus alsnog hier te lezen is. ... niet dat ik nu koffie heb gehaald
Ik heb even vlug door alle post heen gelezen.
Maar ik hoor niemand "garbag collector" zeggen.
Als een sessie bijvoorbeeld een uur niet actief is dan wordt deze of door de "garbag collector" verwijderd of door een hit op die sessie. Ook kun je cookies aan maken die na het sluiten van de browser ongeldig worden. In de cookie staat alleen het sessie id (MD5 of SHA1 hash), meer niet.
Neem daarbij IP, browsernaam en eventueel x-forwarder controle en je hebt een redelijke veilig sessie systeem.
Met IP controle moet je oppassen dat je alleen de eerste 3 delen van het IPv4 controleert. Voor mensen met een dynamisch IP. Uiteraard geld dit ook voor IPv6.
Dit lijkt me dan weer minder veilig omdat je dan maar een deel van het IP hebt...
Het laten verlopen van sessie's is een mogelijkheid maar ik zou dat alleen doen bij website's waar dat echt nodig is of waar de bezoeker er weinig last van heeft. Ik neem even als voorbeeld een bank, daar is het i.m.o. heel goed dat sessie's verlopen. Bij communities e.d. lijkt het me dan weer minder geschikt.