Navigation
 Startseite
 Fachbücher
 Anzeigenmarkt
 Forum
 Webmaster News
 Script Newsletter
 Kontakt
 Script Installation
 Php
 Php Tutorials
 Webhoster Vergleich
 Impressum

Community-Bereich
 kostenlos Registrieren
 Anmelden
 Benutzerliste

Script Datenbank
 Script Archiv
 Script Top 20
 Screenshots
 Testberichte

Suche
 

Unsere Php Scripts
 Counter Script
 Umfrage Script
 Bilder Upload Script
 Terminverwaltung
 Simple PHP Forum
 RSS Grabber

Script Mods
 phpBB Adsense Mode

Tools und Generatoren
 .htpasswd Generator
 md5 Generator
 base64 Generator
 Markdown to HTML
 Colorpicker
 Unix timestamp Tool
 TLD Liste
 Webkatalog‑Verzeichnis

Partner
 Sprüche Treff

Artfiles.de
Bietet Serviceorientierte...
https://www.Artfiles.de
Hosterplus.de
Bekommen Sie Speicherplatz (Webspace), Domains...
https://www.Hosterplus.de
 
 
 

HTML-Zeichen in sichere Zeichen umwandeln

Sie befinden sich: Home > Php Tutorial > HTML-Zeichen in sichere...

HTML-Zeichen in sichere Zeichen umwandeln


Eintrag am:  23.12.2022
Hits / Besucher:  1453
Sprache:  Deutsch
Kategorie:  Einsteiger Tutorials
Tutorial Art:  eigenes
Eingetragen von   schubertmedia schubertmedia
 
Beschreibung

Wer Benutzereingaben oder dynamische Inhalte auf einer Webseite ausgibt, muss sicherstellen, dass kein HTML- oder JavaScript-Code eingeschleust werden kann. Genau dafür ist htmlspecialchars() gedacht: Die Funktion wandelt die fünf wichtigsten Sonderzeichen in ihre HTML-Entitäten um und macht Ausgaben damit sicher gegen Cross-Site-Scripting (XSS). In diesem Tutorial erfährst du, wie die Funktion arbeitet, welche Flags es gibt und wie du sie in der Praxis richtig einsetzt.

Welche Zeichen werden konvertiert?

htmlspecialchars() ersetzt genau diese fünf Zeichen:

  • & wird zu &
  • < wird zu &lt;
  • > wird zu &gt;
  • " wird zu &quot; (bei ENT_COMPAT oder ENT_QUOTES)
  • ' wird zu &#039; bzw. &apos; (nur bei ENT_QUOTES)

Alle anderen Zeichen bleiben unverändert. Das unterscheidet die Funktion von htmlentities(), die zusätzlich alle Zeichen mit benannter HTML-Entität konvertiert (Umlaute, Akzentbuchstaben, Copyright-Zeichen und mehr). Für den XSS-Schutz in UTF-8-Dokumenten reichen die fünf Zeichen von htmlspecialchars() vollständig aus.

<?php

$text = '<script>alert("XSS")</script>';

echo htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
/* Ausgabe:
&lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;
Der Browser zeigt den Code als Text an,
statt ihn auszuführen */
?>

Syntax und Parameter

Die vollständige Funktionssignatur zeigt vier Parameter, von denen nur der erste Pflicht ist:

htmlspecialchars(

string $string,
int $flags = ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401,
?string $encoding = null,
bool $double_encode = true
): string

Die Parameter im Detail:

  • $string: Der zu konvertierende Text. Alle fünf Sonderzeichen werden in ihre Entitäten umgewandelt.
  • $flags: Steuert, wie Anführungszeichen und ungültige Zeichenfolgen behandelt werden. Seit PHP 8.1 werden standardmäßig beide Arten von Anführungszeichen konvertiert.
  • $encoding: Der Zeichensatz des Eingabe-Strings. Seit PHP 5.4 ist UTF-8 der Standard. Bei einem anderen Zeichensatz (z.B. ISO-8859-1) muss dieser hier explizit angegeben werden.
  • $double_encode: Wenn true (Standard), werden bereits vorhandene Entitäten erneut kodiert. Bei false bleiben bestehende Entitäten unverändert.

Die wichtigsten Flags im Detail

Der zweite Parameter akzeptiert verschiedene Flags, die mit dem Oder-Operator (|) kombiniert werden können. Die Wahl des richtigen Flags hat direkte Auswirkungen auf die Sicherheit der Ausgabe.

Flags für Anführungszeichen

Die drei wichtigsten Flags betreffen die Behandlung von Anführungszeichen:

  • ENT_QUOTES: Konvertiert sowohl doppelte (") als auch einfache (') Anführungszeichen. Das ist für die sichere Ausgabe in HTML-Attributen unverzichtbar.
  • ENT_COMPAT: Konvertiert nur doppelte Anführungszeichen. War bis PHP 8.0 der Standard. Einfache Anführungszeichen bleiben unverändert, was in bestimmten Kontexten eine Sicherheitslücke öffnen kann.
  • ENT_NOQUOTES: Konvertiert keine Anführungszeichen. Sollte aus Sicherheitsgründen nie für Benutzereingaben verwendet werden.
<?php

$eingabe = "Er sagte: \"Das klappt 'bestimmt' nicht\"";

/* ENT_COMPAT: Nur doppelte Anführungszeichen */
echo htmlspecialchars($eingabe, ENT_COMPAT, 'UTF-8');
/* Er sagte: &quot;Das klappt 'bestimmt' nicht&quot;
Einfache Anführungszeichen bleiben! */

/* ENT_QUOTES: Beide Arten */
echo htmlspecialchars($eingabe, ENT_QUOTES, 'UTF-8');
/* Er sagte: &quot;Das klappt &#039;bestimmt&#039; nicht&quot;
Jetzt sind beide sicher */

/* ENT_NOQUOTES: Keine */
echo htmlspecialchars($eingabe, ENT_NOQUOTES, 'UTF-8');
/* Er sagte: "Das klappt 'bestimmt' nicht"
Keine Konvertierung, unsicher! */
?>

Flags für ungültige Zeichenfolgen

Diese Flags bestimmen, wie mit ungültigen Byte-Sequenzen umgegangen wird:

  • ENT_SUBSTITUTE: Ersetzt ungültige Code-Sequenzen durch das Unicode-Ersatzzeichen (&ufffd;). Verhindert, dass fehlerhafte Eingaben Teile der Ausgabe verschlucken. Seit PHP 8.1 Teil des Standards.
  • ENT_IGNORE: Verwirft ungültige Sequenzen stillschweigend. Sollte vermieden werden, da es Sicherheitsprobleme verursachen kann.
  • ENT_DISALLOWED: Ersetzt Zeichen, die im gewählten Dokumenttyp nicht erlaubt sind, durch das Unicode-Ersatzzeichen.

Flags für den Dokumenttyp

Diese Flags legen fest, welcher HTML- oder XML-Standard für die Entitäten verwendet wird:

  • ENT_HTML401: Standard. Verwendet HTML 4.01 Entitäten.
  • ENT_HTML5: Verwendet HTML5-Entitäten. Bei einfachen Anführungszeichen wird &apos; statt &#039; erzeugt.
  • ENT_XML1: Verwendet XML 1.0 Entitäten.
  • ENT_XHTML: Verwendet XHTML-Entitäten.

Standardwerte im Wandel der PHP-Versionen

Die Standardwerte von htmlspecialchars() haben sich über die Jahre geändert. Wer Code für verschiedene PHP-Versionen schreibt oder alten Code pflegt, sollte die Unterschiede kennen:

  • Vor PHP 5.4: Der Standard-Zeichensatz war ISO-8859-1. UTF-8-Strings wurden falsch verarbeitet, wenn man den Zeichensatz nicht explizit angab. Bei ungültigen Sequenzen gab die Funktion einen leeren String zurück.
  • Ab PHP 5.4: UTF-8 ist der Standard-Zeichensatz. Das Standard-Flag war ENT_COMPAT | ENT_HTML401, das nur doppelte Anführungszeichen konvertiert.
  • Ab PHP 8.1: Das Standard-Flag wurde auf ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 geändert. Damit werden automatisch beide Arten von Anführungszeichen konvertiert und ungültige Sequenzen sicher behandelt.

Wer auf PHP 8.1 oder neuer arbeitet, erhält die sichersten Standardwerte automatisch. Für ältere Versionen empfiehlt es sich, ENT_QUOTES immer explizit anzugeben.

UTF-8 und Zeichenkodierung

UTF-8 ist heute der Standard im Web. Mehr als 98% aller Webseiten verwenden diesen Zeichensatz, weil er alle Zeichen aller Sprachen abdecken kann. Für htmlspecialchars() hat das praktische Konsequenzen.

Wenn der Eingabe-String in einem anderen Zeichensatz vorliegt als angegeben, kann die Funktion unerwartete Ergebnisse liefern. Ein typisches Problem: Eine Datenbank liefert Daten in Latin-1 (ISO-8859-1), aber htmlspecialchars() erwartet UTF-8. In solchen Fällen können Umlaute verschwinden oder die Funktion gibt einen leeren String zurück.

<?php

/* Zeichensatz stimmt: Alles funktioniert */
$utf8 = 'Müller & Söhne';
echo htmlspecialchars($utf8, ENT_QUOTES, 'UTF-8');
// Müller &amp; Söhne

/* Zeichensatz stimmt nicht: Problem! */
$latin1 = mb_convert_encoding('Müller', 'ISO-8859-1', 'UTF-8');
echo htmlspecialchars($latin1, ENT_QUOTES, 'UTF-8');
/* Leerer String oder Ersatzzeichen,
weil die Bytes kein gültiges UTF-8 sind */

/* Lösung: Encoding vorher konvertieren */
$safe = mb_convert_encoding($latin1, 'UTF-8', 'ISO-8859-1');
echo htmlspecialchars($safe, ENT_QUOTES, 'UTF-8');
// Müller
?>

Die Faustregel lautet: Stelle sicher, dass deine gesamte Anwendung durchgängig UTF-8 verwendet. Das betrifft die Datenbank (Kollation utf8mb4), die Datenbankverbindung (SET NAMES utf8mb4), die PHP-Dateien selbst und den HTML-Header (<meta charset="UTF-8">).

Escaping und Encoding: Was ist der Unterschied?

Zwei Begriffe, die oft vermischt werden, aber unterschiedliche Dinge meinen:

Escaping bedeutet, Sonderzeichen so umzuschreiben, dass sie in einem bestimmten Kontext keine Sonderfunktion mehr haben. Aus < wird &lt;, damit der Browser kein HTML-Tag erkennt. Der Zweck ist Sicherheit: Der ursprüngliche Wert bleibt erhalten, wird aber entschärft.

Encoding beschreibt allgemein die Umwandlung von Zeichen in eine bestimmte Darstellungsform. UTF-8 ist ein Encoding, Base64 ist ein Encoding. Encoding dient der Kompatibilität zwischen verschiedenen Systemen.

htmlspecialchars() ist im engeren Sinn eine Escaping-Funktion: Sie entschärft Zeichen, die in HTML eine besondere Bedeutung haben. Der Begriff "HTML-Encoding" wird aber ebenfalls häufig verwendet und meint dasselbe. Wichtig ist die Erkenntnis: Escaping muss immer zum Ausgabekontext passen. HTML-Escaping schützt HTML-Ausgaben. Für SQL braucht man Prepared Statements, für JavaScript json_encode(), für URLs urlencode().

Praxisbeispiel: Formulardaten sicher ausgeben

Ein häufiger Anwendungsfall ist die Anzeige von Formulardaten. Der folgende Code zeigt, wie ein Benutzername sicher in einem HTML-Attribut und im Seitentext ausgegeben wird:

<?php

$name = htmlspecialchars(
$_POST['name'] ?? '',
ENT_QUOTES,
'UTF-8'
);
?>
<input type="text" value="<?= $name ?>">
<p>Willkommen, <?= $name ?></p>

Durch ENT_QUOTES werden auch einfache Anführungszeichen konvertiert. Ohne dieses Flag könnte ein Angreifer aus dem value-Attribut ausbrechen. Stell dir vor, ein Benutzer gibt folgenden Wert ein: ' onfocus='alert(document.cookie)

<!-- Ohne Escaping: XSS-Lücke -->

<input type="text" value='' onfocus='alert(document.cookie)'>

<!-- Mit htmlspecialchars(): sicher -->
<input type="text" value='&#039; onfocus=&#039;alert(document.cookie)'>

Mit htmlspecialchars() wird das Apostroph in &#039; umgewandelt. Der Browser interpretiert den Wert als harmlosen Text statt als Event-Handler. Ohne Escaping hätte der Angreifer beliebigen JavaScript-Code ausführen und beispielsweise Session-Cookies stehlen können.

Praxisbeispiel: Datenbank-Inhalte sicher ausgeben

Ein weiterer typischer Fall: Daten werden aus einer Datenbank gelesen und in einer HTML-Tabelle angezeigt. Die Daten könnten Sonderzeichen oder sogar eingeschleusten Code enthalten.

<?php

$stmt = $pdo->query('SELECT name, kommentar FROM bewertungen');
?>
<table>
<?php while ($row = $stmt->fetch()): ?>
<tr>
<td><?= htmlspecialchars($row['name'], ENT_QUOTES, 'UTF-8') ?></td>
<td><?= htmlspecialchars($row['kommentar'], ENT_QUOTES, 'UTF-8') ?></td>
</tr>
<?php endwhile; ?>
</table>

Wichtig dabei: Die Daten werden unverändert in der Datenbank gespeichert und erst bei der HTML-Ausgabe durch htmlspecialchars() geschützt. So bleiben die Rohdaten für andere Ausgabeformate (JSON, CSV, E-Mail) nutzbar. Würde man bereits beim Speichern escapen, müsste man die Daten für jeden anderen Kontext erst wieder zurückwandeln.

Doppelte Kodierung vermeiden

Wird htmlspecialchars() auf einen String angewendet, der bereits Entitäten enthält, werden diese standardmäßig erneut kodiert. Aus &amp; wird dann &amp;amp;. Das passiert leicht, wenn Inhalte aus einer Datenbank gelesen, bearbeitet und erneut gespeichert werden.

<?php

$text = 'Bereits kodiert: &amp; und neu: &';

/* Standard: double_encode = true */
echo htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
/* Bereits kodiert: &amp;amp; und neu: &amp;
Die bestehende Entität wurde doppelt kodiert! */

/* Mit double_encode = false */
echo htmlspecialchars($text, ENT_QUOTES, 'UTF-8', false);
/* Bereits kodiert: &amp; und neu: &amp;
Bestehende Entitäten bleiben unverändert */
?>

Gerade bei Content-Management-Systemen, in denen Texte mehrfach bearbeitet werden, ist double_encode = false sinnvoll. Ohne diesen Parameter wachsen die Entitäten mit jeder Speicherung weiter an. Das Problem zeigt sich dann durch mehrfache &amp; im Quelltext der Seite.

htmlspecialchars_decode() als Gegenfunktion

Die Funktion htmlspecialchars_decode() macht die Konvertierung rückgängig. Sie wandelt die HTML-Entitäten zurück in ihre ursprünglichen Zeichen:

<?php

$kodiert = '&lt;strong&gt;Fett&lt;/strong&gt;';

$original = htmlspecialchars_decode($kodiert, ENT_QUOTES);
echo $original;
// <strong>Fett</strong>
?>

Das ist nützlich, wenn HTML-kodierte Daten als Klartext weiterverarbeitet werden sollen, zum Beispiel für den Versand per E-Mail, den Export als CSV oder die Anzeige in einer API-Antwort. Beachte dabei: htmlspecialchars_decode() wandelt nur die fünf Entitäten von htmlspecialchars() zurück. Für alle Entitäten (einschließlich &uuml;, &ouml; etc.) braucht man html_entity_decode().

Wann htmlspecialchars() und wann htmlentities()?

Beide Funktionen schützen vor XSS. Der Unterschied liegt im Umfang der Konvertierung:

  • htmlspecialchars(): Konvertiert nur die fünf Zeichen &, <, >, " und '. Das reicht für den XSS-Schutz in UTF-8-Dokumenten vollständig aus.
  • htmlentities(): Konvertiert zusätzlich Umlaute, Akzentbuchstaben, Copyright-Zeichen und alle weiteren Zeichen mit benannten Entitäten. Das erhöht die Dateigröße, bietet aber keinen zusätzlichen Sicherheitsgewinn.

Empfehlung: Für die meisten Projekte ist htmlspecialchars() die bessere Wahl. Es ist performanter, erzeugt kürzeren HTML-Code und bietet denselben XSS-Schutz. htmlentities() eignet sich für Sonderfälle, zum Beispiel wenn der HTML-Code in Nicht-UTF-8-Umgebungen funktionieren muss oder Sonderzeichen in E-Mail-Templates als Entitäten erscheinen sollen.

Eingabevalidierung und Filterung

htmlspecialchars() ist kein Ersatz für Eingabevalidierung. Die Funktion schützt die Ausgabe, prüft aber nicht, ob die Eingabe sinnvoll ist. Ein vollständiger Schutz besteht aus mehreren Schichten:

  • Validierung: Prüfen, ob die Eingabe dem erwarteten Format entspricht. Eine E-Mail-Adresse muss ein @ enthalten, eine Postleitzahl darf nur Ziffern haben.
  • Filterung: Unerwünschte Zeichen entfernen oder ersetzen. PHP bietet dafür filter_input() und filter_var().
  • Escaping: Bei der Ausgabe die Daten für den jeweiligen Kontext schützen. htmlspecialchars() für HTML, Prepared Statements für SQL, json_encode() für JavaScript.

Diese drei Schritte ergänzen sich. Validierung allein verhindert kein XSS, und Escaping allein lässt ungültige Daten durch. Zusammen bilden sie einen robusten Schutz.

Sicherheitshinweise und Best Practices

Beim Einsatz von htmlspecialchars() gelten folgende Grundregeln:

  • Escaping gehört zur Ausgabe, nicht zur Speicherung. Daten sollten unverändert in der Datenbank landen und erst bei der HTML-Ausgabe durch htmlspecialchars() geschützt werden. So bleiben die Rohdaten für andere Ausgabeformate nutzbar.
  • Zeichensatz immer explizit angeben. Auch wenn UTF-8 seit PHP 5.4 der Standard ist, macht eine explizite Angabe den Code klarer und verhindert Probleme bei Konfigurationswechseln.
  • ENT_QUOTES verwenden. Ohne dieses Flag bleiben einfache Anführungszeichen unkonvertiert, was in bestimmten HTML-Kontexten eine Sicherheitslücke eröffnet.
  • Für JavaScript-Kontexte reicht htmlspecialchars() nicht. Wer Werte in <script>-Blöcke einbettet, braucht json_encode() mit dem Flag JSON_HEX_TAG statt HTML-Escaping.
  • Für SQL-Abfragen Prepared Statements verwenden. htmlspecialchars() schützt nicht vor SQL-Injection. Dafür sind ausschließlich Prepared Statements mit parametrisierten Abfragen geeignet.

Zusammenfassung

htmlspecialchars() ist die wichtigste Funktion zur Absicherung von HTML-Ausgaben in PHP. Sie konvertiert die fünf kritischen Sonderzeichen in ihre Entitäten und verhindert damit zuverlässig Cross-Site-Scripting. Für den sicheren Einsatz gilt: Immer ENT_QUOTES verwenden, den Zeichensatz explizit angeben und das Escaping bei der Ausgabe durchführen, nicht bei der Speicherung. Für die meisten Projekte mit UTF-8 ist htmlspecialchars() gegenüber htmlentities() die bessere Wahl, da es denselben Schutz bei geringerem Overhead bietet.

 

Tags:

 

Bücherregal mit drei Büchern: 'PHP 4 - Grundlagen und Profiwissen' von Hanser Verlag, 'Webdesign in a Nutshell' von O'Reilly Verlag, und 'Webgestaltung' von Galileo Computing.