Oramix Security Advisory
O PHP corrigiu a 21/10/2026 duas falhas críticas que permitem a um atacante remoto, sem credenciais, executar código no servidor através de pedidos HTTP. A 20/10 o projeto PHP anunciou uma versão de segurança iminente e, a 21/10, os detalhes técnicos e as primeiras provas de conceito já circulavam publicamente. O CERT-EU considera que isto aumenta a probabilidade de já haver exploração, por isso o risco sobe depressa.
Quem está em maior risco
Servidores com Apache mod_php, a única configuração com RCE completo validado por HTTP e que a equipa PHP considera a mais exposta. O FrankenPHP chama o encerramento do pedido incondicionalmente, tal como o mod_php, pelo que a análise de código o indica como provavelmente suscetível a ataques independentes da aplicação, sem exploit validado. O ataque corre antes do código da aplicação, por isso WAF aplicacional, validação de input e boas práticas de código não o impedem.
Todas as instalações PHP que servem pedidos web estão em risco (PHP-FPM, mod_php, php-cgi, FrankenPHP e LiteSpeed). No PHP-FPM e no LSAPI, que modela o FPM, os exploits dependem da aplicação ou da configuração: no FPM há caminhos validados e, no LSAPI, exploits prováveis mas não validados. No CVE-2026-109619 o LSAPI é um candidato condicional, porque pode aplicar valores INI de ambiente cedo; no FrankenPHP não foi estabelecido um consumidor equivalente na configuração por defeito, o que não o torna imune. Nada disto justifica adiar a atualização.
Consequência prática de um comprometimento
O atacante passa a correr comandos como o utilizador do worker PHP. Isso dá acesso ao código da aplicação, a ficheiros de configuração com credenciais (base de dados, chaves de API), aos dados que a aplicação trata e a um ponto de partida para movimento lateral. Esta é a consequência típica de um RCE nesse contexto e não um dado específico do advisory.
Versões
Corrigido em: PHP 8.5.12, 8.4.27, 8.3.36 e 8.2.35. PHP 8.1 e anteriores já não recebem versões oficiais (o descobridor refere impacto desde o 5.4). Algumas distribuições e fornecedores LTS têm backports, e a equipa PHP publicou backports mínimos em código-fonte para o 7.4, 8.0 e 8.1 (CERT-EU). Contactar o fornecedor ou migrar. O 8.2 perde suporte de segurança a 31/12/2026.
| CVE-2026-109618 | CVE-2026-109619 | |
| O que é | Falta de memória (OOM) durante um pedido deixa dados internos do PHP a meio da inicialização. O encerramento do pedido usa-os como se fossem válidos. | Estado global de um pedido fica preso no worker e aponta para memória já libertada. Um pedido seguinte, no mesmo worker, usa-o (use-after-free). |
| Impacto | Execução remota de código sem autenticação, com os privilégios do utilizador do servidor web. | Use-after-free com divulgação de memória e execução remota de código sem autenticação, com os privilégios do utilizador do servidor web. |
| Como é atingido | Pedido HTTP multipart desenhado para esgotar memória (sem Content-Length, muitos cabeçalhos ou campos vazios) sem passar os limites aparentes do PHP. | Dois passos: um pedido provoca um erro fatal ou OOM que deixa estado por repor; outro pedido no mesmo worker consome esse estado antes da inicialização normal. |
| Em mod_php | Exploit completo validado por HTTP com limites por defeito, antes de qualquer código da aplicação correr. Funciona independentemente da aplicação. | Exploit confirmado em PHP 8.5 com fatal_error_backtraces ativo; o progresso de upload de sessão também serve de consumidor. |
| Em PHP-FPM | Suscetível pela análise do código; não há exploit completo demonstrado. | RCE validado também em FPM (ciclo de vida do upload de sessão), mas depende de uma operação adequada da aplicação. Exposição condicional via PHP_VALUE enviado pelo servidor web. |
| Dificuldade | Alta (AC:H). Exige afinar o consumo de memória. | Alta (AC:H). Exige combinar produtor e consumidor. |
Boas práticas e medidas compensatórias (aplicáveis desde já)
Atualizar é a única mitigação completa: não existe mitigação genérica por configuração. Até o patch estar em produção, aplicar em conjunto as medidas dos dois CVE, porque cada advisory remete para o outro.
1. Remediação definitiva
- Atualizar para PHP 8.5.12, 8.4.27, 8.3.36 ou 8.2.35 (ou release posterior do mesmo ramo).
- Reiniciar todos os workers e confirmar a versão realmente em execução.
- PHP 8.1 e anteriores: sem versões oficiais. Contactar o fornecedor ou a distribuição para um backport, usar os backports mínimos em código-fonte publicados pela equipa PHP (7.4, 8.0 e 8.1) ou migrar.
- Pacotes de distribuição: as distribuições e fornecedores LTS receberam os patches antecipadamente, por isso confirmar com o fornecedor. O repositório rpms.remirepo.net não terá atualizações no dia da publicação; a equipa PHP aconselha pacotes da distribuição ou compilação a partir do código-fonte.
- Software de terceiros que embebe PHP: produtos comerciais e open source com PHP como backend podem estar afetados mesmo sem expor uma instalação PHP. O CERT-EU recomenda consultar o repositório NCSC-NL php2shell para os identificar.
- Se não for possível atualizar já: o CERT-EU recomenda considerar isolar as aplicações expostas à internet das redes públicas até a correção ser aplicada e verificada.
- Prioridade por SAPI: Apache mod_php e FrankenPHP primeiro (o ataque do CVE-2026-109618 corre antes do código da aplicação); depois PHP-FPM, php-cgi e LiteSpeed, com as mesmas medidas.
2. CVE-2026-109618 (falta de memória)
- Impor memory_limit=-1 ao nível administrativo (por exemplo php_admin_value no pool FPM) e confirmar que nenhum pool, diretório ou aplicação repõe um limite finito. Remove o limite previsível que torna o exploit controlável. Custo: sem limite por pedido, um pedido abusivo pode consumir a memória do servidor, o que pesa em hosts partilhados.
- Limitar o pedido no frontend (proxy ou servidor web): impor o tamanho decodificado do pedido, o número de campos, de partes multipart, de cabeçalhos e a profundidade de aninhamento, incluindo pedidos sem um Content-Length utilizável.
- Definir post_max_size baixo: 8M para aplicações sem uploads e 32M se forem necessários, mantendo upload_max_filesize abaixo de post_max_size.
- Reduzir max_input_nesting_level e o número de variáveis de input.
- Bloquear multipart no frontend se a aplicação não o utiliza, para que o pedido nunca chegue ao PHP.
- Limite de memória por cgroup (memory.max) apenas como apoio, idealmente um cgroup por worker. Se for global, matar o contentor derruba o master e todos os workers.
- Nunca usar RLIMIT_AS nem RLIMIT_DATA: fazem o mmap() falhar e ativam precisamente o caminho vulnerável.
3. CVE-2026-109619 (estado obsoleto entre pedidos)
- Desativar session.upload_progress.enabled (session.upload_progress.enabled=0) e reiniciar todos os workers. Aplicar em php.ini, no pool FPM ou numa configuração do servidor que atue antes do parsing do pedido; não confiar em ini_set() nem em .user.ini. Está ativo por defeito e não exige session_start(). Bloqueia os caminhos de sessão confirmados, mas não outras variantes.
- PHP 8.5: fatal_error_backtraces=0 e reiniciar todos os workers. Bloqueia apenas o caminho confirmado do backtrace de erros fatais, que é o produtor do RCE demonstrado.
- Eliminar diagnósticos de INI aplicados antes da inicialização: @, error_reporting e display_errors não protegem. Preferir php.ini, pool FPM ou configuração do servidor aplicados no arranque, em vez de overrides por pedido. Verificar PHP_VALUE e PHP_ADMIN_VALUE enviados por nginx ou mod_proxy_fcgi, .htaccess e php_value/php_flag/php_admin_* no Apache, e valores inválidos (memory_limit, date.timezone, zend.assertions, mbstring.*, iconv.*, caminhos rejeitados por open_basedir).
- Eliminar erros fatais alcançáveis por um atacante: parse errors, require falhado, erros não capturados e “Maximum execution time exceeded” em caminhos de upload, importação, páginas de erro, shutdown, destrutores, serialização, output handlers, plugins e callbacks. Eliminar também warnings emitidos durante o cleanup de extensões e do servidor.
- pm.max_requests=1 quebra a ligação entre pedidos no mesmo worker. É caro em desempenho, por isso usar apenas como medida temporária.
4. Auditoria e deteção
- Num ambiente isolado, ativar log_errors=On, um error_log funcional e error_reporting=E_ALL na configuração de arranque.
- Rever os logs do Apache, FPM, proxy e serviços à procura de warnings e deprecations repetidos antes de o script alvo correr, diagnósticos durante o cleanup de extensões, erros fatais, parse errors, uncaught errors e “Maximum execution time exceeded”.
- Limites da auditoria: a ausência de erros nos logs não prova segurança. Os logs históricos podem ter excluído deprecations, só cobrem as rotas exercitadas e uma falha pode ocorrer antes de o PHP escrever a mensagem. Complementar com auditoria estática da configuração e dos fluxos da aplicação.
Nenhuma destas medidas é completa. Servem para reduzir a exposição enquanto a atualização não é aplicada. Precisa de ajuda na correção? Fale com a nossa equipa de cibersegurança.
