Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten. Erfahre mehr über dieses Experiment.

View in English Always switch to English

Trusted Types API

Limited availability

This feature is not Baseline because it does not work in some of the most widely-used browsers.

Hinweis: Diese Funktion ist in Web Workers verfügbar.

Die Trusted Types API gibt Webentwicklern eine Möglichkeit, sicherzustellen, dass Eingaben durch eine benutzerdefinierte Transformationsfunktion geleitet werden, bevor sie an eine API übergeben werden, die diese Eingaben möglicherweise ausführt. Dies kann helfen, sich gegen clientseitige Cross-Site Scripting (XSS)-Angriffe zu schützen. Meistens bereinigt die Transformationsfunktion die Eingabe.

Konzepte und Nutzung

Client-seitige oder DOM-basierte XSS-Angriffe passieren, wenn von einem Angreifer manipulierte Daten an eine Browser-API übergeben werden, die diese Daten als Code ausführt. Diese APIs sind bekannt als Injection Sinks.

Die Trusted Types API unterscheidet drei Arten von Injection Sinks:

  • HTML-Sinks: APIs, die ihre Eingabe als HTML interpretieren, wie Element.innerHTML oder document.write(). Diese APIs könnten JavaScript ausführen, wenn es im HTML eingebettet ist, zum Beispiel in <script> Tags oder Event-Handler-Attributen.
  • JavaScript-Sinks: APIs, die ihre Eingabe als JavaScript interpretieren, wie eval() oder HTMLScriptElement.text.
  • JavaScript-URL-Sinks: APIs, die ihre Eingabe als URL eines Skripts interpretieren, wie HTMLScriptElement.src.

Eine der Hauptverteidigungen gegen DOM-basierte XSS-Angriffe ist sicherzustellen, dass die Eingabe sicher gemacht wird, bevor sie an einen Injection Sink übergeben wird.

In der Trusted Types API definiert ein Entwickler ein Policy-Objekt, das Methoden enthält, die die Eingabe, die an einen Injection Sink gebunden ist, transformieren, um sie sicher zu machen. Die Richtlinie kann verschiedene Methoden für die unterschiedlichen Arten von Sinks definieren:

  • Für HTML-Sinks bereinigt die Transformationsfunktion typischerweise die Eingabe, zum Beispiel durch die Verwendung einer Bibliothek wie DOMPurify.
  • Für JavaScript- und JavaScript-URL-Sinks kann die Richtlinie die Sinks komplett abschalten oder bestimmte vordefinierte Eingaben erlauben (zum Beispiel spezifische URLs).

Die Trusted Types API stellt dann sicher, dass die Eingabe durch die entsprechende Transformationsfunktion geleitet wird, bevor sie in den Sink gelangt.

Das heißt, die API ermöglicht es Ihnen, Ihre Richtlinie an einem Ort zu definieren und dann sicherzustellen, dass alle Daten, die an einen Injection Sink übergeben werden, durch die Richtlinie geleitet wurden.

Hinweis:

Die Trusted Types API liefert selbst keine Richtlinie oder Transformationsfunktionen: der Entwickler definiert seine eigene Richtlinie, die die gewünschten Transformationen enthält.

Die API besteht aus zwei Hauptteilen:

  • Eine JavaScript-API ermöglicht es einem Entwickler, Daten zu bereinigen, bevor sie an einen Injection Sink übergeben werden.
  • Zwei CSP-Direktiven erzwingen und steuern die Nutzung der JavaScript-API.

Die Trusted Types JavaScript API

In der Trusted Types API:

  • Die trustedTypes globale Eigenschaft, verfügbar in sowohl Window als auch Worker Kontexten, wird verwendet, um TrustedTypePolicy Objekte zu erstellen.
  • Ein TrustedTypePolicy Objekt wird verwendet, um Trusted-Type-Objekte zu erstellen: es wird dies tun, indem es die Daten durch eine Transformationsfunktion leitet.
  • Trusted-Type-Objekte repräsentieren Daten, die durch die Richtlinie geleitet wurden, und können daher sicher an einen Injection Sink übergeben werden. Es gibt drei Arten von Trusted Types, die den verschiedenen Arten von Injection Sinks entsprechen:
    • TrustedHTML ist zum Übergeben an einen Sink, der die Daten als HTML rendert.
    • TrustedScript ist zum Übergeben an einen Sink, der die Daten als JavaScript ausführt.
    • TrustedScriptURL ist zum Übergeben an einen Sink, der die Daten als URL zu einem Skript parst.

Mit dieser API, anstatt eine Zeichenkette an einen Injection Sink wie innerHTML zu übergeben, verwenden Sie eine TrustedTypePolicy, um ein TrustedHTML Objekt aus der Zeichenkette zu erstellen, übergeben dann das an den Sink, und können sicher sein, dass die Zeichenkette durch eine Transformationsfunktion geleitet wurde.

Zum Beispiel erstellt dieser Code eine TrustedTypePolicy, die TrustedHTML Objekte durch die Bereinigung der Eingabezeichenketten mit der DOMPurify Bibliothek erstellen kann:

js
const policy = trustedTypes.createPolicy("my-policy", {
  createHTML: (input) => DOMPurify.sanitize(input),
});

Als nächstes können Sie dieses policy Objekt verwenden, um ein TrustedHTML Objekt zu erstellen und dieses Objekt in den Injection Sink übergeben:

js
const userInput = "<p>I might be XSS</p>";
const element = document.querySelector("#container");

const trustedHTML = policy.createHTML(userInput);
element.innerHTML = trustedHTML;

Verwendung eines CSP zur Erzwingung von Trusted Types

Die oben beschriebene API ermöglicht es Ihnen, Daten zu bereinigen, aber es stellt nicht sicher, dass Ihr Code niemals Eingaben direkt an einen Injection Sink übergibt: das heißt, es hindert Sie nicht daran, eine Zeichenkette an innerHTML zu übergeben.

Um sicherzustellen, dass immer ein Trusted Type übergeben wird, fügen Sie die require-trusted-types-for Direktive in Ihre CSP ein. Mit dieser Direktive wird das Übergeben von Zeichenketten in Injection Sinks zu einer TypeError-Ausnahme führen:

js
const userInput = "<p>I might be XSS</p>";
const element = document.querySelector("#container");

element.innerHTML = userInput; // Throws a TypeError

Zusätzlich kann die trusted-types CSP Direktive verwendet werden, um zu kontrollieren, welche Richtlinien Ihr Code erstellen darf. Wenn Sie eine Richtlinie mit trustedTypes.createPolicy() erstellen, übergeben Sie einen Namen für die Richtlinie. Die trusted-types CSP Direktive listet akzeptable Richtlinienneamen auf, sodass createPolicy() eine Ausnahme auslöst, wenn ihm ein Name übergeben wird, der nicht in trusted-types aufgelistet ist. Dies verhindert, dass ein Code in Ihrer Webanwendung eine Richtlinie erstellt, die Sie nicht erwartet haben.

Die Standardrichtlinie

In der Trusted Types API können Sie eine Standardrichtlinie definieren. Dies hilft Ihnen, Stellen in Ihrem Code zu finden, an denen Sie noch Zeichenketten in Injection Sinks übergeben, sodass Sie den Code umschreiben können, um stattdessen Trusted Types zu verwenden.

Wenn Sie eine Richtlinie mit dem Namen "default" erstellen und Ihre CSP die Verwendung von Trusted Types erzwingt, wird jedes Zeichenketten-Argument, das in Injection Sinks übergeben wird, automatisch an diese Richtlinie übergeben. Zum Beispiel, nehmen wir an, wir erstellen eine Richtlinie wie diese:

js
trustedTypes.createPolicy("default", {
  createHTML(value) {
    console.log("Please refactor this code");
    return sanitize(value);
  },
});

Mit dieser Richtlinie, wenn Ihr Code eine Zeichenkette innerHTML zuweist, ruft der Browser die Methode createHTML() der Richtlinie auf und weist das Ergebnis dem Sink zu:

js
const userInput = "<p>I might be XSS</p>";
const element = document.querySelector("#container");

element.innerHTML = userInput;
// Logs "Please refactor this code"
// Assigns the result of sanitize(userInput)

Wenn die Standardrichtlinie null oder undefined zurückgab, wird der Browser einen TypeError werfen, wenn er das Ergebnis dem Sink zuweist:

js
trustedTypes.createPolicy("default", {
  createHTML(value) {
    console.log("Please refactor this code");
    return null;
  },
});

const userInput = "<p>I might be XSS</p>";
const element = document.querySelector("#container");

element.innerHTML = userInput;
// Logs "Please refactor this code"
// Throws a TypeError

Hinweis: Es wird empfohlen, die Standardrichtlinie nur während der Transition von Legacy-Code, der Eingaben direkt an Injection Sinks übergibt, zu Code, der direkt Trusted Types verwendet, zu nutzen.

Injection Sink-Schnittstellen

Dieser Abschnitt bietet eine Liste von "direkten" Injection Sink-Schnittstellen.

Beachten Sie, dass es Fälle gibt, in denen unzuverlässige Zeichenketten "indirekt injiziert" werden können, wie zum Beispiel, wenn eine unzuverlässige Zeichenkette als Kindknoten eines Skriptelements hinzugefügt wird und dann das Element dem Dokument hinzugefügt wird. Diese Fälle werden ausgewertet, wenn das unzuverlässige Skript dem Dokument hinzugefügt wird.

TrustedHTML

TrustedScript

TrustedScriptURL

Cross-Browser-Unterstützung für Trusted Types

Die Trusted Types API ist noch nicht in allen modernen Browsern verfügbar, aber sie ist heute überall nutzbar dank Kompatibilitätshilfen, die von der W3C erstellt wurden.

  • Der volle Polyfill definiert die JavaScript-API, versucht, die CSP aus dem aktuellen Dokument abzuleiten, und erzwingt die Verwendung von Trusted Types basierend auf der abgeleiteten CSP.
  • Der API-only Polyfill definiert nur die JavaScript-API und umfasst nicht die Fähigkeit, die Verwendung von Trusted Types mit einer CSP zu erzwingen.

Neben diesen zwei Polyfills bietet die W3C, was sie als tinyfill bezeichnet, das wir im Folgenden näher erläutern.

Beachten Sie, dass solange Sie Ihren Code in einem unterstützenden Browser mit aktiviertem CSP-Erzwingung getestet haben, Sie den oben genannten vollen Polyfill nicht in anderen Browsern verwenden müssen – Sie können die gleichen Vorteile mit dem API-only-Polyfill oder dem tinyfill erhalten.

Dies liegt daran, dass die Erzwingung Sie dazu zwingt, Ihren Code zu überarbeiten, um sicherzustellen, dass alle Daten durch die Trusted Types API (und daher durch eine Bereinigungsfunktion) geleitet werden, bevor sie an einen Injection Sink übergeben werden. Wenn Sie dann den überarbeiteten Code in einem anderen Browser ohne Erzwingung ausführen, wird er immer noch die gleichen Codepfade durchlaufen und Ihnen den gleichen Schutz bieten.

Trusted Types Tinyfill

In diesem Abschnitt betrachten wir, wie das Tinyfill für Trusted Types eine Website schützen kann, obwohl es überhaupt keine Unterstützung für Trusted Types hinzufügt.

Das Trusted Types Tinyfill sieht einfach so aus:

js
if (typeof trustedTypes === "undefined")
  trustedTypes = { createPolicy: (n, rules) => rules };

Es stellt eine Implementierung von trustedTypes.createPolicy() zur Verfügung, die einfach das an sie übergebene policyOptions-Objekt zurückgibt. Das policyOptions-Objekt definiert Bereinigungsfunktionen für Daten, und diese Funktionen sollten Zeichenketten zurückgeben.

Mit diesem Tinyfill eingerichtet, nehmen wir an, wir erstellen eine Richtlinie:

js
const policy = trustedTypes.createPolicy("my-policy", {
  createHTML: (input) => DOMPurify.sanitize(input),
});

In Browsern, die Trusted Types unterstützen, wird dies eine TrustedTypePolicy zurückgeben, die ein TrustedHTML-Objekt erstellt, wenn wir policy.createHTML() aufrufen. Das TrustedHTML-Objekt kann dann an einen Injection Sink übergeben werden, und wir können sicherstellen, dass der Sink einen Trusted Type erhält und keine Zeichenkette.

In Browsern, die Trusted Types nicht unterstützen, wird dieser Code ein Objekt mit einer createHTML()-Funktion zurückgeben, die ihre Eingabe bereinigt und als Zeichenkette zurückgibt. Die bereinigte Zeichenkette kann dann an einen Injection Sink übergeben werden.

js
const userInput = "I might be XSS";
const element = document.querySelector("#container");

const trustedHTML = policy.createHTML(userInput);
// In supporting browsers, trustedHTML is a TrustedHTML object.
// In non-supporting browsers, trustedHTML is a string.

element.innerHTML = trustedHTML;
// In supporting browsers, this will throw if trustedHTML
// is not a TrustedHTML object.

So oder so erhält der Injection Sink bereinigte Daten, und weil wir die Verwendung der Richtlinie in dem unterstützenden Browser erzwingen konnten, wissen wir, dass dieser Codepfad im nicht unterstützenden Browser ebenfalls durch die Bereinigungsfunktion geht.

Schnittstellen

TrustedHTML

Repräsentiert eine Zeichenkette, die in einen Injection Sink eingefügt wird, der sie als HTML rendert.

TrustedScript

Repräsentiert eine Zeichenkette, die in einen Injection Sink eingefügt wird, der dazu führen könnte, dass das Skript ausgeführt wird.

TrustedScriptURL

Repräsentiert eine Zeichenkette, die in einen Injection Sink eingefügt wird, der sie als URL einer externen Skriptressource parsen wird.

TrustedTypePolicy

Definiert die Funktionen, die zur Erstellung der oben genannten Trusted Type-Objekte verwendet werden.

TrustedTypePolicyFactory

Erstellt Richtlinien und verifiziert, dass Trusted Type-Objektinstanzen durch eine der Richtlinien erstellt wurden.

Erweiterungen zu anderen Schnittstellen

Window.trustedTypes

Gibt das TrustedTypePolicyFactory-Objekt zurück, das mit dem globalen Objekt im Hauptthread assoziiert ist. Dies ist der Einstiegspunkt für die Nutzung der API im Window-Thread.

WorkerGlobalScope.trustedTypes.

Gibt das TrustedTypePolicyFactory-Objekt zurück, das mit dem globalen Objekt in einem Worker assoziiert ist.

Erweiterungen zu HTTP

Content-Security-Policy Direktiven

require-trusted-types-for

Erzwingt, dass Trusted Types an DOM XSS Injection Sinks übergeben werden.

trusted-types

Wird verwendet, um eine Zulassungsliste von Trusted-Types-Richtlinienneamen zu spezifizieren.

Content-Security-Policy Schlüsselwörter

trusted-types-eval

Erlaubt die Verwendung von Funktionen wie eval(), aber nur dann, wenn Trusted Types unterstützt und erzwungen werden.

Beispiele

Im folgenden Beispiel erstellen wir eine Richtlinie, die TrustedHTML Objekte mit TrustedTypePolicyFactory.createPolicy() erstellt. Wir können dann TrustedTypePolicy.createHTML() verwenden, um eine bereinigte HTML-Zeichenkette zu erstellen, die in das Dokument eingefügt wird.

Der bereinigte Wert kann dann mit Element.innerHTML verwendet werden, um sicherzustellen, dass keine neuen HTML-Elemente injiziert werden können.

html
<div id="myDiv"></div>
js
const escapeHTMLPolicy = trustedTypes.createPolicy("myEscapePolicy", {
  createHTML: (string) =>
    string
      .replace(/&/g, "&amp;")
      .replace(/</g, "&lt;")
      .replace(/"/g, "&quot;")
      .replace(/'/g, "&apos;"),
});

let el = document.getElementById("myDiv");
const escaped = escapeHTMLPolicy.createHTML("<img src=x onerror=alert(1)>");
console.log(escaped instanceof TrustedHTML); // true
el.innerHTML = escaped;

Lesen Sie mehr über dieses Beispiel und entdecken Sie andere Möglichkeiten zur Bereinigung von Eingaben im Artikel DOM-basierte Cross-Site Scripting-Schwachstellen mit Trusted Types verhindern.

Spezifikationen

Specification
Trusted Types

Browser-Kompatibilität

Siehe auch