Ir para o conteúdo principal
Github

Vulnerabilidade do PHP CVE-2026-109618

O PHP utiliza longjmp() para tratar erros de falta de memória (OOM, do inglês *out of memory*), saindo do contexto atual e interrompendo o processamento da requisição. Em determinados contextos, a memória da requisição fica temporariamente acessível antes de ser totalmente inicializada. Se alguma alocação falhar nesse momento, o PHP não contabiliza corretamente a saída antecipada e deixa a memória da requisição em um estado inválido. A alocação que falhou não precisa estar relacionada à memória inválida. O procedimento de encerramento da requisição pode, então, ler esse estado ou tomar decisões com base nele. Diferentes estratégias de OOM podem acionar essa condição de forma consistente e levar à execução remota de código (RCE, do inglês *remote code execution*).

Resolução

Versões afetadas Versões corrigidas
< 8.2.35 8.2.35
< 8.3.36 8.3.36
< 8.4.27 8.4.27
< 8.5.12 8.5.12

Vulnerabilidade

Estratégias de OOM

Vários problemas no processamento de dados multipart podem fazer com que uma requisição provoque falta de memória, mesmo permanecendo aparentemente dentro dos limites configurados no PHP:

  • Uma requisição multipart sem um comprimento de conteúdo declarado válido pode passar pela verificação inicial de post_max_size e continuar fornecendo dados do corpo da requisição após a decodificação.
  • Uma parte multipart pode conter um número ilimitado de cabeçalhos. A representação desses cabeçalhos na memória do PHP pode consumir consideravelmente mais memória do que sua representação na transmissão, permitindo que uma requisição dentro do limite de post_max_size esgote o limite normal de memory_limit.
  • Controles de arquivo vazios não são contabilizados em max_file_uploads, mas ainda criam os arrays normais de metadados dos arquivos. Nomes de campos aninhados multiplicam o trabalho necessário para gerar esses arrays.

A falta de memória também pode ocorrer de maneiras específicas da aplicação quando uma entrada controlada por um invasor provoca uma alocação suficientemente grande ou um uso repetido de memória.

Suscetibilidade

O Apache mod_php executa incondicionalmente o procedimento de encerramento da requisição, mesmo quando a inicialização da requisição falha. Durante essa inicialização, o processamento automático do corpo da requisição pode esgotar o limite de memória configurado e encerrar a requisição em um contexto no qual o estado está temporariamente inválido. Em seguida, o procedimento de encerramento processa esse estado inválido. Isso ocorre inteiramente antes do início da execução de qualquer código específico da aplicação.

O FPM encerra o processo filho quando a inicialização da requisição falha. Isso impede o uso do estado inválido e remove o processo filho do conjunto de processos disponíveis (*pool*). Após uma inicialização normal, ainda é possível atingir uma condição de OOM em um contexto que não contabiliza corretamente uma saída antecipada, fazendo com que o estado inválido seja processado durante o encerramento da requisição. Portanto, a análise do código-fonte indica que o FPM também é suscetível, embora ainda não tenha sido demonstrado um exploit completo para essa SAPI.

A análise do código-fonte indica que o FrankenPHP, de forma semelhante ao Apache mod_php, chama incondicionalmente o procedimento de encerramento da requisição, o que sugere suscetibilidade a ataques independentes da aplicação. O LSAPI segue um modelo semelhante ao do FPM, sendo prováveis exploits específicos da aplicação, embora ainda não tenham sido validados.

Mitigação

A correção remove o uso de longjmp() em situações de OOM, evitando uma saída antecipada de contextos que não a contabilizam corretamente. Em seu lugar, é introduzido um mecanismo de OOM suave e controlado, acionado de forma adiada no próximo ponto seguro da máquina virtual (VM). Se o consumo de memória atingir um segundo limite, mais elevado, ocorre imediatamente um OOM severo, utilizando _exit(). Dessa forma, o procedimento de encerramento deixa de encontrar um estado inválido, e a capacidade normal do PHP de limitar o consumo de memória é mantida.

Para instalações que não podem ser atualizadas, a principal medida de mitigação por configuração é definir e impor administrativamente memory_limit=-1. Isso remove o limite previsível de memória por requisição que permite o exploit confirmado com uma condição de OOM controlável. Essa medida não constitui uma mitigação completa. Se mmap() ou outro mecanismo de alocação subjacente falhar, o PHP ainda poderá utilizar longjmp() enquanto partes da memória da requisição, ainda incompletas, estiverem acessíveis. Reinicie todos os processos de trabalho do PHP e confirme que nenhuma configuração de pool, diretório ou aplicação restabelece um limite finito de memória do PHP.

Mantenha post_max_size em um valor conservador e imponha, de forma independente, limites ao tamanho da requisição decodificada no frontend. Reduza max_input_nesting_level e limite a quantidade de variáveis de entrada, partes multipart, cabeçalhos em cada parte e uploads. Mesmo após a aplicação da correção, esses controles reduzem o risco de OOM severo e de negação de serviço, mas não substituem a atualização. Se a aplicação não utiliza dados de formulários multipart, bloqueie essas requisições no frontend antes que cheguem ao PHP.

Um limite de memória de contêiner ou cgroup (memory.max) pode servir como alternativa ao memory_limit do próprio PHP, embora com algumas limitações. Não há garantia de que isso impeça falhas de alocação, portanto não constitui uma mitigação completa. Por exemplo, encerrar um contêiner ou cgroup também pode encerrar o processo mestre e todos os processos de trabalho, a menos que cada processo de trabalho tenha seu próprio grupo. Encerrar um único processo filho do FPM afeta apenas as requisições em andamento desse processo, e o processo mestre do FPM o substitui rapidamente. Não utilize RLIMIT_AS ou RLIMIT_DATA, pois esses limites farão com que mmap() falhe quando o limite de memória for atingido, acionando o caminho vulnerável de longjmp().

Importante: siga também as recomendações de correção do relatório relacionado: CVE-2026-109619.

Impacto e confiabilidade

O impacto confirmado é a execução remota de código sem autenticação, com os privilégios da conta utilizada pelo processo de trabalho do servidor web. A execução remota completa de código foi validada por HTTP contra o mod_php, utilizando os limites padrão de entrada e de memória do PHP e configurações prefork normais com vários processos de trabalho. Processos de trabalho adicionais e tráfego não relacionado podem aumentar o número de tentativas necessárias, mas não eliminam a condição vulnerável. A portabilidade e a confiabilidade do exploit dependem da compilação do PHP, das extensões, do comportamento do frontend e da organização da memória utilizada pelo alocador.