2017-08-30 1 views
0

Ich weiß, es gibt zwei Hauptlösungen gegen CSRF-Angriffe.Schutz vor CSRF-Angriffen in PHP für mehrere Browser-Registerkarten

  • ein Token pro Sitzung
  • Token für alle einzigartigen Formen

wählte ich die zweite, aber es ist ein Problem. Wenn der Besucher ein Formular in zwei Registerkarten öffnet, überschreibt das Formular-Token auf der zweiten Registerkarte die vorherigen Token. Ich habe einen Code geschrieben, um dieses Problem zu lösen. Meine Frage ist: Ist es eine gute Lösung, oder muss ich daran arbeiten? (Es gibt nur die wichtigsten Teile in den Beispielen.)

##### CONFIG & FUNCTION.PHP ##### 
// INITIALIZING - RUN ONLY ONCE 
$_SESSION["csrf_tokens"]["postcomment"]  = array(); 
$_SESSION["csrf_tokens"]["postcommentedit"] = array(); 
// etc, etc. 
function makearandomtoken() 
{ 
    // a simple but secure way 
    return bin2hex (openssl_random_pseudo_bytes (32)); 
} 

##### POSTCOMMENT_FORM.PHP ##### 
// new form for comment under a post, so create a new token 
$created_token = makearandomtoken(); 
array_push ($_SESSION["csrf_tokens"]["postcomment"], $created_token); 
// the form (only with important parts) 
print "<form>\n"; 
print "<input type=\"hidden\" name=\"token\" value=\"$created_token\">\n"; 
print "</form>\n"; 

##### POSTCOMMENT_EXECUTE.PHP ##### 
// get the token from POST variable 
$received_token = filter_input (INPUT_POST, 'token', FILTER_UNSAFE_RAW); 
// check it 
if (in_array($received_token, $_SESSION["csrf_tokens"]["postcomment"])) 
{ 
    // VALID token, disable it 
    $token_index = array_search($received_token, $_SESSION["csrf_tokens"]["postcomment"]); 
    unset ($_SESSION["csrf_tokens"]["postcomment"][$token_index]); 
} 
else 
{ 
    // INVALID token -> CSRF attempt 
    die(); // or do anything 
} 
+0

Wenn für Ihre App 2 Tabs erforderlich sind, führen Sie ein einzelnes CSRF-Token pro Anmeldung aus. Wenn dies nicht der Fall ist, sollte der Benutzer nicht mehrere Tabs öffnen. Setzen Sie auch nur Tokens, wenn Sie ein Formular auf diese Weise präsentieren. Sie könnten mehrere Registerkarten für nicht formularbasierte Seiten haben. –

+0

Sieht gut aus. Das einzige, was fehlt, ist eine Strategie, um alte unbenutzte Token zu löschen und/oder ein Limit für die Anzahl gültiger Tokens pro Benutzer. – jh1711

+0

Sie müssen die Anzahl der Token begrenzen, sonst könnte ein Angreifer diese verwenden, um die Sitzung zu füllen. Und da die Sitzungsgröße nur durch das PHP-Skript-Speicherlimit begrenzt ist, könnte es bei mehreren Konten den Server drosseln. – Jarzon

Antwort

0

Ich sehe nicht ein Problem bei der Implementierung, wenn Sie ein neues Token pro Formularinstanz wollen. Beide Tabs wurden vom Benutzer legitim geöffnet, daher ist es sinnvoll, dass beide Token akzeptiert werden.

Wie für den CSRF-Schutz, ich denke, es ist intakt. Eine dritte Site konnte den Benutzer nicht ohne einen Token imitieren, und der Benutzer, der zwei oder drei gültige Tokens hat, erleichtert dem Angreifer die Aufgabe nicht.

Wenn Sie das Front-End codieren, können Sie einen Ereignishandler für die document onUnload event registrieren und der Handler eine POST-Anfrage machen, die dem Server mitteilt, welches Token entladen wird. Auf diese Weise könnte das Backend das Token aus der Sitzung löschen. Das kann mehr Probleme bereiten, als es wert ist, denn wenn der Benutzer den BACK-Button des Browsers drückt, lädt er ein ungültiges Token neu und wird durch den Fehler frustriert, wenn sie das Formular abschickt.

Verwandte Themen