Heim  >  Artikel  >  Backend-Entwicklung  >  CSRF-Verteidigungsbeispiel (PHP)

CSRF-Verteidigungsbeispiel (PHP)

高洛峰
高洛峰Original
2016-10-17 10:44:481377Durchsuche

CSRF-Verteidigung kann sowohl serverseitig als auch clientseitig durchgeführt werden. Der Verteidigungseffekt ist serverseitig besser.

 1. Serverseitige CSRF-Verteidigung

Es gibt viele Möglichkeiten, CSRF auf der Serverseite zu implementieren, aber die Grundidee ist dieselbe, nämlich das Hinzufügen von Pseudozufallszahlen zum Client Seite.

 (1). Cookie-Hashing (alle Formen enthalten den gleichen Pseudozufallswert):

 Dies ist möglicherweise die einfachste Lösung, da der Angreifer (theoretisch) keine Cookies von Drittanbietern erhalten kann. Daher können die Daten im Formular nicht erstellt werden: >

<?php
   //构造加密的Cookie信息
   $value = “DefenseSCRF”;
   setcookie(”cookie”, $value, time()+3600);
 ?>

Fügen Sie dem Formular einen Hash-Wert hinzu, um zu überprüfen, ob es sich tatsächlich um eine vom Benutzer gesendete Anfrage handelt.

<?php
  $hash = md5($_COOKIE[&#39;cookie&#39;]);
?>
<form method=”POST” action=”transfer.php”>
  <input type=”text” name=”toBankId”>
  <input type=”text” name=”money”>
  <input type=”hidden” name=”hash” value=”<?=$hash;?>”>
  <input type=”submit” name=”submit” value=”Submit”>
</form>

Führen Sie dann eine Hash-Wert-Überprüfung auf der Serverseite durch.

    <?php
        if(isset($_POST[&#39;check&#39;])) {
             $hash = md5($_COOKIE[&#39;cookie&#39;]);
             if($_POST[&#39;check&#39;] == $hash) {
                  doJob();
             } else {
        //...
             }
        } else {
      //...
        }
      ?>

Ich persönlich bin der Meinung, dass diese Methode 99 % der CSRF-Angriffe eliminieren kann, sodass immer noch 1 % übrig bleibt. .. Da die Cookies der Benutzer aufgrund von XSS-Schwachstellen der Website leicht gestohlen werden können, sind es weitere 1 %. Die meisten Angreifer werden grundsätzlich aufgeben, wenn sie die Notwendigkeit sehen, Hash-Werte zu berechnen, mit Ausnahme einiger weniger. Wenn Sie es also zu 100 % eliminieren müssen, ist dies nicht die beste Methode.

 (2). Bestätigungscode

Die Idee dieser Lösung ist: Jedes Mal, wenn der Benutzer etwas sendet, muss er eine zufällige Zeichenfolge in das Bild im Formular eintragen, äh ... diese Lösung kann CSRF vollständig lösen, aber ich persönlich bin der Meinung, dass sie in Bezug auf die Benutzerfreundlichkeit nicht sehr gut ist. Ich habe auch gehört, dass die Verwendung von Bestätigungscode-Bildern einen Fehler namens MHTML beinhaltet, der in einigen Fällen betroffen sein kann Versionen von Microsoft IE.

 (3).Einmalige Token (verschiedene Formen enthalten einen unterschiedlichen pseudozufälligen Wert)

Bei der Implementierung von Einmal-Tokens müssen Sie auf eines achten: „Parallelsitzung“. Kompatibilität" ". Wenn ein Benutzer gleichzeitig zwei verschiedene Formulare auf einer Website öffnet, sollten CSRF-Schutzmaßnahmen keinen Einfluss auf die Übermittlung eines Formulars haben. Überlegen Sie, was passieren würde, wenn die Website bei jedem Laden eines Formulars einen Pseudozufallswert generieren und den vorherigen Pseudozufallswert überschreiben würde: Der Benutzer könnte nur das zuletzt geöffnete Formular erfolgreich senden, da alle anderen Formulare einen illegalen Pseudozufallswert enthalten würden. Es muss darauf geachtet werden, dass der CSRF-Schutz das Browsen mit Registerkarten oder die Verwendung mehrerer Browserfenster zum Durchsuchen einer Website nicht beeinträchtigt.

Das Folgende ist meine Implementierung:

1). Zuerst die Token-Generierungsfunktion (gen_token()):

 <?php
     function gen_token() {
     //这里我是贪方便,实际上单使用Rand()得出的随机数作为令牌,也是不安全的。
    //这个可以参考我写的Findbugs笔记中的《Random object created and used only once》
          $token = md5(uniqid(rand(), true));
          return $token;
     }

2). (gen_stoken()):

     <?php
       function gen_stoken() {
      $pToken = "";
      if($_SESSION[STOKEN_NAME]  == $pToken){
        //没有值,赋新值
        $_SESSION[STOKEN_NAME] = gen_token();
      }    
      else{
        //继续使用旧的值
      }
       }
     ?>

3). WEB-Formularfunktion zum Generieren versteckter Eingabefelder:

     <?php
       function gen_input() {
            gen_stoken();
            echo “<input type=\”hidden\” name=\”" . FTOKEN_NAME . “\”
                 value=\”" . $_SESSION[STOKEN_NAME] . “\”> “;
       }
     ?>

4). 🎜> 5). Serverseitiges Verifizierungstoken:

     <?php
          session_start();
          include(”functions.php”);
     ?>
     <form method=”POST” action=”transfer.php”>
          <input type=”text” name=”toBankId”>
          <input type=”text” name=”money”>
          <? gen_input(); ?>
          <input type=”submit” name=”submit” value=”Submit”>
     </FORM>
Das ist sehr einfach, daher werde ich hier nicht auf Details eingehen.

Tatsächlich entspricht das Obige nicht vollständig den Regeln zur „Parallelsitzungskompatibilität“. Sie können es auf dieser Grundlage ändern.

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn