SQL Injection
Wie schütze ich mich davor?


Bei SQL Injection werden Sicherheitslücken beim Zugriff auf Datenbanken ausgenutzt. Dabei wird versucht, an sensible Daten zu kommen oder diese zu ändern/manipulieren.


SQL Injection


Wie funktioniert SQL Injection?


Wird serverseitig auf die Datenbank zugegriffen, werden häufig Daten/Informationen von Usern mit in die Abfrage eingebaut. Wenn der User die Daten/Eingabe so manipuliert, dass diese einen Datenbankcode ergeben, so kann sich der User Zugriff auf die Datenbank verschaffen.


Einfaches Beispiel:

Eine Website, auf welcher Websitebesucher uns einen Gästebucheintrag hinterlassen können.


Usereingaben Gästebuch

Usereingaben werden für die Datenbankabfrage verwendet



Diese Felder können verwendet werden, um den Datenbankcode zu ändern und kontrolliert auf die Datenbank zugreifen zu können.


Manipulierte Eingaben Gästebuch

Manipulierte Eingaben

Wie schütze ich mich vor SQL Injection?


Serverseitig

Niemals und wirklich nie den Eingaben eines Users vertrauen.


Prepared Statements

Im Backend und beim Zugriff auf die Datenbank Prepared Statements verwenden.


Bei Prepared Statements wird vorab der Zugriff definiert, wobei die Daten/Parameter separat in die Abfrage hinzugefügt werden. Beim Hinzufügen werden diese auf Richtigkeit überprüft und bereinigt.


Nahezu alle Programmiersprachen bieten Frameworks bzw. Erweiterungen an, um den Zugriff auf Datenbanken über Prepared Statements zu ermöglichen. Hier gilt, stets aktuelle Technologien auf dem neuesten Stand und richtig zu verwenden, um die Sicherheit der Daten zu gewährleisten.


Beispiel für PHP:

PHP-Beispiel, bei dem keine Prepared Statements verwendet werden und der User somit die Möglichkeit hat, auf die Datenbank zuzugreifen. (Die Parameter werden direkt und ohne Überprüfung in die Datenbankabfrage eingebaut.)


'''php

$message = $_POST["message"];
$from = $_POST["from"];

$query = "INSERT INTO 'guestbook' ('message', 'from') VALUES ('$message', '$from')";
$pdo->query($query);

'''

Verwendung von Prepared Statements mittels PHP Data Objects (PDO) extension. Die Parameter/die Eingaben des Users werden separat in die Abfrage eingebaut.


'''php

$message = $_POST["message"];
$from = $_POST["from"];

$query = "INSERT INTO 'guestbook' ('message', 'from') VALUES (:message, :from)";

$statement = $connection->prepare($query);
$statement->bindParam(':message', $message, PDO::PARAM_STR);
$statement->bindParam(':from', $from, PDO::PARAM_STR);

$result = $statement->execute();

'''

Beispiel näher betrachtet:

Unsere Website verwendet im Hintergrund eine einfache Datenbank mit zwei Tabellen. Eine für Gästebuch-Einträge und eine für unsere User.


Datenbank Struktur
Datenbank Struktur


Werden keine Prepared Statements für den Datenbankzugriff verwendet, haben Websitebesucher eine Möglichkeit, auf unsere Datenbank zuzugreifen (wie im ersten Codebeispiel für PHP).

Bob fügt einen normalen Eintrag ein


Gästebucheintrag


Gästebucheintrag


Alice löscht den Eintrag von Bob

Mittels SQL Injection schafft Alice es, den Eintrag von Bob wieder zu löschen.


Gästebucheintrag SQL Injection


Gästebucheintrag SQL Injection


Alice kopiert alle User in das Gästebuch

Mittels SQL Injection kann Alice Einträge von einer Tabelle in eine andere kopieren.


Gästebucheintrag SQL Injection


Gästebucheintrag SQL Injection


Nun sind alle Userdaten für alle Seitenbesucher sichtbar!


Werden im Backend Prepared Statements verwendet...

... sieht ein Angriffsversuch von Alice wie folgt aus:


Gästebucheintrag SQL Injection


Gästebucheintrag SQL Injection


Der vermeintliche Code, welcher eine Tabelle löschen würde, wird einfach als Text in die Datenbank gespeichert.


Relevante Vorfälle


Unter anderem wurden folgende große Unternehmen Ziel eines SQL-Injection-Angriffs:

  • ThePirateBay   |   2010   |   4 Millionen User-Details geleakt
  • Sony Pictures   |   2011   |   1 Million Accounts geleakt
  • Yahoo   |   2012   |   450.000 Plaintext-Passwörter geleakt




SQL Injection löscht Tabelle

Bildquelle XKCD

Weitere Maßnahmen


  • Regelmäßig Updates der Datenbank erstellen, um vor einem Verlust von Tabellen und Daten geschützt zu sein.
  • Niemals Passwörter in Plaintext speichern. Hashe die Passwörter und vergleiche die Hash-Werte bei der Authentifikation.
  • Encrypted Storage: Relevante und kritische Daten in der Datenbank verschlüsseln.
  • Frameworks und Erweiterungen wie auch das Backend immer am aktuellen Stand halten.
  • Datenbanken sowie Dumps (=Backups) nie öffentlich zugängig machen.