Das Löschen könnte so einfach sein: Ein Programm mit namen person_delete.php,
das als Parameter die id der Person erhält, die gelöscht werden soll:
$id = $_POST['id'];
$dbh->exec("DELETE FROM users WHERE id=$id" );
// NICHT so implementieren!
Dieses Programm ist anfällig für folgende Attacke. Alyssa P. Hacker (eine fiktive Hackerin)
benützt nicht das HTML-Formular unserer Applikation, sondern schreibt selbst ein Formular.
In dem Formular setzt sie den Parameter id auf Wert 9 OR 1=1.
<form method="post"
action="http://somedomain.at/person_delete.php">
<input type="hidden" value="9 OR 1=1" name="id"/>
<input type="submit" value="del all"/>
</form>
Das führt dazu, dass folgendes SQL-Statement ausgeführt wird:
DELETE FROM users WHERE id=9 OR 1=1
Und dieses Statement löscht nicht einen Datensatz sondern alle Datensätze. Diese Art von Attacke auf eine Web-Applikation nennt man „SQL Injection“, weil in das SQL etwas “injiziert” wird.
Dieses Problem kann vermeiden indem man die Eingabe genau überprüft. In diesem
Beispiel also: nur wenn es sich bei id um eine ganze Zahl handelt, darf sie
verwendet werde. Das kann man auf verschiedene Arten prüfen,
z.B. mit der Funktion filter_var:
if( ! $id = filter_var( $_GET['id'], FILTER_VALIDATE_INT ) ) {
echo("Hack detected: Police will arrive shortly.");
echo("variable id is false!");
exit;
}
Oft sieht man auch Eingabeprüfungen mit Regular Expressions - die müssen Sie noch nicht verstehen:
if( ! preg_match( '/^\d+$/', $id ) ) {
error_log("hack: $id statt id in person_delete.php.");
echo("Hack detected. Police will arrive shortly.");
exit;
}
Der zweite Ansatz ist die Verwendung von „Prepared Statements“ in der Datenbank. Dabei wird der SQL-Interpreter der Datenbank gänzlich umgangen.
Als erster Schritt wird mit prepare*
ein SQL-Statement mit Fragenzeichen als Platzhalter vorbereitet. Dieses
SQL-Statement wird vom Datenbank-Server sofort geparset und compiliert.
Mit execute*
wird das Statement ausgeführt, dabei werden die Platzhalter durch echte Daten
ersetzt. Das Schöne daran: es wird dabei nicht mehr ein SQL-Statement als
String gebaut, sondern die einzufügenden Daten werden binär an den
Datenbankserver übertragen. Darin enthaltene SQL-Fragement können keinen Schaden
anrichten.
$sth = $dbh->prepare("DELETE FROM users WHERE id = ?");
$sth->execute(array($id));
execute kann auch mehrfach ausgeführt werden, das ist effektiver als eine
normale query zu wiederholen.
Wir haben eine Sicherheitslücke geschlossen, aber es bleibt trotzdem noch viel zu tun: Löschen, Einfügen, Bearbeiten soll nur nach dem Login möglich sein!
/
#