Cómo prevenir ataques XSS cuando se usa peligrosamenteSetInnerHTML en React

Este artículo pretende mostrar una de las técnicas que utilizamos para mitigar los ataques de scripting entre sitios (XSS) en Jam3. Estas vulnerabilidades pueden aparecer cuando peligrosamente se usa SetInnerHTML incorrectamente, y nuestro objetivo es detectarlo con anticipación y limpiar los valores no confiables.

dangerouslySetInnerHTML es una de las características comúnmente utilizadas para presentar e insertar datos de contenido con formato DOM en la interfaz. Proporciona una serie de beneficios al analizar cadenas HTML en el DOM virtual de React. Sin embargo, es posible que desee pensar dos veces antes de usarlo para la entrada del usuario. Debe tener en cuenta sus vulnerabilidades para evitar ataques XSS.

Ataques XSS

Las secuencias de comandos entre sitios (XSS) permiten a los atacantes (piratas informáticos) inyectar código malicioso en un sitio web para otros usuarios finales. Al hacer esto, los atacantes pueden tener acceso a datos personales, cookies, cámaras web y aún más. Lea más sobre las secuencias de comandos entre sitios.

Copie la siguiente cadena y péguela en el campo de entrada.

https://placeimgxxx.com/320/320/any "onerror =" alert ('inyección xss')

Prevención de XSS

Este problema no está restringido a React; para aprender cómo prevenirlo en su desarrollo web OWASP tiene una buena hoja de trucos de prevención. Un enfoque para evitar ataques XSS es desinfectar los datos. Se puede hacer en el lado del servidor o del lado del cliente; En este artículo, nos centraremos en la solución del lado del cliente.

Prevención de XSS con dangerouslyInnerSetHTML

Desinfectar el contenido en la interfaz cuando se usa peligrosamente SetInnerHTML es siempre una buena práctica de seguridad, incluso con una fuente confiable de verdad. Por ejemplo, otro equipo de desarrollo a cargo de mantener el proyecto cambia la fuente de la verdad sin darse cuenta de cómo podría afectar el sitio. Un cambio como ese puede causar una vulnerabilidad crítica de XSS.

En Jam3, evitamos usar peligrososlySetInnerHTML siempre que sea posible. Cuando es necesario, siempre aplicamos capas de seguridad de desinfección tanto en el back-end como en el front-end. Además, creamos una regla de ESLint llamada no-sanitizer-with-danger dentro de eslint-plugin-jam3 para detectar el uso incorrecto de dangerouslySetInnerHTML.

Regla ESLint

Supongo que ya está familiarizado con ESLint. Si no, comience.

Instalación

Deberá instalar eslint y eslint-plugin-jam3:

$ npm i eslint eslint-plugin-jam3 -save-dev

Extienda los complementos en el archivo de configuración .eslintrc agregando jam3. Puede omitir el prefijo eslint-plugin-. Luego, configure las reglas agregando jam3 / no-sanitizer-with-danger a las reglas. Nota: se recomienda el nivel de error 2. Con esta opción, el código de salida será 1. El nivel de error 1 dará una alerta de advertencia, pero no afectará el código de salida. 0 significa desactivar la regla. El complemento verificará que el contenido pasado a dangerouslySetInnerHTML esté envuelto en esta función de desinfectante. El nombre de la función de contenedor también se puede cambiar en el archivo JSON (sanitizer es el nombre de contenedor predeterminado).

Cómo usarlo

Aquí hay una forma insegura de usar dangerouslySetInnerHTML.

Imagen de captura de pantalla del uso de dangerouslySetInnerHTML sin desinfectante

Una vez que la regla esté habilitada, su editor de código alertará la falta de un desinfectante en peligrosamente SetInnerHTML. Para los fines de este artículo, utilizamos dompurify, puede encontrar una lista extendida de desinfectantes disponibles al final del artículo.

El envoltorio desinfectante debe tener un nombre, para el propósito de este artículo, estamos creando const sanitizer = dompurify.sanitize ;. Sin embargo, se recomienda crear una utilidad de desinfección para abstraer el desinfectante elegido.

Bibliotecas de desinfectante

Nuestro equipo ha investigado y probado muchos desinfectantes y puede recomendar estas 3 bibliotecas.

dompurificar

  • Elimina todo el HTML sucio y devuelve datos HTML limpios
  • npm Descarga semanal 50k +
  • 40 colaboradores
  • Gana 2800+ GitHub ️
  • 5.6kB MINIFIED + GZIPPED

xss

  • Escape de caracteres de entidad HTML para evitar el ataque que se produce para transformar contenido no legible para los usuarios finales
  • npm descarga semanal 30k +
  • 18 colaboradores
  • 5.3kB MINIFIED + GZIPPED
  • Gana 2500+ github ️

filtros xss

  • Escape de caracteres de entidad HTML para evitar el ataque que se produce para transformar contenido no legible para los usuarios finales
  • npm descarga semanal 30k +
  • 5 contribuyentes
  • 2.1kB MINIFIED + GZIPPED
  • Has ganado más de 900 github ️

Conclusión

En resumen, encontrar la biblioteca de desinfectante más adecuada para su proyecto es muy importante para la seguridad. Es posible que desee echar un vistazo a las estrellas de GitHub, los números de descarga de npm y las rutinas de mantenimiento. El uso de no-sanitizer-with-danger en eslint-plugin-jam3 será una gran opción para ayudar a garantizar que todos los datos se purifiquen adecuadamente y ganar confianza de que su proyecto estará a salvo de las vulnerabilidades de XSS.

NOTA: Tenga en cuenta que existe una desventaja de rendimiento al desinfectar los datos en el lado del cliente. Por ejemplo, desinfectar todos los datos a la vez puede ralentizar la carga inicial. Para evitar esto en aplicaciones web a gran escala, puede implementar un enfoque de "desinfección lenta" para desinfectar sobre la marcha.

Lecturas adicionales y fuentes

  • Guía del desarrollador de ESLint
  • Crear un complemento de ESLint
  • eslint-plugin-react
  • eslint-plugin-jam3
  • Secuencias de comandos entre sitios
  • Hoja de trucos de ataque XSS

Contribuyentes

  • Donghyuk (Jacob) Jang / jacob.jang@jam3.com
  • Irán Reyes / iran.reyes@jam3.com
  • Peter Altamirano / peter.altamirano@jam3.com
Jam3 es una agencia de diseño y experiencia que se asocia con marcas innovadoras de todo el mundo. Para obtener más información, visítenos en jam3.com.