MySQL-Injection

SQL injection ist eine Einschleusung von Code der die Datenbank möglicherweise zerstört

SQL injection ist eine von den meist genutzten Hacking Methoden

SQL injection bezeichnet das Einschleusen von bösartigen Code in die SQL-Statements mithilfe von Formulardaten in Webseiten

SQL Injection basierend auf 1=1 ist immer wahr (true)

Nehmen wir an, es soll innerhalb einer Webseite die UserId angegeben werden, um die jeweiligen Informationen des Users auszugeben.
Ist diese Eingabe nicht beschränkt, so kann der Benutzer eingeben was er will. Füllt er diese Eingabe „intelligent“ aus, so kann er die ursprüngliche Funktion des SQL-Statements vollkommen verändern.
z.B.:

Dadurch wird das SQL-Statement wie folgt verändert:

SELECT * FROM Users WHERE UserId = 105 OR 1=1;

Somit wird dieses SQL-Statement alle Zeilen der Tabelle Users zurückgeben, da ja OR 1=1 immer erfüllt ist.
Das wäre besonders heikel, falls die Users Tabelle Benutzernamen & Passwörter beinhaltet. Dann würde das manipulierte SQL-Statement dasselbe verursachen wie folgendes SQL-Statement:

SELECT UserID, Name, Passowrd FROM Users WHERE UserId=105 OR 1=1

Durch diese Manipulation würde der Hacker Zugriff zu allen Benutzernamen und Passwörter in der Datenbank erlangen, durch einfaches hinzufügen von OR 1=1.

bindParam()

Sicherer Code

if (isset($_POST["Senden"])) {
    echo "Schreibe neuen Eintrag...<br />";
 
    // Formulardaten übernehmen
    $name    = $_POST["name"];
    $strasse = $_POST["strasse"];
    $ort     = $_POST["ort"];
    $sorte   = $_POST["sorte"];
    $menge   = $_POST["menge"];
 
    try {
        // SQL-Anweisung mit Platzhaltern für sichere Datenübergabe
        $eintrag = "INSERT INTO bestellung (Name, Strasse, Ort, Sorte, Menge) 
                    VALUES (:name, :strasse, :ort, :sorte, :menge)";
 
        // SQL-Anweisung vorbereiten
        $stmt = $db->prepare($eintrag);
 
        // Daten an die Platzhalter binden
        $stmt->bindParam(':name', $name);
        $stmt->bindParam(':strasse', $strasse);
        $stmt->bindParam(':ort', $ort);
        $stmt->bindParam(':sorte', $sorte);
        $stmt->bindParam(':menge', $menge);
 
        // Ausführen der SQL-Anweisung
        if ($stmt->execute()) {
            echo "Eintrag in der Datenbank wurde erfolgreich vorgenommen!<br>";
            echo "<p>Folgende Angaben wurden gespeichert:</p>";
            echo "$name<br>";
            echo "$strasse<br>";
            echo "$ort<br>";
            echo "$menge kg $sorte<br>";
        } else {
            echo "Es gab ein Problem beim Einfügen der Daten.";
        }
    } catch (PDOException $e) {
        die("SQL-Fehler: " . $e->getMessage());
    }
}

Unsicheres Beispiel ohne bindParam()

Beim Beispiel Apfelbestellung kann man eine MySQL-Injection durchführen:

if (isset($_POST["Senden"])) {
    $name    = $_POST["name"];
    $strasse = $_POST["strasse"];
    $ort     = $_POST["ort"];
    $sorte   = $_POST["sorte"];
    $menge   = $_POST["menge"];
 
    // Unsicher: Direkte Einbindung der Benutzereingaben in die SQL-Anweisung
    $eintrag = "INSERT INTO bestellung (Name, Strasse, Ort, Sorte, Menge) 
                VALUES ('$name', '$strasse', '$ort', '$sorte', '$menge')";
 
    // SQL-Anweisung ausführen
    $db->exec($eintrag);
}

Gefährliche SQL-Injection

Angenommen, ein böswilliger Benutzer gibt in das Feld name die folgende Eingabe ein:

Max', 'Muster', 'Graz', 'Jonagold', 5); DELETE FROM bestellung; -- 

In diesem Fall würde die SQL-Abfrage, die an die Datenbank gesendet wird, wie folgt aussehen:

INSERT INTO bestellung (Name, Strasse, Ort, Sorte, Menge) 
VALUES ('Max', 'Muster', 'Graz', 'Jonagold', 5); DELETE FROM bestellung; --

Was passiert hier?

Konsequenzen:

Alle Bestellungen in der Tabelle bestellung werden gelöscht, was katastrophale Auswirkungen auf die Datenbank und das Unternehmen haben könnte.

Wie bindParam() schützt:

Bei Verwendung von bindParam() oder anderen vorbereiteten Statements würde diese Eingabe als reiner String behandelt werden, ohne die Möglichkeit, SQL-Befehle zu injizieren. Die manipulierte Eingabe würde also als Datensatz in der Datenbank gespeichert werden, anstatt schädlichen Code auszuführen.