SQL-Injection und Cross-Site-Scripting (XSS) gehören zu den häufigsten und gefährlichsten Sicherheitslücken in Webanwendungen. In diesem Tutorial lernen Sie, wie Sie sich mit modernen PHP-Methoden zuverlässig davor schützen.
Wichtiger Hinweis: Ältere Ansätze wie magic_quotes_gpc (entfernt seit PHP 5.4), get_magic_quotes_gpc() (entfernt seit PHP 7.4, Fatal Error in PHP 8.0+) oder addslashes() bieten keinen zuverlässigen Schutz und sollten nicht mehr verwendet werden.
SQL-Injection verhindern mit Prepared Statements
Der sicherste Weg, SQL-Injection zu verhindern, sind Prepared Statements mit Parameterbindung. Dabei werden SQL-Befehl und Daten strikt getrennt – die Datenbank kann eingeschleusten Code nicht als SQL-Befehl interpretieren.
Beispiel mit PDO (empfohlen)
<?php
$pdo = new PDO(
'mysql:host=localhost;dbname=meine_db;charset=utf8mb4',
'benutzer',
'passwort',
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
/** SICHER: Prepared Statement mit benannten Parametern */
$stmt = $pdo->prepare('SELECT * FROM benutzer WHERE email = :email');
$stmt->execute(['email' => $_POST['email']]);
$benutzer = $stmt->fetch(PDO::FETCH_ASSOC);
?>
Beispiel mit MySQLi
<?php
$mysqli = new mysqli('localhost', 'benutzer', 'passwort', 'meine_db');
$mysqli->set_charset('utf8mb4');
/** SICHER: Prepared Statement mit Parameterbindung */
$stmt = $mysqli->prepare('SELECT * FROM benutzer WHERE email = ?');
$stmt->bind_param('s', $_POST['email']);
$stmt->execute();
$ergebnis = $stmt->get_result();
$benutzer = $ergebnis->fetch_assoc();
?>
Was ist eine SQL-Injection?
Bei einer SQL-Injection schleust ein Angreifer schädlichen SQL-Code über ein Eingabefeld ein. Wird die Eingabe ungefiltert in eine SQL-Abfrage eingesetzt, kann der Angreifer Daten lesen, verändern oder löschen. Gibt ein Angreifer z.B. ' OR 1=1 -- als Benutzername ein, kann er die Abfrage manipulieren und sich ohne gültiges Passwort anmelden.
Cross-Site-Scripting (XSS) verhindern
XSS-Angriffe entstehen, wenn Benutzereingaben ohne Bereinigung im HTML ausgegeben werden. Ein Angreifer kann dadurch JavaScript-Code einschleusen, der im Browser anderer Besucher ausgeführt wird. Der Schutz ist einfach: Jede Ausgabe von Benutzerdaten muss mit htmlspecialchars() escaped werden.
<?php
/** UNSICHER - XSS möglich: */
echo $_GET['name'];
/** SICHER - XSS verhindert: */
echo htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8');
?>
Komplettes Beispiel: Sicheres Formular
<?php
$pdo = new PDO(
'mysql:host=localhost;dbname=meine_db;charset=utf8mb4',
'benutzer', 'passwort',
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
if ($name === '' || $email === '') {
$fehler = 'Bitte alle Felder ausfüllen.';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$fehler = 'Bitte eine gültige E-Mail-Adresse eingeben.';
} else {
/** SICHER: Prepared Statement gegen SQL-Injection */
$stmt = $pdo->prepare('INSERT INTO kontakt (name, email) VALUES (:name, :email)');
$stmt->execute(['name' => $name, 'email' => $email]);
$erfolg = 'Vielen Dank!';
}
}
?>
<!-- SICHER: htmlspecialchars() gegen XSS -->
<?php if (isset($fehler)): ?>
<p><?php echo htmlspecialchars($fehler, ENT_QUOTES, 'UTF-8'); ?></p>
<?php endif; ?>
Zusammenfassung
- SQL-Injection: Verwenden Sie ausschließlich Prepared Statements (PDO oder MySQLi) mit Parameterbindung.
- XSS: Escapen Sie jede Benutzerausgabe mit
htmlspecialchars($wert, ENT_QUOTES, 'UTF-8'). - Eingabevalidierung: Prüfen Sie Eingaben mit
filter_var() und trim(). - Zeichenkodierung: Verwenden Sie durchgängig UTF-8 (Datenbank, Verbindung, HTML).
- Veraltet: Nutzen Sie nicht
addslashes(), magic_quotes oder mysqli_real_escape_string() als alleinigen Schutz.