LFI2RCE via Eternal waiting

Reading time: 6 minutes

tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

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.

Observe 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 carregados 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 só precisamos controlar um caminho relativo. Se conseguirmos carregar arquivos e fazer o LFI nunca acabar, teremos "tempo suficiente" para forçar a força bruta de arquivos carregados e encontrar qualquer um dos arquivos carregados.

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 carregados 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 demais
  • Timeout para uma solicitação PHP. Idealmente, isso deveria ser eterno ou deveria matar o processo PHP sem excluir os arquivos temporários carregados, caso contrário, isso também será um problema

Então, como você pode fazer um include PHP nunca acabar? Apenas incluindo 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/ é 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.

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 acelerará 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:

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 eterno.

Nginx

Parece que por padrão o Nginx suporta 512 conexões paralelas ao mesmo tempo (e esse número pode ser melhorado).

tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks