Donnerstag, 17. Juli 2014

Schutz gegen SQL-Injection: Prepared Statements

Um die Benutzereingaben eines HTML-Formulars zu verwerten, wird häufig PHP in Verbindung mit einer Datenbankanbindung verwendet. Damit lassen sich die eingegebenen Daten filtern und in der Datenbank speichern. Passt man dabei allerdings nicht gut auf, so wird man schnell Opfer eines Hacker-Angriffes. MySQL-Injection ist sehr häufig das Mittel der Wahl bei dem Versuch, sich unerlaubt Zugriff auf einen Webserver zu verschaffen. Um diese Sicherheitslücke zu schließen, sollte man in den eigenen PHP-Scripten mit sogenannten "prepared statements" arbeiten:


Dazu erstmal ein Negativbeispiel:

$sql = "SELECT * FROM tabelle WHERE username = '".$username."' AND password = '".$password."'";

Werden die Daten aus dem Formular mittels solchen MySQL-Anfragen an die Datenbank gesendet, so kann MySQL-Injection verwendet werden, um sich von außen unerlaubten Zugriff auf die Datenbank zu verschaffen. Da nämlich $username einen Wert enthält, der direkt von Benutzer eingegeben wurde, also einen beliebigen Wert haben kann, kann so die MySQL-Anfrage manipuliert werden. So ist es beispielsweise möglich, die eigentliche Anfrage durch den Wert der Variable $username abzuschließen und eine weitere Anfrage zu starten. Um das zu verhindern, verwendet man prepared statements:

$sql = "SELECT * FROM tabelle WHERE (username=?) AND (password=?)";

Das "?" ist hier jeweils ein Platzhalter für die Benutzereingaben, die dann erst später im Code hinzugefügt werden:

if($query = $db->prepare($sql)) {
  $query->bind_param("ss", $username, $password);
  $query->execute();
  // Das zurückgelieferte Ergebnis holen
  $result = $query->get_result();
  // Wenn mindestens ein Ergebnis-Datensatz: Datensätze in Schleife holen
  if(mysqli_num_rows($result>0)) {
    while($row = mysqli_fetch_array($result)) {
      echo $row['Spaltenname der Tabelle'];
    }
  }
  $query->close();
}

"ss" steht hierbei für "String String", da es sich im Beispiel bei beiden verwendeten Werten um Strings handelt. Dadurch, dass die Benutzereingaben also nicht direkt in die MySQL-Anfrage kopiert werden, kann MySQL-Injection nicht mehr angewendet werden.

Keine Kommentare:

Kommentar veröffentlichen

Share This