Wenn ich das richtig verstehe, klingt es so, als würden Sie das Token für jede Anfrage festlegen. Meine Vermutung wäre, dass die alte Seite noch das alte Token hat. Ich würde überprüfen, ob das Token gesetzt ist, bevor es automatisch weggeblasen wird.
if (isset($_SESSION['token'])){
//do nothing
} else{
$_SESSION['token'] = md5(rand());
}
Bearbeiten Um Ihre Frage zu beantworten.
Anstatt nur einen „Token“-Schlüssel zu verwenden, erstellen Sie einen Schlüssel für jede Browsersitzung.
$_SESSION[$sessionId] = md5(rand());
Der Trick besteht natürlich darin, herauszufinden, wann diese auftreten, denn wenn Sie die Sitzung nicht verwenden können, wissen Sie wirklich nicht, ob die Anfrage von einem neuen oder einem alten Tab stammt. Sie könnten die Abfragezeichenfolge verwenden, um diesen Parameter weiterzugeben. Grundsätzlich müssten alle Anfragen diesen Parameter haben, sonst ordnen Sie ihnen keine Session zu.
z. B.
http://www.yoursite.com/somepage.php?sessionid=<some generated id>
Letztendlich könnte der Benutzer damit herumalbern, aber ich bin mir nicht sicher, ob es einen Ausweg gibt.
Bearbeiten 2 Ok, hier ist mein Gedanke, wie Sie dies tun sollten. Sicherheitsexperten da draußen, fühlen Sie sich frei, mich zu beschimpfen, wenn ich hier falsch liege, wie ich bereits sagte, ich bin kein Experte, aber es sieht nicht so aus, als würde ich daraus herauskommen, ohne etwas vorzuschlagen;-)
Das Problem mit CSFR ist, dass ein böswilliger Benutzer, Bob, ein Element auf einer anderen Website erstellen könnte, das Alices Browser veranlasst, eine Anfrage an eine andere Website zu stellen, und weil Alice sich zuvor angemeldet hatte und diese Informationen entweder als Cookie oder als Alice gespeichert werden über Sitzung erkannt wird, führt die Seite die Anfrage so aus, als ob Alice sie angefordert hätte. Zum Beispiel, wenn Alices Bank http://www.mybank.com ist , dann könnte Bob einen Forenbeitrag erstellen, der
enthält<img srg="http://www.mybank.com/transferfunds.php?amount=1000&receiver=Bob" />
Alices Bank würde erkennen, dass ihr Browser die Anfrage gestellt hat, und denken, dass sie es ist. Es gibt ein paar wichtige Dinge, die passieren müssen (zusammen führt das Scheitern von beiden dazu, dass der Angriff fehlschlägt), um dies zu einem brauchbaren Angriff zu machen (dies sind die wichtigsten, um zu verstehen, wie man ihn verhindert):
- Alice muss sich auf ihrer Bankseite angemeldet haben, damit die Bank sich an sie erinnert. Dies kann entweder in einem Cookie ("remember me") oder per Session geschehen. Wenn sie jedoch ihren Browser schließt (die Sitzung beendet) oder ihre Cookies löscht, besteht keine Gefahr, da die Website der Bank sie nicht erkennt und die Anfrage ablehnt.
- Bob muss in der Lage sein, alle erforderlichen Parameter für die Anfrage bereitzustellen, andernfalls wird die Bank-Website die Anfrage ablehnen.
Um zusätzlich zu einem zustandslosen Protokoll (HTTP) eine Vorstellung von "Zustand" bereitzustellen, können Sie das Risiko in (1) wirklich nicht umgehen. Wenn Sie die Leute nicht dazu bringen, immer auf "Abmelden" zu klicken oder ihr Fenster zu schließen usw., gibt es nichts, was Sie tun können, um Informationen im Browser oder in der Sitzung zu speichern. Sie können jedoch verhindern, dass (2) ein Problem darstellt. Meine Lösung dafür (und ich bin mir sicher, dass es unzählige andere gibt) besteht darin, einen Hash zu generieren, wie Sie es tun, und ihn in der Sitzung zu speichern.
Zum Beispiel
$_SESSION['token'] = md5(rand());
Dann fügen Sie dieses Token an alle Ihre internen Links an.
http://www.mysite.com/secure.php?token=giuwnrefviunslfghahgliuwnvwrgbaasd
Du NIEMALS Speichern Sie dieses Token im Browserspeicher:d.h. ein Cookie. Wenn Anfragen gestellt werden, überprüfen Sie das Token
, bevor Sie irgendetwas tun//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
}
Der Schlüssel dazu ist, dass alle Links auf Ihrer Website das Token enthalten. Bob kann jedoch nicht wissen, was dieses Token ist, da es nicht in einem Cookie im Browser gespeichert ist. Wenn er versucht, einen Link zu einer Ihrer Seiten zu erstellen, enthält diese entweder den falschen Schlüssel oder keinen Schlüssel und Sie können dies ablehnen. (Um fair zu sein, es besteht die Möglichkeit, dass er das Token für einen bestimmten Benutzer, der zufällig seinen Code sieht, richtig erraten könnte, aber er wird wahrscheinlich eher in Flammen aufgehen.)
Es ist auch nicht erforderlich, dem Token ein Timeout zuzuweisen, da das Token gelöscht wird, wenn der Browser geschlossen wird, und neu generiert werden muss, wenn der Benutzer die Website besucht.