====== 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** {{:inf:inf8bi_201819:2:pasted:20190523-180706.png?direct}} {{:inf:inf8bi_201819:2:pasted:20190523-182247.png?direct}} ==== 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.: {{:inf:inf8bi_201819:2:pasted:20190523-181646.png?direct}} 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...
"; // 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!
"; echo "

Folgende Angaben wurden gespeichert:

"; echo "$name
"; echo "$strasse
"; echo "$ort
"; echo "$menge kg $sorte
"; } else { echo "Es gab ein Problem beim Einfügen der Daten."; } } catch (PDOException $e) { die("SQL-Fehler: " . $e->getMessage()); } }
* Sichere Datenübergabe (SQL-Injection-Vermeidung): Wenn Daten direkt in eine SQL-Abfrage eingefügt werden, ohne diese zu "escapen", können böswillige Benutzer die Abfrage manipulieren, um Datenbankbefehle auszuführen, die nicht beabsichtigt sind (z. B. Löschen von Datensätzen). Die Verwendung von Platzhaltern (:name, :strasse, etc.) und das Binden der Werte mit bindParam() sorgt dafür, dass die Daten als reine Werte behandelt und nicht als Teile des SQL-Codes interpretiert werden. * Automatisches Escapen von Sonderzeichen: bindParam() kümmert sich darum, dass Sonderzeichen in den Benutzereingaben (z. B. Anführungszeichen) korrekt "escaped" werden, sodass sie keine Probleme in der SQL-Abfrage verursachen. * Flexibilität bei der Datenbindung: bindParam() ermöglicht es, Daten in der SQL-Abfrage dynamisch zur Laufzeit zu binden. Das ist besonders nützlich, wenn der Wert erst im Laufe der Programmausführung bestimmt wird. In diesem Fall werden die Variablen, die die Formulardaten enthalten, an die entsprechenden Platzhalter in der Abfrage gebunden. ==== 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?** * Manipulierte Eingabe: Der Benutzer hat absichtlich eine Eingabe gemacht, die einen böswilligen SQL-Befehl enthält. Das '; beendet den ersten VALUES()-Block, und der Befehl DELETE FROM bestellung; wird direkt an die Datenbank angehängt. * Schadcode: Nach dem Einfügen der Daten führt die Datenbank den DELETE FROM bestellung;-Befehl aus, der alle Datensätze in der Tabelle bestellung löscht. * Das -- Kommentarzeichen: Alles, was nach -- kommt, wird von SQL als Kommentar ignoriert, sodass keine Syntaxfehler entstehen. In diesem Fall werden die restlichen SQL-Befehle nach dem DELETE ignoriert. Wichtig: Nach dem Kommentarzeichen muss ein Leerzeichen stehen. **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.