de.comp.lang.php.* FAQ

12.1. Wie unterscheide ich böse Variablen von guten?

Keywords: Sicherheit | Variablen | GET | POST | Cookie

Antwort von Kristian Köhntopp

Es ist im wesentlichen egal, wie die Daten in das lokale Programm kommen - GET, POST, COOKIE oder Request-Parameter spielt kaum eine Rolle. Es ist jedoch wesentlich, dass diese Variablen a) keine Variablen des lokalen Programmes unkontrolliert überschreiben können und b) dass der Übergang von solchen benutzerkontrollierten Variablen in lokale Variablen des Programmes nur nach einer Prüfung der Variablen auf legale Werte stattfindet. Das bedeutet:

  1. Variablen mit vorgegebenen Werten aus einer Wertemenge ("Auswahlvariablen"), wie sie zum Beispiel aus einem <select> fallen:

    Das Programm sollte ein lokales Array haben, das die möglichen Werte als Index eines Hash enthält:

    $val = array(
            "wert1" => 1,
            "wert2" => 1,
            "wert3" => 1
           );
    

    Die Prüfung von $_GET["selectvar"] kann nun so aussehen:

    $checkedvar = isset($val[$_GET["selectvar"]]) ? $_GET["selectvar"] : "default";
    

    Wenn $_GET["selectvar"] einen in $val definierten Wert hat, dann wird dieser Wert nach $checkedvar übernommen. Hat man versucht, dem Programm einen vierten Wert unterzuschieben, dann wird $checkedvar auf "default" gesetzt. Das Programm arbeitet dann ausschliesslich mit $checkedvar. Auf diese Weise können dem Programm keine beliebigen Werte aus $_GET["selectvar"] untergeschoben werden.

  2. Variablen, die eine bestimmte Form haben müssen, aber für die nicht die abgeschlossene Wertemenge aufgezählt werden kann ("Freitextvariablen mit Formvorschrift"):

    Das Programm sollte eine oder mehrere Regex in einem Feld vorliegen haben:

    $val = array(
                 '/^[a-zA-Z ]+$/',
                 '/^[0-9-]+$/'
                );
    

    Die Prüfung kann nun so aussehen:

    $checkedvar = "default";
    if (isset($_GET["inputvar"])) {
      foreach ($val as $k => $v) {
        if (preg_match($v, $_GET["inputvar"])) {
          $checkedvar = $_GET["inputvar"];
          break;
        }
      }
    }
    

    Wenn $_GET["inputvar"] einen Wert hat, der auf eines der Muster in $val passt, wird dieser Wert in $checkedvar übernommen. Dazu müssen die Muster in $val natürlich vorne und hinten verankert sein (also mit ^ beginnen und $ enden), sonst kann man der Prüfung etwas unterschmuggeln. Paßt kein Muster, hat $checkedvar hinterher den Wert "default". Das Programm arbeitet dann ausschliesslich mit $checkedvar. Auf diese Weise können dem Programm keine beliebigen Werte aus $_GET["selectvar"] untergeschoben werden.

  3. Variablen, die eine numerische Form haben müssen.

    Numerische Variablen können durch eine einfache Konvertierung erzwungen werden. Danach muss eine Überpruefung des Wertebereiches erfolgen:

    $checkedvar = isset($_GET["numericvar"]) ? $_GET["numericvar"]+0 : 0;
    

    Durch die Addition von 0 wird eine Konvertierung auf Integer erzwungen. Der Wert ist hinterher entweder Wert des numerischen Prefix von $_GET["numericvar"] oder 0. "123abc" wird also zu 123, "fasel" zu 0. Ein fehlender Wert wird durch das isset() ebenfalls zu 0.

  4. Variablen, die Dateinamennatur haben.

    Programme sollen oft Dateinamen, aber keine Pfadnamen annehmen. Eine Prüfung auf "/" im Dateinamen reicht oftmals als Sicherheitsprüfung aus. Zwingt man außerdem noch die Endung hinten dran, erschwert man die Ausnutzung von Sicherheitslücken zusätzlich, sollten dennoch welche vorhanden sein.

    $checkedvar = "default";
    if (isset($_GET["filenamevar"]) 
       && !preg_match('=/=', $_GET["filenamevar"])) {
       $checkedvar = $_GET["filenamevar"] . ".ext";
    }
    
  5. Templatenamen

    Templatenamen sind kein Spezialfall von Dateinamen oder Namen mit Formvorschrift, sondern ein Spezialfall von vorgegebenen Werten aus einer Liste und sollten wie der erste Fall behandelt werden. Danke.

  6. Benutzerinput, der Tags enthalten kann

    Cross Site Scripting Attacks sind Attacken, in denen eine Benutzereingabe aus einem Formular in die eigene Site als HTML, CSS oder anderer Formattext übernommen wird. Auf diese Weise kann der Benutzer eigene Elemente in unsere Website einbinden (etwa Bilder, Formulare oder Javascript von seiner Site), die einem Opfer dann als legitime Bestandteile unserer Site erscheinen und mit den Rechten unserer Site beim Opfer ausgeführt werden.

    strip_tags() auf GRUNDSÄTZLICH ALLE Benutzereingaben ist eine ausgesprochen gute Idee. Das schließt gegebenenfalls den Referer und andere benutzerkontrollierte Variablen mit ein! So existiert zum Beispiel eine Attacke gegen webalizer, bei der man einer Site Referer unterschiebt, die HTML enthalten. In der webalizer-generierten Referer-Statistik der Site erscheint dann feindseliges HTML!

Valid HTML 4.01! Valid CSS!

12.1. Wie unterscheide ich böse Variablen von guten?
http://www.php-faq.de/q/q-security-variablen.html
Archiv der de.comp.lang.php-FAQ Dies ist eine Archivseite von 2008 und wurde seitdem nicht geändert. Das dclp-FAQ-Team