PHP – Kanntest du schon? – SQL Injections

SQL Injections ist ein Thema seit jeher. Die Gefahr ist, dass man über Eingabefelder die SQL-Abfrage so manipulieren kann, um Zugriff auf andere Daten zu erhalten. Das ist einfacher als man denkt. Folgende Beispiel PHP Datei:

Als Beispieldatenbank nehme ich die Datenbank phplogin aus dem Artikel des PHP Login Projekt welche eine Tabelle account erhält. Hier stehen sehr sensible Informationen drin und wir können uns über das simple Query alle Account-Daten aus der Tabelle ausgeben lassen. Wie? Ganz einfach:

Normalerweise würden wir in das Input-Feld nur unsere E-Mail Adresse eintragen, ein Bösewicht (auch Cracker – fälschlicherweise Hacker) genannt könnte aber statt seine E-Mail die obige Zeile eingeben. Eigentlich sollte nur jeder User seine Daten als Ausgabe erhalten, doch folgende Ausgabe erhalten wir:

Wir erhalten alle Daten aus der Tabelle und zwar nicht nur für unseren Benutzer, denn durch die Eingabe hat sich das SQL-Statement von

in folgendes geändert:

Entweder ist die Mail leer, oder 1=1. 1=1 ist eine Bedingung, man könnte sie auch true nennen, die immer zutrifft und damit die Bedingung sofort erfüllt und das Statement ausführt.

Wie verhindert man SQL Injections?

Das Stichwort, bzw. die Stichwörter hier lauten: Prepared Statements. Wie der Name schon erahnen lässt gibt man hier die Daten nicht direkt als gesamtes SQL-Statement an den Datenbank Server. Vielmehr lässt man den Datenbankserver das Statement vorbereitet. Das tun wir, indem wir ihm folgendes SQL-Statement “preparen” lassen:

Er weiß jetzt was er machen soll, nämlich einen SELECT * aus der Tabelle account und als Bedingung wird eine email kommen. Der Server kann Vorbereitungen treffen hat aber noch keine konkreten Daten zum Ausführen dieses Befehls. Erst im zweiten Schritt lässt man den Datenbankserver dieses Statement ausführen und gibt ihm zeitgleich als Parameter die Daten mit, Ausschnitt:

Weil man beim PDO-Connector besser mit Prepared Statements arbeiten kann und dieser im Gegensatz zum MySQLi-Connector Named Parameters unterstützt und auch aus weiteren Gründen, habe ich in diesem Beispiel zur Prävention von SQL-Injection vom MySQLIi-Connector zum PDO-Connector gewechselt.

Der vollständige Code hier:

Geben wir nun unsere E-Mail Adresse ein, erhalten wir nur unsere Daten. Verwenden wir wieder den Teil für die SQL-Injection (siehe unten), erhalten wir eine leere Seite (weiß), weil intern ein Fehler geworfen wird der bei mir zumindest nicht direkt angezeigt wird.