A 21 de Outubro de 2026, a equipa de segurança do PHP lançou, fora do calendário, as correcções para duas falhas de execução remota de código (RCE) na própria linguagem. A pesquisa que as descobriu dá pelo nome de PHP2Shell, o score oficial é CVSS 4.0 9.2 em ambas, e o impacto não depende de qualquer bug na tua aplicação: qualquer servidor que sirva pedidos HTTP com uma versão afectada do PHP está exposto — inclusive um Hello World. Este guia mostra-te o que as falhas fazem, como confirmar a tua exposição e, sobretudo, como corrigir e vigiar o servidor hoje.

TL;DR — 3 passos:

  1. Confirma a versão e de onde vem o teu PHP: php -v e o changelog do pacote da distro.
  2. Instala 8.2.35, 8.3.36, 8.4.27 ou 8.5.12 — nas distros, o pacote cujo changelog cita o CVE-2026-109618 — e reinicia o PHP-FPM, o Apache e os processos de PHP de longa duração.
  3. Procura sinais de tentativa: erros fatais de memória após pedidos multipart, rajadas de HTTP 500 e segfaults nos workers.

Índice

1. O que é o PHP2Shell

O nome PHP2Shell vem do script de exploração que os investigadores da Wiz Research montaram para provar RCE sem autenticação contra o WordPress, o Drupal e o Joomla mais recentes. O tema, porém, é da linguagem: são duas CVEs no interpretador PHP, causadas por erros de segurança de memória quando o PHP lida com erros fatais — sobretudo o esgotamento de memória (OOM) — durante o processamento de pedidos.

A mecânica essencial: um erro fatal pode deixar estado interno corrompido para trás quando o pedido termina abruptamente. O próximo pedido servido pelo mesmo worker reutiliza esse estado velho como se fosse vivo. Pedidos multipart (formulários e upload de ficheiros) sabem disparar a condição, e a funcionalidade de progresso de upload de sessão — activa por omissão — pode consumir o estado velho mesmo que a aplicação nunca chame session_start().

CVE CVSS 4.0 Bug O que permite
CVE-2026-109618 9.2 Use-after-free no descodificador de progresso de upload RCE pré-autenticação (WordPress/Drupal/Joomla demonstrados) + divulgação de memória do worker sem precisar de RCE
CVE-2026-109619 9.2 Use-after-free no backtrace de erro fatal + confusão de tipos no OPcache Corrupção do estado partilhado do OPcache entre workers e RCE pré-autenticação

Na via da divulgação de memória, o que sai pode ser tudo o que o worker do PHP tem em memória: palavras-passe de base de dados, chaves de API, cookies de sessão, dados de pedidos de outros utilizadores, certificados. Não precisa de execução de código, por isso é mais silenciosa e mais difícil de notar.

A parte mais recente da história: o código vulnerável existia há mais de uma década (o Wiz aponta ao menos até ao PHP 5.4). Tinha sido visto e descartado porque transformar os bugs num exploit real exigia encadear várias falhas e adaptá-las ao mapa de memória de cada versão e aplicação — um esforço que a Wiz diz ser quase proibitivo para humanos, e que os seus modelos fronteira (Wiz Atlas, Gemini 4 Argon, GPT-5.6 Sol) encurtaram para dias. A Calif e a OpenAI Codex Security chegaram às mesmas falhas de forma independente, e a equipa do PHP juntou tudo em duas CVEs.

2. Quem está exposto

Toda a instalação de PHP que sirva pedidos web numa versão afectada — o bug está no interpretador, não na aplicação. O WordPress, o Joomla, o Drupal, o MediaWiki, o Nextcloud, o Moodle, o Magento, o Laravel e o Symfony aparecem na lista, mas qualquer site serve. O que muda de caso para caso é a via de exploração:

Runtime Estado
mod_php (Apache) O mais arriscado — RCE confirmado nas duas CVEs com limites por omissão, podendo disparar antes de qualquer código da aplicação
PHP-FPM RCE pela via da sessão validada e a via OOM vulnerável por análise dos investigadores
FrankenPHP / LiteSpeed Apontado como provavelmente susceptível pelos investigadores
workers de longa duração (Octane, RoadRunner, Swoole, FrankenPHP worker) Tratam-se como web-facing: mantêm memória entre pedidos
CLI / cron / queue workers Não alcançáveis por HTTP em uso normal, mas são actualizados pelo mesmo pacote

ℹ️ Versões: tudo antes de 8.2.35, 8.3.36, 8.4.27 e 8.5.12. O PHP 8.1, 8.0 e 7.x estão no fim de vida e não têm release nova — dependes do pacote da distribuição com suporte estendido (Ubuntu Pro/ESM, Debian LTS, RHEL, CloudLinux) ou de um backport comunitário — confirma a origem antes de o usar.

3. Verificar a versão do PHP

Nota importante antes de actualizar: no Debian, no Ubuntu, no RHEL e no SUSE, os backports de segurança não mudam o número de versão do upstream — um PHP «8.3.6-0ubuntu0.24.04» corrigido fica com o mesmo número. Consulta o changelog do pacote pelo CVE:

# Debian / Ubuntu: número de versão + changelog
php -v
apt list --installed | grep -E '^php8'
zcat /usr/share/doc/php8.3-cli/changelog.Debian.gz | grep -ai -A2 109618

# RHEL / AlmaLinux / Rocky: o changelog do RPM
rpm -q php
rpm -q --changelog php | grep -ai -A2 109618

# Docker/containers: versão no runtime de cada serviço
docker exec meu-wordpress php -v

Se o changelog do pacote mencionar CVE-2026-109618 ou 109619, a tua distro já mandou a correcção — só precisas do restart. Nos hosts partilhados, pergunta à operadora qual build de PHP está activa e confirma que o restart do worker foi feito.

4. Aplicar a correcção

⚠️ Antes de actualizar, assegura o regresso: a actualização do PHP é um patch de segurança dentro da mesma branch, mas convém partir com um plano B pronto. Tira um snapshot da VM (ou clone da imagem do container), faz o dump da base de dados (mysqldump/pg_dump) e copia os ficheiros de configuração do PHP (php.ini, pools do FPM, .htaccess) para fora do servidor. Se o PHP-FPM não arrancar ou a aplicação se recusar a partir, os dados não ficam reféns da correcção — devolves em minutos e não ficas de site em baixo.

No Debian/Ubuntu:

sudo apt update
sudo apt install --only-upgrade php8.3 php8.3-fpm php8.3-cli php8.3-common
sudo systemctl restart php8.3-fpm
sudo systemctl reload apache2    # reinicia os workers do mod_php

No RHEL/AlmaLinux/Rocky (ou o pacote da tua distro, com o nome do teu runtime):

sudo dnf update 'php*'
sudo systemctl restart php-fpm
sudo systemctl reload httpd

Se os sites correm em containers, o princípio é o mesmo: puxa a imagem base com o PHP fixado e recria os containers — actualizar o pacote dentro de um container vivo só toma efeito no reinício:

docker compose pull && docker compose up -d

ℹ️ Reinícios obrigatórios: o pacote fixado não resolve por si — o executável em uso continua em memória. Reinicia tudo que sirva pedidos: PHP-FPM, Apache (mod_php), LiteSpeed, e os workers de longa duração (Octane, RoadRunner, Swoole). É a única correcção completa, sem atalhos de configuração.

Uma mudança de comportamento nas versões corrigidas: o limite de memória reforçado termina o processo de imediato quando é atingido, sem correr as shutdown functions. Testa os caminhos com consumo pesado de memória (exportações grandes, relatórios, backups gerados pelo PHP) depois de actualizar.

5. Se ainda não puderes actualizar

O próprio PHP não publicou nenhuma mitigação completa para estas falhas. Mitigações parciais circulam — desactivar o progresso de upload de sessão (session.upload_progress.enabled = 0) é a mais citada, e há quem desligue o OPcache (opcache.enable = 0) — mas nenhuma substitui o patch: cada uma fecha uma via do problema, não as duas (o upload progress não cobre a via do backtrace, nem a confusão de tipos no OPcache). Até instalares a correcção, o que resta é reduzir a exposição e ganhar tempo:

  1. Retira o PHP da internet directa ou põe-no atrás de controlos de acesso (VPN, allowlists, regras do firewall) enquanto o patch não chega.
  2. Reduz o que um servidor comprometido consegue alcançar: credenciais em memória do worker, acessos a bases de dados, chaves na mesma máquina.
  3. Se o teu PHP estiver num branch EOL (7.4/8.0/8.1), verifica se a tua distribuição (RHEL, Ubuntu Pro/ESM, Debian LTS, CloudLinux) tem o pacote corrigido — o CERT-FR francês recomenda isolar sistemas em PHP sem suporte enquanto a migração não chega.

A Cloudflare, a Akamai e a Imperva publicaram regras WAF de emergência (a Cloudflare até activou por omissão no plano gratuito, horas antes da divulgação pública). Os investigadores, porém, registam payloads a mutar para rodear as regras — considera as regras um stopgap que compra tempo, não a correcção.

6. Saber se tentaram atacar

Não há prova de comprometimento público (os grandes players registam tentativas, não invasões confirmadas), mas convém olhar para os sinais. Não podes confiar só nos logs da aplicação: as falhas correm abaixo dela.

  • Erros fatais de memória (memory_limit) a seguir a pedidos multipart — sobretudo em datas anteriores ao patch.
  • Rajadas de erros HTTP 500 e segfaults nos workers do PHP
  • Cookies PHPSESSID invulgarmente compridos ou percent-encoded nos registos de acesso.

E a procura activa vai além da raiz web: novas ou alteradas cron jobs, unidades systemd/timers/init, utilizadores e chaves SSH novas, mudanças no sudoers, LD_PRELOAD, módulos de kernel, e sobretudo mudanças de configuração PHP: auto_prepend_file / auto_append_file definidos, e disable_functions removido.

⚠️ Se assumires comprometimento: preserva os logs, isola ou reconstrói o host de uma imagem limpa, renova todos os segredos que o PHP podia ver em memória (bases de dados, chaves de API, certificados) e invalida as sessões. A ausência de sinais não prova que estás limpo — trata a divulgação de memória e a execução de código como investigações separadas.

7. Linha temporal

Data (2026) Evento
19-24 Ago Wiz descobre as falhas com modelos de IA e valida RCE contra Drupal/WordPress; reporta à segurança do PHP a 24 de Agosto
Set PHP reconhece e começa o fix coordenado; Calif e OpenAI Codex Security (projecto «Patch the Planet») reportam as mesmas falhas de forma independente
17 Out AWS MadPot detecta uma tentativa de exploração 4 dias antes do patch (telemetria de honeypots)
20 Out Fuga a correr antes da divulgação pública planeada para 22 de Outubro — o exploit aparece no VirusTotal às 02:29 UTC de 21/10 (Recorded Future) e um score errado de 10.0 circula (oficial: 9.2)
21 Out PHP lança 8.2.35/8.3.36/8.4.27/8.5.12 às 14:00 UTC + divulgação pública. Cloudflare e watchTowr registam tentativas de exploração (milhares de tentativas nas 10 horas anteriores ao anúncio). CERTs nacionais e europeus (CERT-EU 2026-018, CERT-FR, NCSC NL) publicam alertas
Estado Nenhum comprometimento confirmado e nenhuma CVE no catálogo KEV da CISA à data — vigia as fontes oficiais

Veredicto

É raro verem-se duas CVEs no núcleo de uma linguagem que serve cerca de 70% da web, mas o que distingue o PHP2Shell não é o número: a falha já estava vista e descartada há mais de uma década, porque transformá-la em exploit era proibitivo — e os modelos de IA derrubaram essa barreira. O mesmo poder, nota a Wiz, serve a defesa: encontra e valida correcções em dias o que levava meses a equipas inteiras. Para o administrador de PME a leitura é directa: o patch está disponível e só ele resolve. Actualiza hoje o PHP de todos os runtimes (mod_php, FPM, containers, workers), reinicia os processos, e usa a lista de sinais acima para vigiar. Se os teus sites estiverem em PHP sem suporte, a migração para 8.4/8.5 deixou de ser opcional — é o teu caminho de saída.

Artigos Relacionados

Fontes Oficiais