Was sind Platzhalter in DBI und wozu brauche ich sie?
Inhalt:
Wahrscheinlich hat dir jemand gesagt, du sollst Platzhalter (engl. ''Placeholder'') in deinen SQL-Ausdrücken
verwenden. Jetzt verstehst du nicht, was das ist und wozu du es brauchst, oder die
DBI-Dokumentation dazu
leuchtet dir nicht ein.
Das Problem
Ein Datenbankzugriff erfolgt meist über ein SQL-Statement, der von der Datenbank ausgeführt wird.
Dabei enthält das Statement üblicherweise Teile, die aus Benutzeranfragen stammen.
Nehmen wir als Beispiel die Kontrolle eines Passworts, mit dem sich z.B. ein Nutzer über ein Webformular anmeldet:
# klassischer DB-Zugriff, aber NICHT EMPFEHLENSWERT!
my $sth = $dbh->prepare("SELECT id from user where pass='$pass'");
$sth->execute();
my $row = $sth->fetchrow_arrayref;
Nun kommt das Passwort
$pass an dieser Stelle offensichtlich vom Benutzer bzw. von dessen Browser.
Nehmen wir an, der User gibt nun in das Passwort aber nicht sein Passwort ein, sondern dies hier, inklusive
der Anführungszeichen:
' OR pass IS NOT NULL or pass = '
Dann lautet das resultierende Statement so:
SELECT id from user where pass='' OR pass IS NOT NULL or pass = ''
Der User ist dann eingeloggt, obwohl er kein gültiges Passwort eingegeben hat.
Diese Art eines Angriffs auf eine Web-Anwendung nennt man
SQL Injection.
Aber mit dieser Vorgehensweise könnte der Benutzer sogar noch mehr Schaden anrichten. Nehmen wir
an, er trägt als Passwort Folgendes ein:
'; DROP TABLE user; --
Das Ergebnis wäre sicherlich katastrophal.
Auf ähnliche Weise wurden in der ersten Jahreshälfte 2008 hunderttausende
von Websites weltweit angegriffen, verändert und teilweise gelöscht.
Hierbei droht nicht nur die Beschädigung der Datenbank, sondern bei entsprechend formulierten
SQL-Statements auch eine Offenlegung von allen in der Datenbank gespeicherten Daten, wie
Adressen, Zahlungsinformationen oder vielleicht auch Passwörter der Benutzer.
Generell ist es nicht empfehlenswert, Variablen direkt in SQL-Statements
zu benutzen, ob aus Benutzereingaben oder anderen Quellen, denn man muss
sich in jedem Falle darum kümmern, dass z.B. kein Anführungszeichen im Wert steht.
Die Lösung
Die DBI-Schnittstelle erlaubt es, Variablen in SQL-Statements durch
ein
Fragezeichen als Platzhalter zu ersetzen. Dem anschließenden
execute() Befehl werden dann die Variablen übergeben:
# Zugriff mit Platzhaltern, einfach und sicher
my $sth = $dbh->prepare("SELECT id from user where pass = ?");
$sth->execute($pass);
my $row = $sth->fetchrow_arrayref;
Hier wird
$pass dem
execute() übergeben und vom DBI-Treiber automatisch
gequotet. Fertig.
Diese Vorgehensweise hat noch den positiven Nebeneffekt, dass jedes SQL-Statement
nur einmalig vorbereitet werden muss und dann jeweils mit den gewünschten Werten
aufgerufen werden kann. Bei vielen gleichartigen Zugriffen kann dies den Datenbankzugriff
deutlich schneller machen.
Wenn man
do() statt
prepare() +
execute() verwendet, geht man folgendermaßen vor:
$dbh->do("UPDATE ... SET foo = ? where bar = ?", undef, 23, 24);
Das
undef steht hier nur an der Stelle eines Hashes, mit dem man noch
weitere Optionen mitgeben kann. Da wir keine weiteren Optionen
brauchen, übergeben wir einfach
undef.
--
TinaMueller
--
HaraldBongartz - 25 May 2008