Un comentario que ejecuta algo
La web de una asociación de vecinos tiene un libro de visitas donde cualquiera deja un comentario. Alguien escribe un comentario con una etiqueta de script. Desde ese día, cada persona que abre la página ejecuta ese script sin saberlo.
La web guardó un texto y lo devolvió tal cual. El navegador no distingue el texto de un visitante del código de la propia web.
La regla única
Advertencia
Este laboratorio es una web insegura a propósito. Ataca solo tu copia privada, que no tiene salida a internet. Atacar un sistema que no es tuyo, o que no tienes permiso para probar, es delito en casi todos los países.
Al final de esta lección
Nota
Puedo explicar y evitar el cross-site scripting escapando lo que se muestra.
Palabras clave
| Palabra | Qué significa | Ejemplo |
|---|---|---|
| HTML | el lenguaje con el que se describe una página | |
| Script | programa pequeño que el navegador ejecuta dentro de una página | |
| XSS | fallo por el que el texto de otra persona se ejecuta como script en tu página | |
| Escapar | cambiar los signos especiales por texto inofensivo | < pasa a < |
| Cookie | dato pequeño que el navegador guarda para una web | PHPSESSID |
| HttpOnly | marca que impide a los scripts leer una cookie |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
El texto llega de dos formas
En el XSS reflejado, el texto viaja en la dirección y la página lo devuelve al momento. Hace falta que la víctima abra un enlace preparado.
En el XSS almacenado, la web guarda el texto y lo muestra a todos los que abren la página. No hace falta ningún enlace. Por eso es el más peligroso.
Ejemplo resuelto: reflejado y almacenado
| Tipo | Dónde queda el texto | Quién lo sufre |
|---|---|---|
| Reflejado | En la dirección y en la respuesta inmediata | Quien abre el enlace preparado |
| Almacenado | En la base de datos de la web | Cada persona que abre la página |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Mira la web de tu laboratorio
Tu laboratorio tiene la web que vas a probar. Arráncalo y ejecuta estos tres comandos. Solo miran la página de acceso. No inician sesión y no escriben ningún script.
Las cookies importan. Un script que se ejecuta en una página puede leer sus cookies, salvo que la cookie lleve la marca HttpOnly.
¿Está la web en marcha?
curl -s -o /dev/null -w "%{http_code}\n" http://dvwa/login.phpSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Las cookies que pone la web
curl -s -I http://dvwa/login.php | grep -i "^set-cookie"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
¿Cuántas cookies dicen HttpOnly?
curl -s -I http://dvwa/login.php | grep -ic httponlySe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Qué te dicen las tres respuestas
El primero imprime 200. El segundo imprime dos líneas: una cookie llamada security y otra PHPSESSID, que es la sesión. El tercero imprime 0.
Ninguna cookie dice HttpOnly. Un script que lograra ejecutarse en esta web podría leer la cookie de sesión. Por eso el XSS suele acabar en sesiones robadas.
Escapar convierte los signos especiales en texto
El navegador toma < como el inicio de una etiqueta. Si la web escribe < en su lugar, el navegador muestra el signo y no lo ejecuta.
Cinco signos se escapan: &, <, >, la comilla doble y la comilla simple. El & va primero. Si no, escaparías dos veces el & que acabas de crear.
Escapar un comentario
comment = "<b>Hola</b> & gracias"
# Cambia el comentario y pulsa Run. El orden de los cambios importa.
safe = comment.replace("&", "&")
safe = safe.replace("<", "<")
safe = safe.replace(">", ">")
print(safe)
Ejemplo resuelto: cinco signos
| Signo | Se escribe | Por qué importa |
|---|---|---|
| & | & | Empieza todas las demás entidades |
| < | < | Abre una etiqueta |
| > | > | Cierra una etiqueta |
| " | " | Cierra un valor entre comillas dobles |
| ' | ' | Cierra un valor entre comillas simples |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Un error frecuente
Advertencia
Mucha gente cree que basta con prohibir la palabra script. No es así. Hay otras etiquetas y atributos que ejecutan código, y las mayúsculas engañan a los filtros. Escapa al mostrar, siempre, con una sola función. No intentes adivinar qué texto es peligroso.
El escapado depende del sitio
El texto puede acabar en el cuerpo de la página, dentro de un atributo o dentro de un script. Cada sitio necesita su propio escapado.
Las cookies con HttpOnly y una política de contenido (CSP) son una segunda defensa. No sustituyen al escapado.
Para ir más allá: dentro de un atributo
El código de show-escape solo cambia tres signos. Pon el comentario dentro de un atributo: print('<img alt="' + safe + '">').
Prueba con el comentario x" onmouseover="y y pulsa Run. Explica qué atributo nuevo aparece, y añade el cambio que lo impide.