Appearance
Kapitel 15: MySQL Sicherheit ⭐⭐
Sicherheit ist extrem wichtig für Datenbanken! In diesem Kapitel lernst du, wie man MySQL sicher macht.
15.1 SQL-Injection (SQL-Einschleusung) ⭐⭐ Wichtig!
SQL-Injection ist eine der häufigsten Sicherheitslücken bei Webseiten.
Was ist SQL-Injection?
Angreifer können bösartigen SQL-Code über Eingabefelder einschleusen.
Beispiel (Unsicher):
php
// ❌ Gefährlich! (SQL-Injection möglich)
$username = $_POST['username'];
$passwort = $_POST['passwort'];
$sql = "SELECT * FROM users
WHERE username = '$username'
AND passwort = '$passwort'";
// Angreifer gibt bei Username ein: ' OR '1'='1
// SQL wird zu:
// SELECT * FROM users WHERE username = '' OR '1'='1' AND passwort = '...'
// → Logged sich OHNE Passwort ein!Gefahren durch SQL-Injection
- ✅ Datenklau (Benutzernamen, Passwörter, Kreditkartennummern)
- ✅ Datenmanipulation (Löschen, Ändern von Daten)
- ✅ Datensatz-Löschung (komplettes Löschen der Tabelle)
- ✅ Administrator-Rechte erlangen
Schutzmaßnahmen ⭐⭐
1. Parametrisierte Abfragen (Prepared Statements) - Wichtigste Methode!
PHP-Beispiel (Sicher):
php
✅ Sicher! (Prepared Statements verwenden)
$stmt = $pdo->prepare("SELECT * FROM users
WHERE username = :username
AND passwort = :passwort");
$stmt->execute([
'username' => $username,
'passwort' => $passwort
]);
// → SQL-Injection unmöglich!Java-Beispiel (Sicher):
java
// ✅ Sicher! (Prepared Statements verwenden)
String sql = "SELECT * FROM users WHERE username = ? AND passwort = ?";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1, username);
stmt.setString(2, passwort);
ResultSet rs = stmt.executeQuery();2. Eingaben validieren und bereinigen
php
// ✅ Sicher! (Eingabe validieren)
$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
if (empty($username)) {
die('Ungültiger Benutzername!');
}3. Keine dynamischen SQL-Abfragen bauen
php
// ❌ Gefährlich!
$sql = "SELECT * FROM users WHERE username = '" . $_POST['username'] . "'";
// ✅ Sicher!
$sql = "SELECT * FROM users WHERE username = ?";4. Fehlermeldungen unterdrücken
php
// ❌ Gefährlich! (Zeigt Tabellenstruktur preis)
mysql_query($sql) or die(mysql_error());
// ✅ Sicher!
mysql_query($sql) or die('Ein Fehler ist aufgetreten.');15.2 Datenbank-Berechtigungsverwaltung (Für Einsteiger: Grundlegendes wissen)
MySQL verfügt über ein leistungsstarkes Berechtigungssystem.
1. Benutzer erstellen
sql
-- Benutzer erstellen
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'starkes_passwort_123';
-- Benutzer mit beliebigem Host erstellen (⚠️ Vorsicht!)
CREATE USER 'app_user'@'%' IDENTIFIED BY 'starkes_passwort_123';2. Berechtigungen gewähren (GRANT)
sql
-- Alle Berechtigungen auf alle Datenbanken gewähren (⚠️ Nicht empfohlen!)
GRANT ALL PRIVILEGES ON *.* TO 'app_user'@'localhost';
-- Nur Lesezugriff auf eine Datenbank gewähren
GRANT SELECT ON shop_db.* TO 'app_user'@'localhost';
-- Lese- und Schreibzugriff gewähren
GRANT SELECT, INSERT, UPDATE, DELETE ON shop_db.* TO 'app_user'@'localhost';
-- Berechtigungen aktivieren
FLUSH PRIVILEGES;3. Berechtigungen entziehen (REVOKE)
sql
-- Eine Berechtigung entziehen
REVOKE DELETE ON shop_db.* FROM 'app_user'@'localhost';
-- Alle Berechtigungen entziehen
REVOKE ALL PRIVILEGES ON *.* FROM 'app_user'@'localhost';4. Benutzer löschen
sql
DROP USER 'app_user'@'localhost';Best Practices für Berechtigungen
- ✅ Prinzip der geringsten Rechte (Least Privilege): Nur die unbedingt notwendigen Berechtigungen gewähren
- ✅ Keine Root-Berechtigungen für Anwendungen: Erstelle separate Benutzer für jede Anwendung
- ✅ Starke Passwörter: Verwende komplexe Passwörter für Datenbankbenutzer
- ✅ Berechtigungen regelmäßig überprüfen
15.3 Datenbank-Backup und -Wiederherstellung (Kernpunkt - Datenverlust verhindern)
Backups sind lebenswichtig! Wenn die Datenbank beschädigt wird oder Daten verloren gehen, ist ein Backup die einzige Rettung.
1. Backup erstellen (mysqldump)
Befehlzeile (Terminal / Eingabeaufforderung):
bash
# Ganze Datenbank sichern
mysqldump -u root -p shop_db > backup_shop_db.sql
# Mehrere Datenbanken sichern
mysqldump -u root -p --databases shop_db blog_db > backup_mehrere.sql
# Alle Datenbanken sichern
mysqldump -u root -p --all-databases > backup_alle.sqlMit phpMyAdmin:
- Datenbank auswählen
- "Export" klicken;
- "Schnell" oder "Benutzerdefiniert" wählen;
- "Ausführen" klicken →
.sql-Datei herunterladen.
2. Wiederherstellung (Restore)
Befehlzeile:
bash
# Wiederherstellung über die Befehlzeile
mysql -u root -p shop_db < backup_shop_db.sqlMit phpMyAdmin:
- Eine neue Datenbank erstellen (oder eine vorhandene auswählen);
- "Import" klicken;
.sql-Datei auswählen;- "Ausführen" klicken.
3. Automatisierte Backups (Cron Job / Task Scheduler)
Linux (Cron Job):
bash
# Jedes Mal um 2 Uhr morgens ein Backup durchführen
0 2 * * * mysqldump -u root -pMEIN_PASSWORT shop_db > /backups/shop_$(date +\%Y\%m\%d).sqlWindows (Task Scheduler):
- Einen Batch-Skript (
backup.bat) erstellen:batch@echo off set DATE=%date:~6,4%%date:~3,2%%date:~0,2% mysqldump -u root -pMEIN_PASSWORT shop_db > C:\backups\shop_%DATE%.sql - Den Taskplaner verwenden, um
backup.batregelmäßig auszuführen.
Praxisbeispiel: SQL-Injection verhindern
Szenario: Erstelle ein sicheres Login-Skript.
Unsicheres Skript (❌ Gefährlich!)
php
// login_unsafe.php
$username = $_POST['username'];
$passwort = $_POST['passwort'];
$sql = "SELECT * FROM users WHERE username = '$username' AND passwort = '$passwort'";
$result = mysqli_query($conn, $sql);Sicheres Skript (✅ Mit Prepared Statements)
php
// login_safe.php
$username = $_POST['username'];
$passwort = $_POST['passwort'];
// 1. Prepared Statement vorbereiten
$stmt = $conn->prepare("SELECT * FROM users WHERE username = ? AND passwort = ?");
$stmt->bind_param("ss", $username, $passwort); // "ss" = zwei Strings
// 2. Ausführen
$stmt->execute();
// 3. Ergebnis abrufen
$result = $stmt->get_result();Häufige Fehler für Einsteiger
Fehler 1: SQL-Injection ignorieren
php
// ❌ Falsch: Eingabe direkt in SQL einfügen
$sql = "SELECT * FROM users WHERE username = '" . $_GET['user'] . "'";
// ✅ Richtig: Prepared Statements verwenden
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$_GET['user']]);Fehler 2: Root-Benutzer in Anwendungen verwenden
sql
-- ❌ Falsch: Root-Benutzer in der Anwendung verwenden
$conn = new mysqli('localhost', 'root', 'root_passwort', 'shop_db');
-- ✅ Richtig: separaten Benutzer mit begrenzten Berechtigungen erstellen
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'starkes_passwort';
GRANT SELECT, INSERT, UPDATE, DELETE ON shop_db.* TO 'app_user'@'localhost';Fehler 3: Keine Backups erstellen
bash
# ❌ Falsch: Niemals ein Backup erstellen!
# → Bei Festplattenausfall: ALLE DATEN WEG!
# ✅ Richtig: Regelmäßig Backups erstellen!
mysqldump -u root -p shop_db > backup_$(date +%Y%m%d).sqlZusammenfassung
In diesem Kapitel hast du gelernt:
- ✅ Was SQL-Injection ist und wie gefährlich sie ist
- ✅ SQL-Injection zu verhindern (Prepared Statements)
- ✅ MySQL-Berechtigungen zu verwalten (Benutzer, GRANT, REVOKE)
- ✅ Datenbank-Backups zu erstellen (
mysqldump) - ✅ Datenbanken aus Backups wiederherzustellen
- ✅ Automatisierte Backups einzurichten
Übungen
- Theorie: Was ist SQL-Injection und wie kann man sie verhindern?
- Praxis: Erstelle ein sicheres PHP-Login-Skript mit Prepared Statements
- SQL: Erstelle einen neuen MySQL-Benutzer
webappmit nur Lese- und Schreibzugriff auftest_db - Praxis: Erstelle ein manuelles Backup deiner
shop_dbDatenbank - Praxis: Stelle die Datenbank aus dem Backup wieder her
Nächstes Kapitel
Im nächsten Kapitel lernen wir MySQL-Leistungsoptimierung - wie man Indizes verwendet, SQL-Abfragen optimiert und die Ausführungspläne analysiert!
