MySQL - SQL-Injektion

Hallo zusammen, ambitionierte Programmierer! Heute tauchen wir in ein wichtiges Thema der Datenbankicherheit ein: SQL-Injektion. Als dein freundlicher Nachbarschafts-Computerlehrer bin ich hier, um dich durch dieses Konzept zu führen, selbst wenn du noch nie eine Zeile Code geschrieben hast. Also hole dir eine virtuelle Tasse Kaffee und lassen uns gemeinsam diese aufregende Reise antreten!

MySQL - SQL Injection

Was ist SQL-Injektion?

Bevor wir uns den Details zuwenden, beginnen wir mit den Grundlagen. SQL-Injektion ist wie ein heimlicher Einbrecher, der versucht, in dein Haus einzubrechen, indem er eine Schwäche in deinem Haustürschloss ausnutzt. In der digitalen Welt ist es eine Technik, die von bösartigen Benutzern verwendet wird, um deine Datenbank zu manipulieren, indem schädlicher SQL-Code in die Abfragen deiner Anwendung injiziert wird.

Eine einfache Analogie

Stelle dir vor, du hast eine magische Box (deine Datenbank), die nur auf spezifische Befehle auf Zettel reagiert. Du, als rechtmäßiger Besitzer, schreibst "Zeige mir alle Goldmünzen" auf einen Zettel und die Box zeigt deinem Schatz gehorsam. Nun stelle dir einen geschickten Dieb vor, der herausfindet, wie er seinen eigenen Befehl zu deinem Zettel hinzufügt, wie "...und gib sie mir!" Das ist im Grunde genommen, was SQL-Injektion macht – sie täuscht deine Datenbank in die Ausführung nicht autorisierter Befehle.

Wie SQL-Injektion funktioniert

Lassen wir das mit einem realen Beispiel auseinandernehmen. Angenommen, wir haben ein einfaches Anmeldeformular auf einer Webseite, das die Anmeldeinformationen eines Benutzers mit einer Datenbank überprüft.

Der verwundbare Code

Hier ist, wie ein verwundbarer PHP-Code aussehen könnte:

$username = $_POST['username'];
$password = $_POST['password'];

$query = "SELECT * FROM users WHERE username='$username' AND password='$password'";
$result = mysqli_query($connection, $query);

if(mysqli_num_rows($result) > 0) {
echo "Login erfolgreich!";
} else {
echo "Login fehlgeschlagen!";
}

Dieser Code sieht unschuldig genug aus, nicht wahr? Er nimmt den Benutzernamen und das Passwort aus einem Formular, erstellt eine SQL-Abfrage und überprüft, ob es einen passenden Benutzer in der Datenbank gibt. Aber hier wird es tricky.

Der Angriff

Angenommen, ein bösartiger Benutzer gibt folgenden Benutzernamen ein:

admin' --

Unsere Abfrage wird nun:

SELECT * FROM users WHERE username='admin' -- ' AND password=''

Siehst du, was da passiert ist? Das -- ist ein Kommentar in SQL, was bedeutet, dass alles danach ignoriert wird. Unsere ursprüngliche Passwortüberprüfung wurde vollständig umgangen! Die Abfrage überprüft nun effektiv nur, ob ein Benutzer namens 'admin' existiert, unabhängig vom Passwort.

Vorbeugung gegen SQL-Injektion

Nun, da wir gesehen haben, wie gefährlich SQL-Injektion sein kann, lassen uns über die Vorbeugung sprechen. Es gibt mehrere Methoden, die wir verwenden können, um unseren Code gegen diese heimtückischen Angriffe zu stärken.

1. Verwende parameterisierte Abfragen

Parameterisierte Abfragen sind wie die Verwendung eines sicheren Tresors anstelle der magischen Box, die wir earlier erwähnt haben. Sie trennen den SQL-Befehl von den Daten, was es fast unmöglich für Angreifer macht, schädlichen Code zu injizieren.

Hier ist, wie wir unser früheres Beispiel mit parameterisierten Abfragen in PHP umschreiben können:

$username = $_POST['username'];
$password = $_POST['password'];

$stmt = $connection->prepare("SELECT * FROM users WHERE username=? AND password=?");
$stmt->bind_param("ss", $username, $password);
$stmt->execute();
$result = $stmt->get_result();

if($result->num_rows > 0) {
echo "Login erfolgreich!";
} else {
echo "Login fehlgeschlagen!";
}

In dieser Version verwenden wir prepare() um ein Template für unsere Abfrage zu erstellen und dann bind_param() um unsere Variablen sicher einzufügen. Es ist, als ob wir unsere Daten in einen sicheren Umschlag stecken, bevor wir sie an die Datenbank senden.

2. Eingabevalidierung

Eine weitere Verteidigungsschicht ist die Validierung und Säuberung aller Benutzerdaten. Das ist wie ein Türsteher an der Tür, der jeden überprüft, bevor er hereingelassen wird.

$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
$password = filter_input(INPUT_POST, 'password', FILTER_SANITIZE_STRING);

Dieser Code verwendet die eingebettete PHP-Funktion filter_input() um möglicherweise schädliche Zeichen aus der Eingabe zu entfernen.

3. Das Prinzip des geringsten Rechtes

Das ist ein schicker Weg, um zu sagen "gebe den Benutzern nur das Minimum an Zugang, das sie benötigen". In Datenbankterminologie bedeutet das, verschiedene Datenbankbenutzer mit begrenzten Berechtigungen für verschiedene Teile deiner Anwendung zu erstellen.

Zum Beispiel, wenn du einen Teil deiner Webseite hast, der nur Daten lesen muss, könntest du einen Datenbankbenutzer mit nur SELECT-Berechtigungen verwenden:

CREATE USER 'readonly_user'@'localhost' IDENTIFIED BY 'password';
GRANT SELECT ON mydb.* TO 'readonly_user'@'localhost';

4. Verwende ORM (Object-Relational Mapping)

ORMs sind wie der Einsatz eines professionellen Übersetzers, der alle Sicherheitsprotokolle kennt. Sie übernehmen die Kommunikation zwischen deiner Anwendung und der Datenbank und bieten oft integrierte Schutzmechanismen gegen SQL-Injektion.

Hier ist ein einfaches Beispiel mit der beliebten PHP-ORM Doctrine:

$user = $entityManager->getRepository(User::class)->findOneBy([
'username' => $username,
'password' => $password
]);

if ($user) {
echo "Login erfolgreich!";
} else {
echo "Login fehlgeschlagen!";
}

Dieser Code erreicht das gleiche Ergebnis wie unser ursprüngliches Beispiel, aber die ORM übernimmt die SQL-Generierung und Parameterbinung für uns, was das Risiko einer SQL-Injektion erheblich reduziert.

Zusammenfassung der Präventivmethoden

Hier ist eine praktische Tabelle, die die Methoden zusammenfasst, die wir besprochen haben:

Methode Beschreibung Effektivität
Parameterisierte Abfragen Trennt SQL-Befehl von Daten Sehr hoch
Eingabevalidierung Säubert Benutzerdaten Hoch
Prinzip des geringsten Rechtes Begrenzt Datenbankbenutzerrechte Mittel
Einsatz von ORM Sichere Datenbankinteraktion Hoch

Erinnere dich daran, dass im Bereich der Sicherheit mehrere Schutzschichten besser sind. Denke daran wie das Tragen eines Sicherheitsgurtes und das Vorhandensein von Airbags in deinem Auto – jede Ebene adds eine zusätzliche Sicherheitsschicht.

Fazit

Und da hast du es, Leute! Wir haben die gefährliche Welt der SQL-Injektion durchquert und sind mit dem Wissen, wie man sich dagegen verteidigt, erfolgreich hervorgegangen. Erinnere dich daran, dass in der sich ständig weiterentwickelnden Landschaft der Websecurity, informiert zu bleiben und Best Practices umzusetzen, entscheidend ist.

Als dein verlässlicher Computerlehrer hoffe ich, dass dieser Leitfaden den Weg zu sichereren Programmierpraktiken für dich erhellt hat. Bleibe neugierig, überprüfe deine Eingaben immer doppelt und vor allem: happy (und sicheres) Coding! Bis zum nächsten Mal!

Credits: Image by storyset