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

UtilFaqSubForm edit

Titel Was sind Platzhalter in DBI und wozu brauche ich sie?
Autor TinaMueller
Bereich FaqDatenbanken
Tags DBI, Platzhalter
Topic revision: r6 - 2008-05-25 - 19:31:00 - HaraldBongartz
 
Bitte die NutzungsBedingungen beachten.
Bei Vorschlägen, Anfragen oder Problemen mit dem PerlCommunityWiki bitten wir um WebBottomBarExample">Rückmeldung.