CVE-2026-109619: falha crítica em PHP
RCE via stale global state
Publicada em · Atualizada em
Priorize a correção. Ela está sob exploração confirmada pelo CISA, tem alerta oficial do governo brasileiro e tem prova de conceito pública.
O governo federal publicou alerta, recomendação ou boletim que cita esta vulnerabilidade.
- CISC Gov.br · 23 out 2026[Atualização] Vulnerabilidades críticas de execução remota de código PHPler no gov.br ↗
- CTIR Gov · RECOMENDAÇÃO 21/2026 · 22 out 2026Recomendação de Segurança – PHP (CVE-2026-115560)ler no gov.br ↗
- CTIR Gov · RECOMENDAÇÃO 20/2026 · 22 out 2026Recomendação Técnica – Diretrizes de Endurecimento (Hardening): Ocultação de Banners Tecnológicos e Versõesler no gov.br ↗
- CISC Gov.br · 21 out 2026Vulnerabilidades crí´ticas de execução remota de código PHPler no gov.br ↗
- CTIR Gov · ALERTA 93/2026 · 21 out 2026Vulnerabilidades críticas que afeta o PHPler no gov.br ↗
Apply mitigations in accordance with vendor instructions, ensuring compliance with CISA’s BOD 26-04 Prioritizing Security Updates Based on Risk (see URL in Notes) guidance and CISA’s “Forensics Triage Requirements” (see URL in Notes). Follow applicable BOD 26-04 guidance for cloud services or discontinue use of the product if mitigations are unavailable. Stakeholders are responsible for evaluating each asset's internet exposure and ensuring adherence to BOD 26-04 patching guidelines.
Resumo
CVE-2026-109619 (GHSA-6wmf-4rv5-p3rp) é um use-after-free no núcleo do PHP. Estado global que aponta para memória de uma requisição sobrevive ao fim dela e é lido pela requisição seguinte do mesmo worker, antes da inicialização normal. O PHP classifica a falha como RCE sem autenticação (CVSS v4 9.2) e a corrigiu nas versões 8.2.35, 8.3.36, 8.4.27 e 8.5.12. O vetor traz AC:H e AT:P: a exploração exige um 'produtor' e um 'consumidor' do estado obsoleto e um layout de heap controlado. Mesmo assim, há relatos de ataques iniciais e o exploit PHP2Shell vazou, então trate como urgente.
Detalhamento técnico
O PHP mantém estado global (erro, sessão, objetos, extensões) que um worker conserva entre requisições mas que aponta para memória pertencente a uma única requisição. Esse estado precisa ser zerado antes de o heap da requisição ser liberado. O advisory descreve duas formas de ele sobreviver. Na primeira, um erro fatal, inclusive por esgotamento de memória, abandona uma operação antes do reset correspondente. Na segunda, um aviso ou outro diagnóstico não fatal repopula o estado de erro depois que ele já foi limpo no shutdown. O heap é liberado e o campo global continua apontando para ele.
O consumidor é qualquer operação que roda antes da inicialização normal da próxima requisição e lê, libera ou ramifica sobre o valor obsoleto. O advisory cita operações de entrada, configuração, sessão e tratamento de erro. O resultado é um use-after-free (classe CWE-416). O advisory afirma que um layout de heap 'estrategicamente' construído leva a RCE completa. A imprensa técnica (BleepingComputer) também menciona divulgação de memória. O atacante controla indiretamente o que ocupa a memória liberada, por meio da requisição produtora e da seguinte.
O advisório lista condições que geram diagnósticos antes da decisão de reportar, exibir ou logar o aviso. Entre elas: encodings de mbstring/iconv configurados explicitamente; valores inválidos ou conflitantes de zend.assertions, memory_limit, date.timezone e de extensões (DBA, EXIF, mail, OpenSSL, zlib); quantidades malformadas ou com overflow no PHP 8.2+ (memory_limit, tamanho do corpo, timeout, stack); e caminhos de log, mail, sessão ou cache SOAP rejeitados por open_basedir. O trecho que li não mostra o cabeçalho dessa lista, então a classificação exata de cada item como produtor ou consumidor deve ser conferida no advisory. Como o acesso ao estado ocorre antes da decisão de reportar o aviso, error_reporting, o operador @, display_errors=0 e log_errors=0 não protegem. O advisory também cita upload progress de sessão como um dos consumidores. No Apache com mod_php, .htaccess e as diretivas php_value/php_flag/php_admin_* são aplicadas antes de php_request_startup(). O php.ini normal é configuração de startup e não é reaplicado entre requisições.
A falha é irmã da CVE-2026-109618 (OOM corruption, GHSA-w8hw-w9fx-j79w). O changelog do PHP agrupa as duas sob 'Avoid state corruption via bailout'. O advisory da 109618 manda seguir também as recomendações do relatório da 109619.
Como é explorada
Vetor de rede, sem autenticação e sem interação do usuário. A exploração é encadeada: uma requisição produtora deixa estado apontando para memória já liberada, e uma requisição seguinte, atendida pelo mesmo worker, o consome. O worker precisa sobreviver e ser reutilizado entre as duas. Daí o AC:H e o AT:P do vetor, e daí vem a exigência de grooming de heap para chegar a execução de código. Em caso de falha, o atacante provavelmente derruba workers (inferência minha, não confirmada nas fontes). O impacto final, segundo o fornecedor e a imprensa, é execução de código com os privilégios da conta do worker web (www-data, nginx, apache etc.), com possível vazamento de memória.
O que a manchete esconde está no advisory: é preciso haver um produtor e um consumer alcançáveis. As fontes secundárias divergem sobre a exposição. Upwind e ma.ttias afirmam que a configuração padrão é vulnerável, em sites com sessões ou upload de arquivos, ambos habilitados no php.ini padrão. O advisory é mais restritivo e fala em condições específicas (erros fatais ou OOM, valores de configuração que geram avisos, upload progress de sessão). Não encontrei prova independente de qual fração das instalações reais é exploravel de ponta a ponta. O PHP considera o risco maior no mod_php, onde uma requisição não autenticada dispara o ataque antes de qualquer código da aplicação (relato do Patchstack). Também são citados PHP-FPM, php-cgi, FrankenPHP e LiteSpeed.
Sobre exploração ativa, as fontes divergem. A entrada do catálogo que recebemos não registra artefato de exploração. Um screenshot de uma ferramenta chamada PHP2Shell, atribuída à Calif.IO, vazou antes do patch. Segundo a Sansec, a Cloudflare relatou ataques iniciais e publicou regras de WAF em 21/10 às 07:43 UTC, antes do release oficial. The Stack e Patchstack também falam em ataques em curso. Não vi telemetria primária que confirme isso para esta CVE especificamente, em vez da 109618. A Tenable, antes da divulgação, descreveu a 109619 como parte de uma cadeia com outra falha. A divulgação oficial e o BleepingComputer apresentam as duas como RCE independentes, cada uma com seu mecanismo. Não encontrei no KEV da CISA registro desta CVE nem prazo de correção.
Versões
Como se proteger
Atualize para PHP 8.2.35, 8.3.36, 8.4.27 ou 8.5.12, conforme o ramo, e reinicie todos os workers (FPM, Apache, FrankenPHP etc.) para o processo antigo não continuar em memória. A correção está no runtime e não dá para fazer em código de aplicação. O PHP, segundo a Laravel News, afirma que não há mitigação completa. Em imagens de container, reconstrua a base. Em hosting gerenciado, confirme a versão efetivamente carregada, e não só a do pacote instalado.
Se não for possível atualizar hoje, nada elimina o risco. Reduzir a superfície é paliativo parcial: o advisory da 109618 recomenda manter post_max_size conservador, limitar variáveis de entrada, partes multipart e uploads, e bloquear multipart no frontend quando a aplicação não o usa. Um comentário no Hacker News (não confirmei contra o texto integral do advisory) cita session.upload_progress.enabled=Off em php.ini e como php_admin_flag em cada pool FPM, para que configuração por diretório não o reative, por ser um dos consumidores confirmados. O ma.ttias relata que o PHP recomendou fatal_error_backtraces=0 no PHP 8.5 e post_max_size baixo; não consegui confirmar a qual das duas CVEs cada item se aplica. O custo é quebrar uploads grandes e o recurso de progresso de upload. O NCSC do Reino Unido recomenda considerar tirar do ar sistemas que não possam ser corrigidos.
O que não funciona: ajustar error_reporting, usar @ ou desligar display_errors/log_errors, porque o estado é acessado antes da decisão de reportar (advisory). Regras de WAF (a Cloudflare publicou algumas) reduzem ruído, mas não fecham a falha. Ramos sem suporte (8.1 e anteriores, 7.x, 5.x) não têm correção esperada, e para eles a única saída é migrar de ramo.
Como detectar
Não encontrei assinatura confiável publicada. O advisory que li não descreve indicadores de comprometimento, e a falha exige aviso ou erro (que o atacante provoca) e depois uma requisição comum, então não há payload único para casar. Uma requisição de ataque pode parecer tráfego legítimo, e o estado obsoleto só é explorado na requisição seguinte, em outro ponto do log.
Pistas razoáveis, por inferência a partir do mecanismo (não comprovadas): sequências de erros fatais por esgotamento de memória ou avisos de configuração inválida (memory_limit, open_basedir, encodings) no error_log, seguidas de workers que encerram com segfault em PHP-FPM ou Apache; requisições multipart ou com progresso de upload de origem única, em rajada; e processos filhos inesperados do usuário do worker web, processo PHP abrindo conexão de saída ou arquivos novos em diretórios gravaveis (web shells). Como a Cloudflare publicou regras de WAF, vale revisar os bloqueios dessas regras a partir de 21/10. Se o ambiente ficou exposto em versão vulnerável desde o vazamento (20/10), trate como suspeito e investigue o host, não só o log HTTP.
No mesmo produto, das mais perigosas para as menos.