XSS verhindern in PHP – Ausgaben richtig escapen mit htmlspecialchars
SQL-Injection verhinderst du mit Prepared Statements – aber der andere große Angriff, XSS, passiert bei der AUSGABE. Ich zeige dir, warum du jede dynamische Ausgabe mit htmlspecialchars und ENT_QUOTES escapen musst und wie ein kurzer Helfer das übernimmt.
Prepared Statements schützen deine Datenbank vor SQL-Injection. Der zweite große Angriff, Cross-Site-Scripting (XSS), passiert an einer ganz anderen Stelle: bei der Ausgabe. Gibst du Nutzertext ungeprüft ins HTML, kann jemand <script>-Code einschleusen, der im Browser deiner Besucher läuft.
Das Problem
// Ein Besucher trägt als Namen ein: <script>stehleCookie()</script>
echo "Hallo " . $_GET['name']; // 💥 der Code wird im Browser ausgeführtDie Lösung: escapen bei der Ausgabe
echo "Hallo " . htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8');
// Ausgabe: Hallo <script>stehleCookie()</script>htmlspecialchars wandelt <, >, & und Anführungszeichen in harmlose HTML-Entities um. Der Text erscheint dann exakt so, wie er eingegeben wurde – aber der Browser führt ihn nicht mehr als Code aus.
Wichtig ist das zweite Argument ENT_QUOTES. Ohne es bleiben einfache Anführungszeichen ' stehen – und wenn du Nutzertext in ein Attribut schreibst (value='...'), kann jemand daraus ausbrechen. ENT_QUOTES escapt beide Anführungszeichen-Arten.
Ein kurzer Helfer, den du überall nutzt
function h(string $s): string
{
return htmlspecialchars($s, ENT_QUOTES, 'UTF-8');
}
?>
<h1><?= h($titel) ?></h1>
<input value="<?= h($eingabe) ?>">Die Regel dahinter ist simpel: Escape so spät wie möglich – direkt bei der Ausgabe, nicht beim Speichern. So bleibt in der Datenbank der Originaltext, und du entscheidest je Kontext (HTML, Attribut, URL), wie escaped wird.
Genau diesen h()-Helfer nutze ich in jeder PHP-Seite, die ich baue. Brauchst du eine sichere Website? Melde dich über bymw.de.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
array_find, array_any und array_all in PHP 8.4 – Arrays durchsuchen ohne Schleife
„Gibt es einen inaktiven Eintrag?", „Sind alle bezahlt?", „Hol mir den ersten Treffer" – dafür hast du bisher eine foreach-Schleife mit break geschrieben. PHP 8.4 macht daraus je eine Zeile, die genau sagt, was sie meint.
First-Class-Callable-Syntax in PHP: aus strlen(...) wird ein echter Wert
Funktionen als Zeichenketten weiterzureichen – 'strlen', [$objekt, 'methode'] – hat nie jemand gemocht: kein Tippfehlerschutz, keine Sprungmarke in der IDE. Seit PHP 8.1 schreibst du drei Punkte und bekommst ein Closure-Objekt.
Dateirechte verstehen – was 755 und 644 wirklich bedeuten
chmod 777 löst jedes Rechteproblem – und schafft ein größeres. Die drei Ziffern sind kein Zauberspruch, sondern eine simple Addition. Wer sie einmal verstanden hat, rät nie wieder.