Als ik het goed begrijp, klinkt het alsof je de token voor elk verzoek instelt. Mijn gok zou zijn dat de oude pagina nog steeds de oude token heeft. Ik zou controleren of het token is ingesteld voordat ik het automatisch wegblaas.
if (isset($_SESSION['token'])){
//do nothing
} else{
$_SESSION['token'] = md5(rand());
}
Bewerken Om uw vraag te beantwoorden.
In plaats van slechts één sleutel van "token" te gebruiken, maakt u een sleutel voor elke browsersessie.
$_SESSION[$sessionId] = md5(rand());
De truc is natuurlijk om uit te zoeken wanneer die plaatsvinden, want als je de sessie niet kunt gebruiken, weet je echt niet of het verzoek afkomstig is van een nieuw of een oud tabblad. U kunt de queryreeks gebruiken om deze parameter door te geven. In principe zouden alle verzoeken deze parameter moeten hebben, anders koppel je er geen sessie aan.
bijv.
http://www.yoursite.com/somepage.php?sessionid=<some generated id>
Uiteindelijk kan de gebruiker hiermee apen, maar ik weet niet zeker of er een manier is om dat te omzeilen.
Bewerk 2 Ok, hier is mijn gedachte over hoe je dit zou moeten doen. Beveiligingsexperts die er zijn, voel je vrij om me te ontslaan als ik dit verkeerd heb, zoals ik al eerder zei, ik ben geen expert, maar het ziet er niet naar uit dat ik hier uit ga komen zonder iets te suggereren;-)
Het probleem met CSFR is dat een kwaadwillende gebruiker, Bob, een element op een andere site kan maken waardoor de browser van Alice een verzoek doet aan een andere site en omdat Alice eerder had ingelogd en die informatie als een cookie of Alice is opgeslagen. wordt herkend via een sessie, voert de site het verzoek uit alsof Alice het had aangevraagd. Als de bank van Alice bijvoorbeeld http://www.mybank.com is , dan zou Bob een forumbericht kunnen maken met
<img srg="http://www.mybank.com/transferfunds.php?amount=1000&receiver=Bob" />
De bank van Alice zou haar browser herkennen die het verzoek deed, in de veronderstelling dat zij het was. Er zijn een paar belangrijke dingen die moeten gebeuren (samen zal een van deze falen ervoor zorgen dat de aanval mislukt) om dit een levensvatbare aanval te maken (dit zijn de belangrijkste dingen om te begrijpen hoe deze te voorkomen):
- Alice moet ingelogd zijn op haar banksite zodat de bank haar onthoudt. Dit kan gebeuren in een cookie ("onthoud mij") of via een sessie. Als ze echter haar browser sluit (de sessie beëindigt) of haar cookies wist, is er geen gevaar omdat de banksite haar niet zal herkennen en het verzoek zal weigeren.
- Bob moet alle benodigde parameters aan het verzoek kunnen verstrekken, anders zal de bankwebsite het verzoek weigeren.
Om een idee van "staat" te geven bovenop een staatloos protocol (HTTP), kun je het risico in (1) echt niet omzeilen. Tenzij u ervoor zorgt dat mensen altijd op "uitloggen" klikken of hun venster sluiten, enz., kunt u niets doen om het opslaan van informatie in de browser of sessie te omzeilen. U kunt echter voorkomen dat (2) een probleem wordt. Mijn oplossing hiervoor (en ik weet zeker dat er talloze andere zijn) is om een hash te genereren, zoals je doet, en deze tijdens een sessie op te slaan.
Bijvoorbeeld,
$_SESSION['token'] = md5(rand());
Vervolgens voegt u dat token toe aan al uw interne links.
http://www.mysite.com/secure.php?token=giuwnrefviunslfghahgliuwnvwrgbaasd
Jij NOOIT sla die token op in het geheugen van de browser:d.w.z. een cookie. Wanneer verzoeken worden gedaan, controleert u voordat u iets doet het token
//note, you'll want to sanitize user input, I'm just being brief
if ($_GET['token'] != $_SESSION['token']){
//User either attempted to enter a link on their own or it's a CSRF attack
header('HTTP/1.1 403 Forbidden');
}else{
//do whatever needs to be done
}
De sleutel hiervoor is dat alle links op uw site de token bevatten. Bob kan echter niet weten wat dat token is, omdat het niet in een cookie in de browser is opgeslagen. Als hij een link naar een van uw pagina's probeert te maken, zal deze ofwel de verkeerde sleutel bevatten, of zal deze geen enkele sleutel bevatten en kunt u deze weigeren. (Om eerlijk te zijn, er is een kans dat hij het token correct kan raden voor een specifieke gebruiker die toevallig zijn code bekijkt, maar de kans is groter dat hij in brand vliegt.)
Het is ook niet nodig om een time-out aan het token toe te wijzen, aangezien het token wordt gewist wanneer de browser wordt gesloten en opnieuw moet worden gegenereerd wanneer de gebruiker de site bezoekt.