HTML-Entity-Encoding vs. URL-Encoding: Die wichtigsten Unterschiede
HTML-Entity-Encoding wandelt Zeichen wie <, >, & und " in HTML-Entities um (<, >, &, "), damit sie in Webseiten sicher angezeigt werden. URL-Encoding wandelt Zeichen in das Format %XX um, damit sie sicher in URLs übertragen werden können. Beide schützen vor unterschiedlichen Angriffsarten und kommen in verschiedenen Kontexten zum Einsatz.
Was ist HTML-Entity-Encoding?
HTML-Entity-Encoding (auch HTML-Escaping genannt) wandelt Zeichen, die in HTML eine besondere Bedeutung haben, in Entity-Referenzen um, die der Browser als das jeweilige Zeichen selbst anzeigt, anstatt sie als Markup zu interpretieren. Die wichtigsten zu kodierenden Zeichen sind <, >, &, " und '.
Ohne HTML-Encoding würde eine Zeichenkette wie <script>alert('XSS')</script> vom Browser als JavaScript ausgeführt. Mit Encoding wird daraus <script>alert('XSS')</script>, und sie wird als harmloser Text angezeigt.
HTML-Entities lassen sich auf zwei Arten schreiben: als benannte Entities wie &, < und " oder als numerische Entities wie &, < und ". Numerische Entities verwenden den Unicode-Codepoint des Zeichens und können jedes beliebige Unicode-Zeichen darstellen.
<!-- Vor dem HTML-Encoding -->
<p>The formula is: x < y & y > z</p>
<!-- Der Browser interpretiert < als Anfang eines Tags! -->
<!-- Nach dem HTML-Encoding -->
<p>The formula is: x < y & y > z</p>
<!-- Der Browser zeigt an: x < y & y > z -->
<!-- Gängige HTML-Entities -->
& → & (Kaufmanns-Und)
< → < (kleiner als)
> → > (größer als)
" → " (doppeltes Anführungszeichen)
' → ' (einfaches Anführungszeichen / Apostroph)
→ (geschütztes Leerzeichen)
Was ist URL-Encoding?
URL-Encoding (Percent-Encoding) wandelt Zeichen, die in URLs nicht sicher sind, in ein Prozentzeichen gefolgt von zwei Hexadezimalziffern um, die den Bytewert repräsentieren. Es ist in RFC 3986 definiert und stellt sicher, dass URLs nur gültige ASCII-Zeichen enthalten, die sich sicher über das Internet übertragen lassen.
URL-Encoding ist notwendig, weil URLs einer strengen Syntax folgen, in der bestimmte Zeichen als Trennzeichen dienen (/, ?, &, #, =). Wenn diese Zeichen in Daten auftauchen (etwa in den Werten von Query-Parametern), müssen sie kodiert werden, damit sie nicht als strukturelle Elemente interpretiert werden.
// Beispiele für URL-Encoding
space → %20
& → %26
= → %3D
? → %3F
# → %23
/ → %2F
+ → %2B
// Vollständige URL mit kodiertem Query-Parameter
https://example.com/search?q=salt%20%26%20pepper
// Der Wert von q ist "salt & pepper"
Vergleichstabelle
| Merkmal | HTML-Entity-Encoding | URL-Encoding |
|---|---|---|
| Zweck | Sichere Anzeige in HTML-Seiten | Sichere Übertragung in URLs |
| Standard | HTML-/WHATWG-Spezifikation | RFC 3986 |
| Format | &name; oder &#number; |
%XX (Hex-Bytewert) |
| Leerzeichen wird zu | (geschützt) oder bleibt unverändert |
%20 oder + |
| & wird zu | & |
%26 |
| < wird zu | < |
%3C |
| Verhindert | XSS-Angriffe, defektes HTML | Defekte URLs, Injection-Angriffe |
| Kontext | HTML-Dokumentkörper und Attribute | URL-Pfade, Query-Strings, Fragmente |
| JS-Funktion | Keine integrierte (Bibliothek oder DOM-APIs verwenden) | encodeURIComponent() |
Wann brauchst du beides?
Es gibt häufige Situationen, in denen sowohl HTML- als auch URL-Encoding erforderlich sind. Der häufigste Fall ist, wenn du eine URL in ein HTML-Attribut einfügst, etwa in ein href- oder src-Attribut. Die URL muss zunächst korrekt URL-kodiert werden, und anschließend müssen alle besonderen HTML-Zeichen im Ergebnis HTML-kodiert werden.
<!-- Schritt 1: Den Wert des Query-Parameters URL-kodieren -->
<!-- Wert: "Tom & Jerry" → URL-kodiert: "Tom%20%26%20Jerry" -->
<!-- Schritt 2: Die URL zusammenbauen -->
<!-- URL: https://example.com/search?q=Tom%20%26%20Jerry -->
<!-- Schritt 3: Die URL für die Verwendung in einem href-Attribut HTML-kodieren -->
<a href="https://example.com/search?q=Tom%20%26%20Jerry">
Search for Tom & Jerry
</a>
<!-- In diesem Fall müssen die %-Sequenzen nicht HTML-kodiert werden, -->
<!-- weil % kein besonderes HTML-Zeichen ist -->
<!-- Enthält die URL jedoch & als Trennzeichen, MUSS es HTML-kodiert werden: -->
<a href="https://example.com/search?q=cats&sort=name">
Search cats sorted by name
</a>
<!-- Ohne & könnte der Browser &sort als HTML-Entity interpretieren -->
In modernen Frameworks wie React, Vue und Angular wird das HTML-Encoding automatisch übernommen, wenn du Template-Ausdrücke oder JSX verwendest. Das URL-Encoding muss beim Erstellen von URLs aus dynamischen Daten jedoch weiterhin explizit erfolgen.
// React - HTML-Encoding erfolgt automatisch, URL-Encoding nicht
function SearchLink({ query }) {
// URL-Encoding muss explizit erfolgen
const url = '/search?q=' + encodeURIComponent(query);
// HTML-Encoding erfolgt in JSX automatisch
return <a href={url}>Search for {query}</a>;
// React kodiert sowohl das href-Attribut als auch den Textinhalt automatisch als HTML
}
XSS-Prävention: Welches Encoding wo einsetzen
Die Prävention von Cross-Site-Scripting (XSS) erfordert, das jeweils korrekte Encoding je nach Kontext anzuwenden, in dem Benutzereingaben platziert werden. Das falsche Encoding in einem bestimmten Kontext bietet keinerlei Schutz.
- HTML-Body-Kontext: Verwende HTML-Entity-Encoding. Dadurch werden eingeschleuste Tags wie
<script>nicht als Markup interpretiert. - HTML-Attribut-Kontext: Verwende HTML-Entity-Encoding und setze Attributwerte immer in Anführungszeichen. Aus nicht in Anführungszeichen gesetzten Attributen kann man selbst mit HTML-Encoding ausbrechen.
- URL-Kontext (href, src): Verwende URL-Encoding für die dynamischen Teile und kodiere anschließend die gesamte URL als HTML, wenn du sie in HTML einfügst. Prüfe, dass die URL mit einem sicheren Schema beginnt (
https:), umjavascript:-URLs zu verhindern. - JavaScript-Kontext: Verwende JavaScript-String-Escaping (JSON.stringify oder eine spezialisierte Bibliothek). Weder HTML- noch URL-Encoding ist in einem JavaScript-Kontext ausreichend.
- CSS-Kontext: Verwende CSS-Escaping. HTML- und URL-Encoding schützen nicht vor CSS-Injection.
Der Grundsatz lautet: Kodiere für den Ausgabekontext, nicht für die Eingabequelle. Ein und dieselbe Benutzereingabe kann je nachdem, wo sie in der Antwort erscheint, ein unterschiedliches Encoding erfordern. Verlasse dich zur XSS-Prävention niemals allein auf die Eingabevalidierung; wende immer ein Output-Encoding an.