Kodokon kodokon.com

Sicherheit auf HTML-Seite: XSS, sandbox, noopener und CSP

Erkenne die markup-spezifischen XSS-Vektoren und setze die nativen Abwehrmechanismen von HTML ein: sandbox, noopener und Content Security Policy.

11 Min. · 3 Fragen

Diese Lektion in Kodokon öffnen

Der Escaping-Kontext macht den ganzen Unterschied: Ein Wert, der in einem Textknoten harmlos ist, wird in einem Attribut ausführbar. Das nicht in Anführungszeichen gesetzte Attribut ist der schlimmste Fall: Ein einziges Leerzeichen in den eingeschleusten Daten genügt, um ein neues Attribut zu erzeugen, zum Beispiel einen onmouseover-Handler. Selbst korrekt in Anführungszeichen gesetzt bleibt ein Wert in sensiblen Sinks gefährlich: href und src akzeptieren das javascript:-Schema, formaction kapert das Absenden eines Formulars, und srcdoc interpretiert seine Entities nach dem Dekodieren als HTML.

HTML
<!-- userName = x onmouseover=alert(1) -->
<img src="avatar.png" alt=x onmouseover=alert(1)>
<!-- The unquoted attribute lets a handler in -->
Nicht escapte Daten in einem Attribut ohne Anführungszeichen werden zu Code.

Das sandbox-Attribut eines Iframes entzieht alle Rechte, und du gewährst sie danach einzeln wieder: allow-scripts, allow-forms, allow-popups... Ohne allow-same-origin erhält das eingebettete Dokument einen undurchsichtigen Ursprung (opaque origin): keine Cookies, kein Storage, kein Zugriff auf das übergeordnete DOM - selbst wenn es von deiner eigenen Domain ausgeliefert wird.

HTML
<iframe
  src="https://widget.example.com"
  sandbox="allow-scripts allow-forms"
  referrerpolicy="no-referrer">
</iframe>
Ein Drittanbieter-Widget, das Skripte ausführen kann, jedoch auf einen undurchsichtigen Ursprung beschränkt ist.

Ein target=_blank-Link gab der geöffneten Seite historisch eine window.opener-Referenz auf deinen Tab: Sie konnte deine Seite auf einen Phishing-Klon umleiten - der als Tabnabbing bekannte Angriff. Moderne Browser wenden noopener bei target=_blank inzwischen implizit an, aber es auszuschreiben bleibt wesentlich für window.open in JavaScript und um die Absicht zu dokumentieren; füge noreferrer hinzu, um auch den Referer-Header zu unterdrücken.

HTML
<a href="https://external.example"
   target="_blank"
   rel="noopener noreferrer">
  View the external resource
</a>
Die geöffnete Seite erhält window.opener === null.

Eine Content Security Policy beschränkt die Quellen ausführbaren Codes und neutralisiert die meisten XSS-Angriffe, selbst wenn die Injektion gelungen ist. Über ein <meta http-equiv>-Tag deklariert hat sie dennoch blinde Flecken: Die Direktiven frame-ancestors, report-uri und sandbox werden dort ignoriert und erfordern den HTTP-Header. Bevorzuge bei jeder Antwort neu erzeugte Nonces gegenüber Domain-Allowlists, die die Direktive strict-dynamic ohnehin überflüssig macht.

HTML
<meta http-equiv="Content-Security-Policy"
      content="default-src 'self';
               script-src 'self' 'nonce-r4nd0m'">
Nur Skripte, die den Nonce des Servers tragen, werden ausgeführt.

Wissenscheck

Stelle sicher, dass du die wichtigsten Punkte dieser Lektion behalten hast.

  1. Warum hebt die Kombination von allow-scripts und allow-same-origin bei einem gleichursprünglichen Iframe die Sandbox auf?
    • Das eingebettete Dokument, skriptfähig und nicht isoliert, kann das übergeordnete DOM erreichen und das sandbox-Attribut selbst entfernen
    • Die beiden Tokens sind inkompatibel, und der Browser ignoriert das gesamte Attribut
    • allow-same-origin deaktiviert automatisch alle anderen Tokens
  2. Vor welchem Angriff schützt rel=noopener?
    • Diebstahl von Session-Cookies durch die geöffnete Seite
    • Skript-Injektion in die geöffnete Seite
    • Tabnabbing: Die geöffnete Seite nutzt window.opener, um deinen Tab auf eine Phishing-Seite umzuleiten
  3. Welche Direktive wird ignoriert, wenn die CSP über <meta http-equiv> deklariert wird?
    • script-src
    • frame-ancestors
    • default-src
    • img-src