SQL-Injection verstehen und vermeiden

SQL-Injection verstehen und vermeidenEine Einführung für PHP-Anwendungen

Was ist eine SQL-Injection?

Eine SQL-Injection ist eine der gefährlichsten Schwachstellen in datenbank-basierenden Webanwendungen. Sie tritt auf, wenn Benutzereingaben ungefiltert in SQL-Datenbankabfragen eingebaut werden. Ein Angreifer kann so eigene SQL-Befehle einschleusen und z. B. vertrauliche Daten auslesen, löschen oder manipulieren.

Beispiel einer unsicheren Abfrage:

$unsafe_query = "SELECT * FROM users WHERE email = '" . $_GET['email'] . "'";

Gibt ein Angreifer als Parameter einer PHP-Seite z. B. ein:

?email=' OR 1=1

wird daraus der SQL-Befehl

"SELECT * FROM users WHERE email = '' OR 1=1"

Die WHERE-Klausel wird also unwirksam, da der logische Vergleich 1=1 stets wahr ist.
Daher werden alle Benutzer werden angezeigt.

Als Parameter sind weitere SQL-Anweisungen möglich, die realen Schaden, bis hin zu Datenverlusten, anrichten können.

Wie kann man SQL-Injection in PHP vermeiden?

  • Prepared Statements (empfohlen!)
    Verwendung von vorbereiteten SQL-Befehle mit Platzhaltern. Automatisches Escaping schützt vor Manipulation.
  • Eingabevalidierung
    Stellt sicher, dass Benutzereingaben nur erlaubte Werte enthalten (z. B. E-Mail-Format, Zahlen etc.).
  • Whitelisting
    Bei dynamischen Parametern (z. B. Sortierung) sollten nur vordefinierte Werte erlaubt werden.

Best Practice mit mysqli:

$mysqli = new mysqli("localhost", "user", "pass", "datenbank");
$stmt = $mysqli->prepare("SELECT * FROM users WHERE email = ?");
$stmt->bind_param("s", $_GET['email']);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
    echo $row['name'];
}

Best Practice mit PDO:

$pdo = new PDO("mysql:host=localhost;dbname=datenbank", "user", "pass");
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$_GET['email']]);
foreach ($stmt as $row) {
    echo $row['name'];
}

Weitere Information zu 'Prepared Statements':

Fazit:

Eine SQL-Injection ist leicht vermeidbar, wenn man bewährte Methoden wie Prepared Statements anwendet.

Alte Methoden mit Stringverkettung einzel gefilterter Parameter sollten wenn möglich vermieden werden.
u schnell übersieht man im eigenen Filter ein problematisches Zeichen, vor allem wenn noch Zeichensatzabhängigkeiten hinzukommen.

Prepared Statements innerhalb des PHP-Codes erlauben eine sichere Vorgehensweise.