- Der Computer erlaubt es uns, Fehler schneller zu machen als jede andere Erfindung, vielleicht mit der Ausnahme von Handfeuerwaffen und Tequila.
- -- Mitch Ratcliffe
So jetzt kommt mal wieder einer, den der
Geek in mir geschrieben hat. Wer also nicht programmiert, kann sich beruhigt den Rest des Artikels sparen.
Man ließt in der einschlägigen Presse immer wieder etwas von Lücken in zum Beispiel Websystemen, bei denen der Angriff über den Mechanismus der sogenannten
SQL-Injektion.
Mir ist das immer etwas schleierhaft. Vermutlich ist mein Denken in dieser sicherheitsrelevanten Frage wohl zu einfach gestrickt, aber ich sehe da nur ein kleines Fallstrickchen und das war es dann auch schon. Das Riesenproblem, was da immer wieder von gemacht wird, erinnert mich an das Sprichwort von der Mücke und dem Elefanten.
Nochmal ganz kurz die Erläuterung des Problems aus Programmierersicht anhand eines kurzen Beispiels. Dazu wollen wir annehmen, dass wir per SQL das Passwort eines Benutzers überprüfen wollen. Ich verwende dazu die PHP-Syntax, das ganze habe ich aber auch schon in mehreren Programmiersprachen umgesetzt:
function getPassword( $user )
{
$sql = "SELECT password FROM users WHERE login = '$user'";
[... ab hier wird jetzt die SQL-Anweisung ausgeführt, das Passwort geholt und zurückgegeben ...]
}
Das Problem hier ist, wenn sich ein Benutzer unter dem Namen "'; DROP TABLE users; --" anmeldet, wird die SELECT-Anweisung irrelevant, und der DROP TABLE sorgt dafür, dass sämtliche Benutzerdaten weg sind. Böse Sache, aber definitiv mit einfachsten Mitteln verhinderbar. Da drängt sich einem natürlich die Frage auf: wie bekommt man denn überhaupt ein Hochkomma in die Datenbank? Der SQL-Standard sieht vor, dass dann ganz einfach doppelt (also zwei Stück hintereinander) zu schreiben sind.
Daraus folgt, dass alles was man tun muss ist bei jeder Zeichenkette, die in die Datenbank soll, einfach nur das einzelne Hochkomma gegen zwei aufeinanderfolgende auszutauschen. Das war es schon. In PHP gibt es sogar die Möglichkeit, dass komplett automatisch machen zu lassen. Ich schalte das immer gleich als erstes ab, weil es mehr Probleme gibt, als dass es was nützt. Stattdessen verwende ich eine Ersetzungsfunktion für Zeichenketten:
function getPassword( $user )
{
$quser = ereg_replace("'","''",$user);
$sql = "SELECT password FROM users WHERE login = '$quser'";
[... ab hier wird jetzt die SQL-Anweisung ausgeführt, das Passwort geholt und zurückgegeben ...]
}
Das war es schon. Ist das wirklich so einfach, oder habe ich da etwas übersehen?
Kommentare
Unter PHP ist die offizielle Loesung meines Wissens die *_real_escape_string() Funktion, die Deinen Trick Datenbankspezifisch anwendet.
http://lwn.net/Articles/185813/
http://xkcd.com/327/
:-)
Mittlerweile esacpe ich den Input auch nicht mehr per Hand, sondern per php-Funktion (im sqlite-Fall dann per sqlite_escape_string). Allerdings habe ich das Verhalten bei illegalen Multibyte Sequenzen noch nicht getestet. ;-)