Element: setHTMLUnsafe() Methode
Limited availability
This feature is not Baseline because it does not work in some of the most widely-used browsers.
Warnung: Diese Methode analysiert ihre Eingabe als HTML und schreibt das Ergebnis in das DOM. Solche APIs sind als Injection Sinks bekannt und können potenziell ein Vektor für Cross-Site Scripting (XSS) Angriffe sein, wenn die Eingabe ursprünglich von einem Angreifer stammt.
Sie können dieses Risiko mindern, indem Sie immer TrustedHTML
Objekte anstelle von Zeichenfolgen übergeben und trusted types erzwingen.
Siehe Sicherheitsüberlegungen für weitere Informationen.
Hinweis:
Element.setHTML()
sollte fast immer anstelle dieser Methode verwendet werden — auf Browsern, wo es unterstützt wird — da es immer XSS-unsichere HTML-Entitäten entfernt.
Die setHTMLUnsafe()
Methode der Element
Schnittstelle wird verwendet, um HTML-Eingaben in einen DocumentFragment
zu analysieren, wobei optional unerwünschte Elemente und Attribute herausgefiltert werden, und dann damit den Teilbaum des Elements im DOM zu ersetzen.
Syntax
setHTMLUnsafe(input)
setHTMLUnsafe(input, options)
Parameter
input
-
Eine Instanz von
TrustedHTML
oder eine Zeichenfolge, die HTML definiert, das analysiert werden soll. options
Optional-
Ein Optionsobjekt mit den folgenden optionalen Parametern:
sanitizer
Optional-
Ein
Sanitizer
oderSanitizerConfig
Objekt, das definiert, welche Elemente der Eingabe erlaubt oder entfernt werden. Dies kann auch eine Zeichenfolge mit dem Wert"default"
sein, was einenSanitizer
mit der Standard-(XSS-sicheren) Konfiguration anwendet. Wenn nicht angegeben, wird kein Sanitizer verwendet.Beachten Sie, dass ein
Sanitizer
normalerweise effizienter ist als eineSanitizerConfig
, wenn die Konfiguration wiederverwendet werden soll.
Rückgabewert
None (undefined
).
Ausnahmen
TypeError
-
Dies wird ausgelöst, wenn:
input
eine Zeichenfolge übergeben wird, wenn Trusted Types durch ein CSP erzwungen werden und keine Standardrichtlinie definiert ist.options.sanitizer
ein:- Wert, der kein
Sanitizer
,SanitizerConfig
oder String ist. - nicht normalisierte
SanitizerConfig
(eine, die sowohl "erlaubte" als auch "entfernte" Konfigurationseinstellungen enthält). - String, der nicht den Wert
"default"
hat, übergeben wird.
- Wert, der kein
Beschreibung
Die setHTMLUnsafe()
Methode wird verwendet, um eine HTML-Eingabe in einen DocumentFragment
zu analysieren, wobei optional unerwünschte Elemente und Attribute entfernt und Elemente, die laut HTML-Spezifikation im Zielelement nicht erlaubt sind, verworfen werden (wie z.B. <li>
innerhalb eines <div>
).
Der DocumentFragment
wird dann verwendet, um den Teilbaum des Elements im DOM zu ersetzen.
Anders als bei Element.innerHTML
werden deklarative Shadow Roots in der Eingabe in das DOM analysiert.
Wenn der HTML-String mehr als eine deklarative Shadow Root in einem bestimmten Shadow Host definiert, wird nur die erste ShadowRoot
erstellt — nachfolgende Deklarationen werden als <template>
Elemente innerhalb dieser Shadow Root analysiert.
setHTMLUnsafe()
führt standardmäßig keine Sanitärmaßnahmen durch.
Wenn kein Sanitizer als Parameter übergeben wird, werden alle HTML-Entitäten in der Eingabe eingefügt.
Es ist daher potenziell noch weniger sicher als Element.innerHTML
, das die Ausführung von <script>
deaktiviert, wenn es analysiert wird.
Sicherheitsüberlegungen
Das Suffix "Unsafe" im Methodennamen weist darauf hin, dass es nicht die Entfernung aller XSS-unschädlichen HTML-Entitäten erzwingt (im Gegensatz zu Element.setHTML()
).
Obwohl es dies tun kann, wenn es mit einem geeigneten Sanitizer verwendet wird, muss es keinen effektiven Sanitizer verwenden, oder überhaupt einen Sanitizer!
Die Methode ist daher ein potenzieller Vektor für Cross-site-scripting (XSS) Angriffe, bei denen möglicherweise unsichere vom Benutzer bereitgestellte Zeichenfolgen in das DOM eingefügt werden, ohne dass sie zuvor gesäubert werden.
Sie sollten dieses Risiko mindern, indem Sie immer TrustedHTML
Objekte anstelle von Zeichenfolgen übergeben und trusted types erzwingen mit der require-trusted-types-for
CSP-Direktive.
Dies stellt sicher, dass die Eingabe durch eine Transformationsfunktion läuft, die die Möglichkeit hat, die Eingabe zu säubern, um potenziell gefährliche Markups (wie <script>
Elemente und Ereignishandlerattribute) zu entfernen, bevor sie eingefügt wird.
Die Nutzung von TrustedHTML
ermöglicht es, die Säuberungscodes nur an wenigen Stellen zu prüfen und zu überprüfen, statt sie über alle Injektionspfade zu verteilen.
Sie sollten keinen Sanitizer an die Methode übergeben müssen, wenn Sie TrustedHTML
verwenden.
Wenn Sie aus irgendeinem Grund TrustedHTML
(oder noch besser, setHTML()
) nicht verwenden können, dann ist die nächste sichere Option, setHTMLUnsafe()
mit dem XSS-sicheren Standard Sanitizer
zu verwenden.
Wann sollte setHTMLUnsafe()
verwendet werden?
setHTMLUnsafe()
sollte fast nie verwendet werden, wenn Element.setHTML()
verfügbar ist, weil es nur sehr wenige (wenn überhaupt) Fälle gibt, in denen benutzerdefinierter HTML-Eingang XSS-unschädliche Elemente enthalten muss.
Nicht nur ist setHTML()
sicher, es vermeidet auch das Berücksichtigen von trusted types.
Die Verwendung von setHTMLUnsafe()
könnte angemessen sein, wenn:
-
Sie
setHTML()
oder trusted types nicht verwenden können (aus welchen Gründen auch immer) und Sie die sicherste mögliche Filterung benötigen. In diesem Fall könnten SiesetHTMLUnsafe()
mit dem StandardSanitizer
verwenden, um alle XSS-unschädlichen Elemente zu filtern. -
Sie
setHTML()
nicht verwenden können und die Eingabe deklarative Shadow Roots enthalten könnte, sodass SieElement.innerHTML
nicht verwenden können. -
Sie einen Sonderfall haben, bei dem Sie HTML-Eingaben erlauben müssen, die eine bekannte Menge unsicherer HTML-Entitäten enthalten.
Sie können
setHTML()
in diesem Fall nicht verwenden, weil es alle unsicheren Entitäten entfernt. Sie könntensetHTMLUnsafe()
ohne einen Sanitizer oderinnerHTML
verwenden, aber das würde alle unsicheren Entitäten erlauben.Eine bessere Option hier ist,
setHTMLUnsafe()
mit einem Sanitizer zu verwenden, der nur die gefährlichen Elemente und Attribute erlaubt, die wir tatsächlich benötigen. Auch wenn dies noch unsicher ist, ist es sicherer als alle zu erlauben.
Für den letzten Punkt, bedenken Sie eine Situation, in der Ihr Code darauf angewiesen ist, unsichere onclick
-Handler zu verwenden.
Der folgende Code zeigt die Wirkung der verschiedenen Methoden und Sanitizer für diesen Fall.
const target = document.querySelector("#target");
const input = "<img src=x onclick=alert('onclick') onerror=alert('onerror')>";
// Safe - removes all XSS-unsafe entities.
target.setHTML(input);
// Removes no event handler attributes
target.setHTMLUnsafe(input);
target.innerHTML = input;
// Safe - removes all XSS-unsafe entities.
const configSafe = new Sanitizer();
target.setHTMLUnsafe(input, { sanitizer: configSafe });
// Removes all XSS-unsafe entities except `onclick`
const configLessSafe = new Sanitizer();
config.allowAttribute("onclick");
target.setHTMLUnsafe(input, { sanitizer: configLessSafe });
Beispiele
>setHTMLUnsafe() mit Trusted Types
Um das Risiko von XSS zu mildern, erstellen wir zuerst ein TrustedHTML
Objekt aus der Zeichenfolge, die das HTML enthält, und übergeben dann dieses Objekt an setHTMLUnsafe()
.
Da trusted types noch nicht in allen Browsern unterstützt werden, definieren wir den trusted types tinyfill.
Dies fungiert als transparenter Ersatz für die trusted types JavaScript-API:
if (typeof trustedTypes === "undefined")
trustedTypes = { createPolicy: (n, rules) => rules };
Als Nächstes erstellen wir eine TrustedTypePolicy
, die eine createHTML()
definiert, um eine Eingabezeichenfolge in TrustedHTML
Instanzen zu transformieren.
In der Regel verwenden Implementierungen von createHTML()
eine Bibliothek wie DOMPurify, um die Eingabe zu säubern, wie unten gezeigt:
const policy = trustedTypes.createPolicy("my-policy", {
createHTML: (input) => DOMPurify.sanitize(input),
});
Dann verwenden wir dieses policy
Objekt, um ein TrustedHTML
Objekt aus der möglicherweise unsicheren Eingabezeichenfolge zu erstellen:
// The potentially malicious string
const untrustedString = "abc <script>alert(1)<" + "/script> def";
// Create a TrustedHTML instance using the policy
const trustedHTML = policy.createHTML(untrustedString);
Da wir jetzt trustedHTML
haben, zeigt der folgende Code, wie Sie es mit setHTMLUnsafe()
verwenden können.
Die Eingabe wurde durch die Transformationsfunktion geführt, also übergeben wir keinen Sanitizer an die Methode.
// Get the target Element with id "target"
const target = document.getElementById("target");
// setHTMLUnsafe() with no sanitizer
target.setHTMLUnsafe(trustedHTML);
Verwendung von setHTMLUnsafe() ohne Trusted Types
Dieses Beispiel zeigt den Fall, in dem wir keine trusted types verwenden, sodass wir Sanitizer-Argumente übergeben werden.
Der Code erstellt eine nicht vertrauenswürdige Zeichenfolge und zeigt eine Reihe von Möglichkeiten, wie ein Sanitizer an die Methode übergeben werden kann.
// The potentially malicious string
const untrustedString = "abc <script>alert(1)<" + "/script> def";
// Get the target Element with id "target"
const target = document.getElementById("target");
// Define custom Sanitizer and use in setHTMLUnsafe()
// This allows only elements: div, p, button, script
const sanitizer1 = new Sanitizer({
elements: ["div", "p", "button", "script"],
});
target.setHTMLUnsafe(untrustedString, { sanitizer: sanitizer1 });
// Define custom SanitizerConfig within setHTMLUnsafe()
// Removes the <script> element but allows other potentially unsafe entities.
target.setHTMLUnsafe(untrustedString, {
sanitizer: { removeElements: ["script"] },
});
setHTMLUnsafe()
Live-Beispiel
Dieses Beispiel bietet eine "Live"-Demonstration der Methode, wenn sie mit verschiedenen Sanitisern aufgerufen wird.
Der Code definiert Schaltflächen, auf die Sie klicken können, um eine Zeichenfolge von HTML einzufügen.
Eine Schaltfläche fügt das HTML ein, ohne es überhaupt zu säubern, und die zweite verwendet einen benutzerdefinierten Sanitizer, der <script>
Elemente erlaubt, aber andere unsichere Elemente nicht.
Die ursprüngliche Zeichenfolge und das eingefügte HTML werden protokolliert, sodass Sie die Ergebnisse in jedem Fall inspizieren können.
Hinweis: Da wir zeigen möchten, wie das Sanitizer-Argument verwendet wird, injiziert der folgende Code eine Zeichenfolge anstelle eines trusted type. Sie sollten dies in Produktionscode nicht tun.
HTML
Das HTML definiert zwei <button>
Elemente zum Aufrufen der Methode mit verschiedenen Sanitisern, eine weitere Schaltfläche zum Zurücksetzen des Beispiels und ein <div>
Element zum Einfügen der Zeichenfolge.
<button id="buttonNoSanitizer" type="button">None</button>
<button id="buttonAllowScript" type="button">allowScript</button>
<button id="reload" type="button">Reload</button>
<div id="target">Original content of target element</div>
JavaScript
Zuerst definieren wir die zu säubernde Zeichenfolge, die für alle Fälle gleich sein wird.
Diese enthält das <script>
Element und den onclick
Handler, die beide als XSS-unsicher gelten.
Wir definieren auch den Handler für die Neuladeschaltfläche.
// Define unsafe string of HTML
const unsanitizedString = `
<div>
<p>This is a paragraph. <button onclick="alert('You clicked the button!')">Click me</button></p>
<script src="path/to/a/module.js" type="module"><script>
</div>
`;
const reload = document.querySelector("#reload");
reload.addEventListener("click", () => document.location.reload());
Als Nächstes definieren wir den Klick-Handler für die Schaltfläche, die das HTML ohne Sanitizer setzt.
Im Allgemeinen würden wir erwarten, dass die Methode Elemente in der Zeichenfolge, die im Kontext nicht erlaubt sind (wie tabellenspezifische Elemente in einem <div>
Element) verwirft, aber ansonsten die Eingabezeichenfolge abgleicht.
In diesem Fall sollten die Zeichenfolgen übereinstimmen.
const buttonNoSanitizer = document.querySelector("#buttonNoSanitizer");
buttonNoSanitizer.addEventListener("click", () => {
// Set unsafe HTML without specifying a sanitizer
target.setHTMLUnsafe(unsanitizedString);
// Log HTML before sanitization and after being injected
logElement.textContent =
"No sanitizer: string should be injected without filtering\n\n";
log(`\nunsanitized: ${unsanitizedString}`);
log(`\nsanitized: ${target.innerHTML}`);
});
Der nächste Klick-Handler setzt das Ziel-HTML mithilfe eines benutzerdefinierten Sanitizers, der nur <div>
, <p>
, und <script>
Elemente erlaubt.
Beachten Sie, dass durch die Verwendung der setHTMLUnsafe()
Methode <script>
nicht entfernt werden!
const allowScriptButton = document.querySelector("#buttonAllowScript");
allowScriptButton.addEventListener("click", () => {
// Set the content of the element using a custom sanitizer
const sanitizer1 = new Sanitizer({
elements: ["div", "p", "script"],
});
target.setHTMLUnsafe(unsanitizedString, { sanitizer: sanitizer1 });
// Log HTML before sanitization and after being injected
logElement.textContent = "Sanitizer: {elements: ['div', 'p', 'script']}\n";
log(`\nunsanitized: ${unsanitizedString}`);
log(`\nsanitized: ${target.innerHTML}`);
});
Ergebnisse
Klicken Sie auf die "None" und "allowScript" Schaltflächen, um die Auswirkungen von keinem Sanitizer und einem benutzerdefinierten Sanitizer zu sehen.
Wenn Sie auf die "None" Schaltfläche klicken, sollten Sie sehen, dass die Eingabe und Ausgabe übereinstimmen, da kein Sanitizer angewendet wird.
Wenn Sie auf die "allowScript" Schaltfläche klicken, ist das <script>
Element noch vorhanden, aber das <button>
Element wird entfernt.
Mit diesem Ansatz können Sie sicheres HTML erstellen, sind aber nicht dazu gezwungen.
Spezifikationen
Specification |
---|
HTML> # dom-element-sethtmlunsafe> |
Browser-Kompatibilität
Loading…