Einleitung: Warum ist SQL-Injection im Jahr 2025 immer noch relevant?
Stellen Sie sich vor: Sie haben eine coole Website mit PHP erstellt, ein Kontaktformular und eine Produktsuche hinzugefügt, und eine Woche später stellen Sie fest, dass ein Angreifer die gesamte Kundendatenbank heruntergeladen hat. Klingt wie eine Horrorgeschichte aus den 2010er Jahren? Leider gehört SQL-Injection laut OWASP immer noch zu den Top 3 der gefährlichsten Schwachstellen von Webanwendungen. Und ja, im Jahr 2025 machen Entwickler immer noch diesen Fehler.
Die Frage "How can I prevent SQL injection in PHP?" hat auf Stack Overflow tausende Aufrufe und hunderte Antworten gesammelt. Aber das Problem ist nicht der Mangel an Informationen – das Problem ist, dass viele immer noch veraltete Methoden wie mysql_*-Funktionen (die bereits in PHP 7.0 entfernt wurden) verwenden oder naiv auf mysqli_real_escape_string() als Allheilmittel vertrauen.
In diesem Artikel werden wir die besten Praktiken zum Schutz vor SQL-Injection in PHP im Jahr 2025 behandeln. Sie erfahren, warum Prepared Statements der Industriestandard sind, wie man richtig mit PDO und mysqli arbeitet und welche Fallstricke noch immer auf unerfahrene Entwickler warten. Los geht's!
Was ist SQL-Injection einfach erklärt?
SQL-Injection ist ein Angriff, bei dem ein Angreifer bösartigen SQL-Code über Benutzereingaben (Formulare, URLs, Cookies) in eine Abfrage "einschleust". Anstatt nur einen Benutzernamen zu übergeben, kann ein Hacker ' OR '1'='1 senden – und erhält Zugriff auf alle Daten.
Hier ist ein klassisches Beispiel für anfälligen Code:
// Machen Sie das NIEMALS so!$username = $_POST['username'];$password = $_POST['password'];$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";$result = mysqli_query($conn, $query);Wenn der Angreifer im Feld username Folgendes eingibt: admin' --, dann wird die Abfrage zu:
SELECT * FROM users WHERE username = 'admin' --' AND password = '...'Alles nach -- ist ein Kommentar. Die Authentifizierung ist bestanden. Die Datenbank gehört uns. Hallo, Datenleck!
Methode Nr. 1 (und die wichtigste): Prepared Statements
Im Jahr 2025 ist dies die einzige empfohlene Methode zum Schutz vor SQL-Injection. Prepared Statements trennen die SQL-Logik von den Daten. Sie sagen der Datenbank zuerst: "Hier ist eine Abfragevorlage, hier sind die Stellen für Variablen", und dann übergeben Sie die Daten separat. Die Datenbank escaped alles, was nötig ist, selbstständig.
Variante A: PDO (PHP Data Objects) – der moderne Standard
PDO unterstützt 12 verschiedene DBMS (MySQL, PostgreSQL, SQLite und andere). Wenn Sie im Jahr 2025 ein neues Projekt schreiben – verwenden Sie PDO.
<?php// Verbindung zur Datenbank über PDO$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8mb4';$user = 'root';$password = '';
try { $pdo = new PDO($dsn, $user, $password); // Wichtig: Ausnahmen bei Fehlern werfen $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);} catch (PDOException $e) { die('Verbindungsfehler: ' . $e->getMessage());}
// Prepared Statement mit benannten Platzhaltern$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email AND status = :status');$stmt->execute([ ':email' => $_POST['email'], ':status' => 'active']);$user = $stmt->fetch(PDO::FETCH_ASSOC);
// Alternative mit Positions-Platzhaltern (?)$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ? AND status = ?');$stmt->execute([$_POST['email'], 'active']);$user = $stmt->fetch();?>Warum ist das sicher? Weil die Daten niemals direkt in den SQL-String eingefügt werden. Selbst wenn der Benutzer ' OR '1'='1 übergibt, übergibt PDO dies als String-Literal, und die Datenbank interpretiert es genau als String, nicht als Teil des SQL-Befehls.