PHP2Shell: falhas críticas no PHP e como se proteger
As falhas críticas no PHP CVE-2026-109618 e CVE-2026-109619 deixam invadir o servidor sem login. Veja como corrigir, mesmo sem poder atualizar.
Em resumo
Em 21 de outubro de 2026 saíram correções de emergência para duas falhas críticas no PHP, a CVE-2026-109618 e a CVE-2026-109619, apelidadas de PHP2Shell. As duas permitem que alguém sem login execute código no seu servidor usando requisições HTTP. A correção completa é atualizar para o PHP 8.5.12, 8.4.27, 8.3.36 ou 8.2.35, ou para o pacote corrigido da sua distribuição, e reiniciar o PHP. Quem não pode atualizar hoje tem medidas que reduzem o risco, mas não o eliminam.
Atualização em 23 de outubro: o PHP divulgou outra falha, a CVE-2026-115560, bem mais restrita. A configuração session.upload_progress.enabled=0, recomendada abaixo, também a bloqueia. Os detalhes estão em Nova falha no PHP CVE-2026-115560.
O que aconteceu
O projeto PHP publicou as versões 8.5.12, 8.4.27, 8.3.36 e 8.2.35 às 11h (horário de Brasília) desta quarta-feira, 21 de outubro. Elas corrigem duas falhas com nota 9,2 de 10 no CVSS, a escala usada para medir a gravidade de vulnerabilidades.
As duas levam à execução remota de código: o atacante faz o servidor rodar comandos dele, com as permissões do usuário que roda o PHP. A partir daí ele pode ler a configuração do site, as senhas do banco de dados e as chaves de API, trocar páginas ou instalar programas no servidor.
Segundo o aviso oficial, está em risco toda instalação do PHP que atende requisições web: PHP-FPM, Apache com mod_php, php-cgi, FrankenPHP e LiteSpeed. O caso mais grave é o mod_php, em que uma requisição sem login dispara o ataque antes de qualquer código da aplicação rodar. Senha forte, plugin de segurança ou tela de login na aplicação não protegem.
Como a falha está na linguagem, e não num sistema específico, ela alcança WordPress, Drupal, Joomla, Magento, Laravel e qualquer outro sistema em PHP. A Calif, empresa que reportou as falhas primeiro, confirmou o ataque sem login contra versões recentes de WordPress, Drupal, Joomla, Magento, Nextcloud e phpMyAdmin, entre outros.
As duas falhas, sem jargão
O PHP atende o site com workers: processos que recebem uma requisição atrás da outra. As duas falhas exploram o que acontece quando uma requisição é interrompida no meio.
CVE-2026-109618: memória que acaba na hora errada
Todo PHP tem um teto de memória por requisição, o memory_limit. Quando uma requisição bate nesse teto, o PHP aborta a operação na hora. Em alguns pontos, porém, ele já tinha marcado dados internos como prontos antes de terminar de prepará-los. Ao encerrar a requisição, trata esses dados pela metade como válidos e corrompe a memória.
O atacante provoca isso de propósito com envios de formulário com arquivos (multipart) montados para esgotar a memória: requisições sem tamanho declarado, partes com cabeçalhos demais ou campos de arquivo vazios com nomes aninhados. No mod_php, a execução de código foi demonstrada com a configuração padrão. A correção muda o jeito de o PHP lidar com a falta de memória: em vez de abortar no meio da operação, ele espera um ponto seguro para encerrar a requisição.
CVE-2026-109619: sobra de uma requisição usada pela próxima
Alguns dados internos do PHP, de erro, de sessão e de extensões, sobrevivem de uma requisição para a outra no mesmo worker. Se a requisição anterior terminou com um erro fatal, uma falta de memória ou um tempo esgotado, esses dados podem continuar apontando para memória que já foi liberada. A requisição seguinte usa essa memória, um erro conhecido como use-after-free (uso depois de liberar), e o atacante consegue vazar dados da memória do servidor ou executar código.
Para isso ele precisa de duas peças no mesmo worker: uma requisição que deixa a sobra e outra que a usa antes de o PHP reiniciar esse estado. As que usam a sobra, confirmadas até agora, são o progresso de upload da sessão (session.upload_progress) e os avisos de configuração aplicada por diretório, como um php_value inválido no .htaccess.
Como as falhas foram encontradas
Os primeiros sinais apareceram em 2024. Um desenvolvedor do núcleo do PHP viu o problema de falta de memória enquanto corrigia outra falha. Na época, um ataque foi teorizado, mas ninguém tinha um caminho concreto para ele.
Em 30 de julho de 2026, a Calif começou a auditar o PHP dentro do Patch the Planet, iniciativa da OpenAI com projetos de código aberto. O pesquisador Ryan Austin estudava justamente o que acontece quando uma requisição estoura o limite de memória e, em 1º de agosto, achou o primeiro caminho. Segundo a Calif, o achado veio do conhecimento do histórico de falhas do PHP. Depois dele, a equipe usou agentes de IA para procurar o mesmo padrão no resto do código.
A cronologia, pelos relatos da Calif e da PHP Foundation:
- 11 de agosto: a Calif reporta a primeira falha. A OpenAI reporta a mesma causa no mesmo dia.
- 14 e 15 de agosto: a Calif envia uma prova de execução de código, e o PHP confirma que ela funciona.
- 21 de agosto: a Calif reporta a segunda falha.
- 24 de agosto: a Wiz, que chegou ao problema de forma independente, também reporta.
- 20 de outubro, por volta do meio-dia: os números das CVEs começam a circular em fóruns e redes sociais, com data errada e nota 10. O PHP antecipa o aviso e traz a publicação do dia 22 para o dia 21.
- 20 de outubro, no fim da tarde: a Calif publica por engano um vídeo do ataque funcionando em vários alvos, que se espalha pelas redes.
- 21 de outubro, de madrugada: a Chainguard publica imagens com a correção antes do horário combinado, o que permite estudar a mudança antes da hora.
- 21 de outubro, 11h: saem as versões corrigidas e os avisos oficiais.
A correção levou dois meses. Ela mexe no controle de memória e no tratamento de erros, partes que quase toda requisição usa. A PHP Foundation reconheceu que a demora também veio do seu processo de decisão e da falta de recursos, e anunciou mudanças nos dois.
Segundo a equipe de segurança do PHP, não havia ataque funcional público no momento da publicação. A Amazon, porém, diz ter registrado uma tentativa de exploração em 17 de outubro e outras no dia 21, e a Cloudflare relatou os primeiros ataques no dia da publicação. Já circula código de ataque na internet. Não rode esse código para testar o seu servidor: ninguém o verificou, e ele pode trazer malware.
Se você pode atualizar
Atualizar é a única correção completa. Estas são as versões que trazem a correção:
| Versão em uso | Atualize para |
|---|---|
| 8.5 | 8.5.12 |
| 8.4 | 8.4.27 |
| 8.3 | 8.3.36 |
| 8.2 | 8.2.35 |
| 8.1, 8.0 e 7.4 | sem versão oficial (veja abaixo) |
| 7.3 ou anterior | sem correção do PHP |
Descubra primeiro a versão que o servidor web usa. O php -v mostra a versão de linha de comando, que pode ser outra. O binário do FPM (php-fpm8.3 -v no Debian e no Ubuntu) ou uma página com phpinfo(), apagada logo em seguida, mostram a versão certa.
Depois atualize pelo mesmo caminho por onde o PHP foi instalado:
- Pacote da distribuição (
apt,dnf): as distribuições Linux e os fornecedores de suporte estendido receberam a correção antes da divulgação. Algumas aplicam a correção sem mudar o número da versão do PHP, só o sufixo do pacote. Confira pelo histórico do pacote:apt changelog php8.3-fpm | grep CVE-2026-109618ourpm -q --changelog php-fpm | grep CVE-2026-109618. - Repositório do Remi: o PHP avisou que ele não teria atualização no dia da divulgação e recomenda trocar pelos pacotes da distribuição ou compilar do código-fonte.
- Docker: troque a imagem base por uma versão corrigida, refaça a imagem e suba os containers de novo.
- Hospedagem compartilhada ou painel (cPanel, Plesk): quem atualiza é o provedor. Confira a versão no painel e pergunte ao suporte se a correção já foi aplicada.
- Código-fonte: baixe a versão corrigida em php.net e compile.
Reinicie o PHP-FPM e o Apache em seguida (systemctl restart php8.3-fpm, systemctl restart apache2). Um worker antigo continua rodando o código vulnerável até ser reiniciado. Confira a versão de novo depois do reinício.
Se você não pode atualizar agora
As medidas abaixo fecham os caminhos de ataque conhecidos, mas não as variantes. O PHP é claro: elas reduzem a exposição e não deixam a instalação segura. A CISA, agência de cibersegurança dos Estados Unidos, recomenda tirar do ar o sistema em PHP que não possa ser atualizado de imediato. Quando isso não for possível, aplique tudo o que couber e marque a data da atualização.
Feche os caminhos conhecidos na configuração
Aplique no php.ini, no pool do PHP-FPM ou na configuração do Apache. Não use ini_set() nem .user.ini: eles agem tarde demais, e a aplicação pode desfazer a mudança. Num pool do PHP-FPM:
; /etc/php/8.3/fpm/pool.d/www.conf
; tira o teto de memória que o ataque usa (CVE-2026-109618)
php_admin_value[memory_limit] = -1
; desliga o progresso de upload da sessão (CVE-2026-109619)
php_admin_flag[session.upload_progress.enabled] = off
; limita o tamanho do envio: 8M sem upload de arquivos, 32M com
php_admin_value[post_max_size] = 8M
No Apache com mod_php, as mesmas diretivas vão no VirtualHost:
php_admin_value memory_limit -1
php_admin_flag session.upload_progress.enabled off
php_admin_value post_max_size 8M
O que cada uma faz e o que custa:
memory_limit = -1: sem teto, o atacante não consegue forçar a falta de memória pelo limite do PHP. O custo é que uma requisição pode consumir a memória toda do servidor. Compense com um limite no container ou no cgroup, de preferência um que derrube só o worker afetado, e acompanhe o uso de memória. Não useulimit(RLIMIT_ASouRLIMIT_DATA) para isso: ele faz a alocação falhar e reabre o caminho vulnerável. Volte o limite normal depois de atualizar.session.upload_progress.enabled = off: o recurso só serve para barras de progresso de upload, e poucas aplicações o usam. O PHP recomenda deixá-lo desligado mesmo depois da atualização, se você não precisa dele.post_max_sizebaixo: reduz o espaço para montar o ataque. Mantenhaupload_max_filesizemenor quepost_max_size.- No PHP 8.5,
fatal_error_backtraces = off: fecha o caminho confirmado que passa pelo rastro de erros fatais.
Reinicie todos os workers depois de mudar a configuração e confira que nenhum pool, .htaccess ou configuração da aplicação volta a impor um limite de memória.
Barre o ataque antes de ele chegar ao PHP
No Nginx, no Apache ou no proxy, limite o tamanho da requisição, inclusive das que chegam sem tamanho declarado, e o número de campos, de partes de upload e de cabeçalhos. No PHP, baixe max_input_vars e max_input_nesting_level. Se a aplicação não recebe arquivos, bloqueie as requisições multipart/form-data antes do PHP.
Um WAF (firewall de aplicação web, um filtro que examina o tráfego antes de ele chegar ao servidor) ajuda como paliativo. A Cloudflare publicou regras para os ataques conhecidos, liberadas em todos os planos, inclusive no gratuito. Elas só cobrem o tráfego que passa pela Cloudflare, e já há tentativas de contorno.
Corrija o que termina em erro fatal
A segunda falha depende de uma requisição que termina em erro fatal ou tempo esgotado. Revise o log de erros e corrija os erros fatais que um visitante consegue provocar: upload, importação, páginas de erro. Tire do .htaccess as diretivas php_value inválidas ou obsoletas, que geram avisos antes de a requisição começar. Esconder os erros com display_errors, error_reporting ou @ não adianta.
Se o desempenho não for prioridade, pm.max_requests = 1 no pool do PHP-FPM faz cada worker atender uma única requisição, e não sobra nada para a próxima. O custo é um servidor bem mais lento.
PHP 8.1 ou mais antigo
Não há versão oficial corrigida. A equipe de segurança do PHP publicou correções mínimas no código-fonte do 7.4, do 8.0 e do 8.1, para quem compila o próprio PHP. Quem usa uma distribuição com suporte estendido deve procurar a correção do fornecedor. Do 7.3 para trás, até o 5.4, não há correção: isole o sistema, deixe-o acessível só por VPN ou por uma lista de IPs, e planeje a migração para o 8.4 ou o 8.5.
Depois de corrigir, procure sinais de invasão
Atualizar fecha a porta, mas não expulsa quem já entrou. A Amazon recomenda revisar o período desde 17 de outubro. Procure por:
- worker do PHP abrindo um shell ou rodando
id,whoami,curl,wget,base64ounc; - arquivos novos em
/tmp,/dev/shm,/var/tmpou nas pastas em que o usuário do site pode gravar, e arquivos PHP desconhecidos nas pastas do site; - mudanças em
authorized_keyse tarefas novas no cron do usuário do site; - usuários novos ou alterados no banco da aplicação, como administradores no WordPress;
- no log, muitos POST grandes do mesmo IP, erros
PHP Fatal errorcomin Unknown on line 0e envios com o campoPHP_SESSION_UPLOAD_PROGRESS; - conexões de saída estranhas a partir do servidor.
Apague também as sessões gravadas na pasta de session.save_path: uma sessão adulterada antes da correção continua sendo lida até expirar. Os usuários vão precisar entrar de novo.
Se encontrar algum sinal, trate como invasão: isole o servidor, troque as senhas e chaves a que ele tinha acesso (banco de dados, APIs, arquivos .env) e restaure de um backup anterior ao ataque.
O que fazer hoje
- Liste todo servidor, container e hospedagem com PHP, inclusive os esquecidos: site antigo, painel, phpMyAdmin.
- Atualize e reinicie, começando pelo que está exposto na internet e pelo que roda mod_php.
- Onde não der para atualizar hoje, aplique as medidas de configuração e marque a data da atualização.
- Revise os logs desde 17 de outubro.
- Se você roda o PHP 8.2 ou anterior, planeje a migração: o 8.2 deixa de receber correções em 31 de dezembro de 2026.
Atualizar servidores e aplicar essas medidas sem derrubar o site é o dia a dia da nossa gestão de servidores. Se a sua aplicação precisa de ajustes para rodar numa versão nova do PHP, veja o nosso desenvolvimento web sob medida.