# SQL-Injection: Erklärung und Schutzmaßnahmen

SQL-Injections stellen für relationale Datenbankmodelle und die darin gespeicherten Informationen eine große Gefahr dar. Ein umfassender Schutz gegen diese unbefugten externen Zugriffe, die durch Sicherheitslücken möglich werden, ist daher essenziell.

## Was ist eine SQL-Injection?

Unter einer SQL-Injection (dt. SQL-Einschleusung) versteht man das Ausnutzen einer Sicherheitslücke in [relationalen Datenbanksystemen](https://www.ionos.at/digitalguide/hosting/hosting-technik/relationale-datenbanken/), die bei der Dateneingabe auf die Abfragesprache [SQL](https://www.ionos.at/digitalguide/server/knowhow/was-ist-sql/) zurückgreifen. Der Angreifer bzw. die Angreiferin macht sich dabei solche Benutzereingaben zunutze, die **nicht ausreichend maskiert** sind und **Metazeichen** wie den doppelten Bindestrich, Anführungszeichen oder das Semikolon enthalten. Diese Zeichen besitzen Sonderfunktionen für den SQL-Interpreter und erlauben die externe Beeinflussung der ausgeführten Befehle. Oft tritt eine SQL-Injection im Zusammenhang mit PHP- und ASP-Programmen auf, die auf ältere Interfaces zurückgreifen. Hier erhalten die Eingaben in einigen Fällen nicht die notwendige Maskierung und sind damit das perfekte Ziel für einen Angriff.

Mit dem gezielten Einsatz von Funktionszeichen kann ein unberechtigter User auf diese Weise weitere SQL-Befehle einschleusen und die Einträge derart manipulieren, dass er **Daten verändern, löschen oder lesen** kann. In gravierenden Fällen ist es sogar möglich, dass sich ein Angreifer auf diesem Wege den **Zugriff auf die Kommandozeile** des befehlsausführenden Systems und damit auf den gesamten Datenbankserver verschafft.

## SQL-Injection-Beispiele: So funktionieren die Datenbank-Angriffe

Da anfällige Datenbankserver schnell aufgespürt und SQL-Injection-Attacken ebenso einfach ausgeführt werden können, gehört die Methode weltweit zu den beliebtesten. Dabei agieren die Kriminellen mit **verschiedenen Angriffsmustern** und machen sich aktuelle, aber vor allem auch altbekannte Sicherheitslücken der am Datenmanagementprozess beteiligten Anwendungen zunutze. Um zu verdeutlichen, wie genau eine SQL-Injection funktioniert, folgen exemplarisch zwei typische Methoden.

## Beispiel 1: Zugriff über eine mangelhaft maskierte Benutzereingabe

Damit Benutzerinnen und Benutzer auf eine Datenbank zugreifen können, müssen sie sich für gewöhnlich zunächst authentifizieren. Zu diesem Zweck existieren Skripte, die beispielsweise ein **Login-Formular** bestehend aus Nutzername und Passwort präsentieren. User füllen das Formular aus und das **Skript überprüft** im Anschluss, ob in der Datenbank entsprechende Einträge existieren. Standardmäßig sind hierfür in der Datenbank eine Tabelle mit dem Namen `users` sowie den Spalten `username` und `password` angelegt. Bei einer beliebigen Webapplikation könnten die betreffenden Skriptzeilen (Python-Pseudocode) für den Webserver-Zugriff folgendermaßen lauten:

```python
uname = request.POST['username']
passwd = request.POST['password']
sql = "SELECT id FROM users WHERE username='" + uname + "' AND password='" + passwd + "'"
database.execute(sql)
```

Ein Angreifer hat nun die Möglichkeit, das **Passwortfeld per SQL-Injection gezielt zu manipulieren**, indem er beispielsweise `password' OR 1='1` eingibt, was zu folgender SQL-Abfrage führt:

```python
sql = "SELECT id FROM users WHERE username='' AND password='password' OR 1='1'"
```

Auf diese Weise erhält er vollen Zugriff auf die gesamte Nutzertabelle der Datenbank, da das **Passwort immer wahr** ist (`1='1'`). Loggt er sich nun **als Admin** ein, kann er beliebige Veränderungen an den Einträgen vornehmen. Alternativ kann auf dem gleichen Weg auch das Feld des Benutzernamens manipuliert werden.

## Beispiel 2: Daten ausspähen per ID-Manipulation

Informationen aus einer Datenbank per ID abzufragen ist eine praktische und gängige Methode, allerdings auch ein mögliches Einfallstor für eine SQL-Injection. So erfährt ein Webserver beispielsweise durch eine in der URL übermittelte ID-Angabe, welche Informationen er aus der Datenbank abrufen soll. Das dazu passende **PHP-Skript** sieht in etwa so aus:

```php
<?php
    $mysqli = new mysqli("localhost", "benutzername", "passwort", "datenbank");
    $id = intval($_GET['id']);
    $result = $mysqli->query("SELECT * FROM tabelle WHERE id=$id");
    while ($row = $result->fetch_assoc()) {
        echo print_r($row, true);
    }
?>
```

Die erwartete URL hat die Form `.../script.php?id=22`. In dem aufgeführten Fall würde der **Tabelleneintrag** mit der ID „22“ aufgerufen werden. Hat eine fremde Person nun die Gelegenheit, diese anfragende URL zu manipulieren und schickt dem Webserver stattdessen die Anfrage `…/script.php?id=22+OR+1=1`, bewirkt der daraus resultierende Aufruf, dass alle Daten der Tabelle ausgelesen werden:

```sql
SELECT * FROM tabelle WHERE id=22 OR 1=1;
```

## Wie finden Kriminelle gefährdete Datenbanksysteme?

Prinzipiell können alle Websites und Webanwendungen, die SQL-Datenbanken ohne vorbereitete Anfragen ([Prepared Statements](https://www.ionos.at/digitalguide/websites/web-entwicklung/prepared-statements-in-phpmysql/)) oder andere Schutzmechanismen nutzen, anfällig für SQL-Injections sein. Entdeckte Schwachstellen bleiben in den Weiten des World Wide Webs nicht lange geheim und so existieren beispielsweise Informationsseiten, die aktuelle Sicherheitslücken präsentieren und Kriminellen darüber hinaus auch gleich verraten, wie sie passende Webprojekte über die Google-Suche finden können. Falls eine Website detaillierte SQL-Fehlermeldungen zurückgibt, können Kriminelle diese nutzen, um potenzielle Schwachstellen zu identifizieren. So kann man einer URL mit enthaltenem ID-Parameter einfach ein Apostroph anhängen (wie im folgenden Beispiel):

```none
[Domainname].de/news.php?id=5‘
```

Eine angreifbare Website sendet dann eine Fehlermeldung zurück, die in etwa folgendermaßen lautet:

`Query failed: You have an error in your SQL Syntax …`

Zu Deutsch: „Abfrage gescheitert: Ihre SQL-Syntax ist fehlerhaft …“. Mit ähnlichen Methoden lassen sich auch die Spaltenanzahl, Tabellen- und Spaltennamen, SQL-Version oder gar Nutzernamen und Passwörter ausgeben. Mit verschiedenen Tools lassen sich die Suche und anschließende SQL-Injections darüber hinaus auch **automatisieren**.

## Wie Sie Ihre Datenbank vor SQL-Injection schützen

Sie können verschiedene Maßnahmen ergreifen, um SQL-Injection-Attacken auf Ihr Datenbanksystem zu verhindern. Dabei sollten Sie sich mit allen involvierten Komponenten – dem Server, den einzelnen Anwendungen sowie dem [Datenbankmanagementsystem](https://www.ionos.at/digitalguide/hosting/hosting-technik/datenbankmanagementsystem-dbms-erklaert/) – auseinandersetzen.

### Schritt 1: Die automatischen Eingaben der Applikationen überwachen

Bei der Verarbeitung von Eingaben durch externe oder eingebundene Applikationen ist es essenziell, die übermittelten Werte zu validieren und zu filtern, um SQL-Injections zu verhindern.

**1. Datentypen überprüfen**

Jede Eingabe sollte dem erwarteten Datentyp entsprechen. Falls beispielsweise eine numerische Eingabe erforderlich ist, kann eine einfache Validierung in PHP so aussehen:

```php
if (filter_var($input, FILTER_VALIDATE_INT) === false) {
    throw new InvalidArgumentException("Ungültige Eingabe");
}
```

Ähnliche Prüfungen sollten für Strings, Datumswerte oder andere spezifische Formate implementiert werden.

**2. Sonderzeichen filtern**

Spezielle Zeichen können Sicherheitslücken verursachen, insbesondere in SQL- oder HTML-Kontexten. Eine sichere Methode ist die Nutzung von `htmlspecialchars()` für HTML-Eingaben und von `PDO::quote()` für SQL-Anfragen.

**3. Fehlermeldungen vermeiden**

Direkte Fehlermeldungen, die technische Details über die Datenbank oder das System enthalten, sollten vermieden werden. Stattdessen empfiehlt sich eine generische Ausgabe wie:

```php
echo "Ein Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.";
error_log("Unerwarteter Fehler aufgetreten. Weitere Details siehe Systemlog.");
```

**4. Prepared Statements nutzen**

Eine sichere Möglichkeit, SQL-Injections zu verhindern, sind die bereits erwähnten **Prepared Statements**. Hierbei werden [SQL-Befehle](https://www.ionos.at/digitalguide/server/konfiguration/sql-befehle/) und Parameter getrennt übermittelt, sodass schädlicher Code nicht ausgeführt werden kann. Ein passendes Beispiel in PHP mit PDO (PHP Data Objects) sieht wie folgt aus:

```php
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->bindParam(':id', $user_id, PDO::PARAM_INT);
$stmt->execute();
```

Das Datenbankmanagementsystem sorgt automatisch für eine sichere Verarbeitung der Eingaben.

### Schritt 2: Für einen umfassenden Server-Schutz sorgen

Die Sicherheit des Servers, auf dem Sie Ihr Datenbankmanagementsystem ausführen, spielt natürlich auch bei der SQL-Injection-Prävention eine große Rolle. An erster Stelle steht hierbei das **Härten des Betriebssystems** nach dem bekannten Muster:

- Installieren bzw. aktivieren Sie nur solche Anwendungen und Dienste, die für den Betrieb der Datenbank relevant sind.
- Löschen Sie alle Benutzerkonten, die Sie nicht benötigen.
- Sorgen Sie dafür, dass alle relevanten System- und Programm-Updates installiert sind.
- Wenden Sie das Least-Privilege-Prinzip an, um sicherzustellen, dass User und Dienste nur die minimal erforderlichen Berechtigungen erhalten.

Je nach Sicherheitsanforderungen Ihres Webprojekts sollten zusätzliche Schutzmaßnahmen in Betracht gezogen werden:

- **[Intrusion-Detection-Systeme (IDS)](https://www.ionos.at/digitalguide/server/sicherheit/intrusion-detection-system-ids/) und [Intrusion-Prevention-Systeme (IPS)](https://www.ionos.at/digitalguide/server/sicherheit/intrusion-prevention-system-ips/)**: Diese Systeme arbeiten mit verschiedenen Erkennungsmethoden, **um Angriffe auf den Server frühzeitig zu erkennen**, Warnungen auszugeben und im Falle von IPS auch automatisch entsprechende Gegenmaßnahmen einzuleiten.
- **Application Layer Gateway (ALG)**: Ein ALG überwacht und filtert den Datenverkehr zwischen Anwendungen und Webbrowsern direkt auf Applikationsebene.
- **Web Application Firewall (WAF)**: Eine WAF schützt Webanwendungen gezielt vor SQL-Injection und [Cross-Site-Scripting (XSS)](https://www.ionos.at/digitalguide/websites/web-entwicklung/was-ist-xss-bzw-cross-site-scripting/), indem sie verdächtige Anfragen blockiert oder entschärft.
- **Zero-Trust-Ansatz**: Dieser moderne Sicherheitsansatz stellt sicher, dass jeder Zugriff, unabhängig von seiner Quelle, überprüft und verifiziert wird, bevor er zugelassen wird.
- **Firewall-Regelungen und Netzwerksegmentierung**: Diese Maßnahmen sind elementar, um die Angriffsfläche langfristig zu minimieren.
- **Regelmäßige IT-Sicherheitsaudits und [Penetrationstests](https://www.ionos.at/digitalguide/server/knowhow/penetrationstest-der-netzwerk-komplettcheck/)**: Diese helfen dabei, Schwachstellen frühzeitig zu erkennen und zu schließen.

### Schritt 3: Datenbank härten und sichere Codes verwenden

Wie auch Ihr Betriebssystem sollte die Datenbank von sämtlichen irrelevanten Faktoren befreit und regelmäßig aktualisiert werden. Entfernen Sie zu diesem Zweck alle gespeicherten Prozeduren, die Sie nicht benötigen und deaktivieren Sie alle unnötigen Dienste und Benutzerkonten. Richten Sie einen **speziellen Datenbank-Account** ein, der ausschließlich für den Zugriff aus dem Web vorgesehen ist und mit minimalen Zugriffsrechten auskommt.

Im Sinne der Prepared Statements ist es dringend zu empfehlen, das PHP-Modul `mysql` nicht zu verwenden (seit PHP 7 entfernt) und stattdessen `mysqli` oder PDO zu wählen. Auf diese Weise können Sie sich zusätzlich auch mit sicheren Codes schützen. Eine sichere `mysqli`-Abfrage sieht beispielsweise folgendermaßen aus:

```php
$mysqli = new mysqli("localhost", "benutzer", "passwort", "datenbank");
if ($mysqli->connect_error) die("Verbindung fehlgeschlagen");
$stmt = $mysqli->prepare("SELECT password FROM users WHERE username = ?");
$stmt->bind_param("s", $_POST['username']);
$stmt->execute();
$stmt->bind_result($hashedPassword);
if ($stmt->fetch() && password_verify($_POST['password'], $hashedPassword)) {
    echo "Login erfolgreich";
} else {
    echo "Falsche Zugangsdaten";
}
$stmt->close();
$mysqli->close();
```

Zudem sollten Passwörter niemals direkt in einer Datenbank gespeichert oder als Klartext abgefragt werden. Verwenden Sie stattdessen eine Hashing-Methode wie `password_hash()` in Kombination mit `password_verify()`, um die Kennwörter optimal zu schützen. Eine sichere Lösung könnte folgendermaßen aussehen:

```php
$mysqli = new mysqli("localhost", "benutzer", "passwort", "datenbank");
$stmt = $mysqli->prepare("SELECT password FROM users WHERE username = ?");
$stmt->bind_param("s", $_POST['username']);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
if ($row && password_verify($_POST['password'], $row['password'])) {
    echo "Login erfolgreich!";
} else {
    echo "Falscher Benutzername oder falsches Passwort.";
}
```

## Bobby Tables: SQL-Injection im Comicstil erklärt

Auf der Seite [bobby-tables.com](https://bobby-tables.com/ "Bobby Tables Website") hat man sich anhand eines xkcd-Webcomics mit der Thematik unsicherer **Datenbank-Benutzereingaben** auseinandergesetzt. Der Comic zeigt eine Mutter, die einen Anruf von der Schule ihres Sohnes – liebevoll „Klein Bobby Tables“ genannt – erhält. Sie bejaht die Frage, ob ihr Sohn tatsächlich `Robert'); DROP TABLE Students;– –` hieße und erfährt im Anschluss den Hintergrund für den Anruf: Der Versuch, einen Eintrag für Robert in der Schülerdatenbank zu erstellen, führte dazu, dass der komplette Datenbestand gelöscht wurde. Roberts Mutter hat daraufhin nur wenig tröstende Worte übrig und äußert ihre Hoffnung, dass die Schule aus dem Fehler gelernt hat und die Eingaben in die Datenbank zukünftig bereinigen wird.

Der Comic zeigt eindrücklich, welche fatalen Folgen nicht überprüfte Benutzereingaben in Datenbanken haben können.


This is a markdown version of: [https://www.ionos.at/digitalguide/server/sicherheit/sql-injection-grundlagen-und-schutzmassnahmen/](https://www.ionos.at/digitalguide/server/sicherheit/sql-injection-grundlagen-und-schutzmassnahmen/) for AI/LLM consumption.