mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
98 lines
6.6 KiB
Markdown
98 lines
6.6 KiB
Markdown
# LFI2RCE via Eternal waiting
|
|
|
|
{{#include ../../banners/hacktricks-training.md}}
|
|
|
|
## Informações Básicas
|
|
|
|
Por padrão, quando um arquivo é enviado para o PHP (mesmo que não esteja esperando por isso), ele gerará um arquivo temporário em `/tmp` com um nome como **`php[a-zA-Z0-9]{6}`**, embora eu tenha visto algumas imagens do docker onde os arquivos gerados não contêm dígitos.
|
|
|
|
Em uma inclusão de arquivo local, **se você conseguir incluir esse arquivo enviado, você obterá RCE**.
|
|
|
|
Note que, por padrão, **o PHP só permite o upload de 20 arquivos em uma única solicitação** (configurado em `/etc/php/<version>/apache2/php.ini`):
|
|
```
|
|
; Maximum number of files that can be uploaded via a single request
|
|
max_file_uploads = 20
|
|
```
|
|
Além disso, o **número de nomes de arquivos potenciais é 62\*62\*62\*62\*62\*62 = 56800235584**
|
|
|
|
### Outras técnicas
|
|
|
|
Outras técnicas dependem de atacar protocolos PHP (você não conseguirá se controlar apenas a última parte do caminho), divulgar o caminho do arquivo, abusar de arquivos esperados ou **fazer o PHP sofrer uma falha de segmentação para que arquivos temporários enviados não sejam excluídos**.\
|
|
Esta técnica é **muito semelhante à última, mas sem precisar encontrar um zero day**.
|
|
|
|
### Técnica de espera eterna
|
|
|
|
Nesta técnica **nós só precisamos controlar um caminho relativo**. Se conseguirmos enviar arquivos e fazer o **LFI nunca acabar**, teremos "tempo suficiente" para **forçar a força bruta de arquivos enviados** e **encontrar** qualquer um dos arquivos enviados.
|
|
|
|
**Prós desta técnica**:
|
|
|
|
- Você só precisa controlar um caminho relativo dentro de um include
|
|
- Não requer nginx ou nível inesperado de acesso a arquivos de log
|
|
- Não requer um 0 day para causar uma falha de segmentação
|
|
- Não requer divulgação de caminho
|
|
|
|
Os **principais problemas** desta técnica são:
|
|
|
|
- Necessidade de um arquivo(s) específico(s) estar presente (pode haver mais)
|
|
- A **quantidade insana** de nomes de arquivos potenciais: **56800235584**
|
|
- Se o servidor **não estiver usando dígitos**, a quantidade total potencial é: **19770609664**
|
|
- Por padrão, **apenas 20 arquivos** podem ser enviados em uma **única solicitação**.
|
|
- O **número máximo de trabalhadores paralelos** do servidor utilizado.
|
|
- Este limite com os anteriores pode fazer com que este ataque dure muito
|
|
- **Timeout para uma solicitação PHP**. Idealmente, isso deveria ser eterno ou deveria matar o processo PHP sem excluir os arquivos temporários enviados, caso contrário, isso também será um problema
|
|
|
|
Então, como você pode **fazer um include PHP nunca acabar**? Basta incluir o arquivo **`/sys/kernel/security/apparmor/revision`** (**não disponível em contêineres Docker** infelizmente...).
|
|
|
|
Tente apenas chamando:
|
|
```bash
|
|
php -a # open php cli
|
|
include("/sys/kernel/security/apparmor/revision");
|
|
```
|
|
## Apache2
|
|
|
|
Por padrão, o Apache suporta **150 conexões simultâneas**, seguindo [https://ubiq.co/tech-blog/increase-max-connections-apache/](https://ubiq.co/tech-blog/increase-max-connections-apache/) é possível aumentar esse número para até 8000. Siga isso para usar PHP com esse módulo: [https://www.digitalocean.com/community/tutorials/how-to-configure-apache-http-with-mpm-event-and-php-fpm-on-ubuntu-18-04](https://www.digitalocean.com/community/tutorials/how-to-configure-apache-http-with-mpm-event-and-php-fpm-on-ubuntu-18-04).
|
|
|
|
Por padrão, (como posso ver em meus testes), um **processo PHP pode durar eternamente**.
|
|
|
|
Vamos fazer algumas contas:
|
|
|
|
- Podemos usar **149 conexões** para gerar **149 \* 20 = 2980 arquivos temporários** com nosso webshell.
|
|
- Em seguida, use a **última conexão** para **forçar** arquivos potenciais.
|
|
- A uma velocidade de **10 requisições/s**, os tempos são:
|
|
- 56800235584 / 2980 / 10 / 3600 \~= **530 horas** (50% de chance em 265h)
|
|
- (sem dígitos) 19770609664 / 2980 / 10 / 3600 \~= 185h (50% de chance em 93h)
|
|
|
|
> [!WARNING]
|
|
> Note que no exemplo anterior estamos **completamente DoSing outros clientes**!
|
|
|
|
Se o servidor Apache for melhorado e pudéssemos abusar de **4000 conexões** (metade do número máximo). Poderíamos criar `3999*20 = 79980` **arquivos** e o **número** seria **reduzido** para cerca de **19.7h** ou **6.9h** (10h, 3.5h 50% de chance).
|
|
|
|
## PHP-FMP
|
|
|
|
Se em vez de usar o módulo php regular para apache para executar scripts PHP a **página da web está usando** **PHP-FMP** (isso melhora a eficiência da página da web, então é comum encontrá-lo), há algo mais que pode ser feito para melhorar a técnica.
|
|
|
|
PHP-FMP permite **configurar** o **parâmetro** **`request_terminate_timeout`** em **`/etc/php/<php-version>/fpm/pool.d/www.conf`**.\
|
|
Esse parâmetro indica a quantidade máxima de segundos **quando** **a requisição ao PHP deve terminar** (infinito por padrão, mas **30s se o parâmetro estiver descomentado**). Quando uma requisição está sendo processada pelo PHP, o número indicado de segundos é **morto**. Isso significa que, se a requisição estava fazendo upload de arquivos temporários, porque o **processamento php foi interrompido**, esses **arquivos não serão deletados**. Portanto, se você conseguir fazer uma requisição durar esse tempo, pode **gerar milhares de arquivos temporários** que não serão deletados, o que **acelera o processo de encontrá-los** e reduz a probabilidade de um DoS na plataforma consumindo todas as conexões.
|
|
|
|
Então, para **evitar DoS**, vamos supor que um **atacante estará usando apenas 100 conexões** ao mesmo tempo e o tempo máximo de processamento php por **php-fmp** (`request_terminate_timeout`**)** é **30s**. Portanto, o número de **arquivos temporários** que podem ser gerados **por segundo** é `100*20/30 = 66.67`.
|
|
|
|
Então, para gerar **10000 arquivos**, um atacante precisaria: **`10000/66.67 = 150s`** (para gerar **100000 arquivos** o tempo seria **25min**).
|
|
|
|
Então, o atacante poderia usar essas **100 conexões** para realizar uma **busca por força bruta**. Supondo uma velocidade de 300 req/s, o tempo necessário para explorar isso é o seguinte:
|
|
|
|
- 56800235584 / 10000 / 300 / 3600 \~= **5.25 horas** (50% de chance em 2.63h)
|
|
- (com 100000 arquivos) 56800235584 / 100000 / 300 / 3600 \~= **0.525 horas** (50% de chance em 0.263h)
|
|
|
|
Sim, é possível gerar 100000 arquivos temporários em uma instância EC2 de tamanho médio:
|
|
|
|
<figure><img src="../../images/image (240).png" alt=""><figcaption></figcaption></figure>
|
|
|
|
> [!WARNING]
|
|
> Note que para acionar o timeout seria **suficiente incluir a página LFI vulnerável**, para que entre em um loop de inclusão eterna.
|
|
|
|
## Nginx
|
|
|
|
Parece que por padrão o Nginx suporta **512 conexões paralelas** ao mesmo tempo (e esse número pode ser melhorado).
|
|
|
|
{{#include ../../banners/hacktricks-training.md}}
|