PHP2Shell SaaS: o Risco de Vazamento Entre Clientes no PHP-FPM

Em SaaS multi-tenant, o worker que atendeu um cliente atende o próximo. Veja por que o PHP2Shell ameaça o isolamento e o que fazer.

por Cleverson Gouvêa

Diagrama de php2shell saas: um worker PHP-FPM compartilhado entre vários clientes de uma plataforma multi-tenant

O PHP2Shell SaaS é o cenário mais delicado desta crise do PHP: quando um único pool PHP-FPM atende todos os seus clientes, um use-after-free entre requisições no mesmo worker deixa de ser só "um servidor invadido" e vira risco de um cliente enxergar dados de outro. Neste guia eu explico o mecanismo sem jargão, mostro o que o time de produto precisa decidir esta semana e onde as mitigações enganam.

TL;DR

  • PHP2Shell é o apelido de duas falhas críticas do PHP: CVE-2026-109618 (RCE por corrupção em falta de memória) e CVE-2026-109619 (RCE por estado global obsoleto, um use-after-free entre requisições). As duas têm CVSS 4.0 de 9.2 e não exigem login.
  • A correção saiu em 21/10/2026: PHP 8.5.12, 8.4.27, 8.3.36 e 8.2.35. Do 7.4 ao 8.1 só existem backports mínimos de código-fonte; do 5.4 ao 7.3 não há correção do projeto PHP.
  • Em SaaS multi-tenant, o worker que atendeu o cliente A atende o cliente B logo depois. É por isso que o risco do PHP2Shell SaaS é maior do que o de um site institucional.
  • memory_limit=-1, session.upload_progress.enabled=0 e fatal_error_backtraces=0 reduzem a exposição, mas o próprio php.net diz que não tornam a instalação segura. Só atualizar resolve.
  • Depois de atualizar, reinicie todos os processos PHP de longa duração (filas, Horizon, Octane, Messenger) e trate 17/10 como o início da janela de investigação.

O que é o PHP2Shell e por que o PHP2Shell SaaS virou urgência

PHP2Shell é a cadeia de exploração que junta duas vulnerabilidades no núcleo do PHP. Segundo o comunicado oficial do php.net, a primeira (CVE-2026-109618) acontece quando o tratamento de falta de memória interrompe o PHP com dados internos da requisição ainda pela metade, e a limpeza da requisição trata esse lixo como válido. A segunda (CVE-2026-109619) é a que define o risco do PHP2Shell SaaS: um estado interno que pertence a uma requisição sobrevive depois que a memória por trás dele foi liberada, e uma requisição seguinte atendida pelo mesmo worker pode usar esse estado obsoleto antes de a inicialização normal zerá-lo.

O calendário foi atropelado. Os identificadores das CVEs vazaram em 20/10/2026, e o PHP antecipou a release para 21/10, segundo o FAQ da Tenable. Pior: a Amazon Threat Intelligence registrou uma tentativa de exploração na rede de honeypots MadPot em 17/10, quatro dias antes da divulgação pública. A recomendação da própria Amazon é começar qualquer investigação a partir dessa data.

O tamanho do problema

  • A Palo Alto Networks identificou mais de 22,6 milhões de instâncias expostas potencialmente vulneráveis (TechTarget).
  • O php.net lista como afetada toda instalação PHP que serve requisições web: PHP-FPM, Apache com mod_php, php-cgi, FrankenPHP e LiteSpeed. O risco mais alto é o do mod_php, onde há exploit demonstrado que dispara antes de qualquer código da aplicação rodar.
  • O Datadog Security Labs reproduziu a corrupção por falta de memória no PHP 8.5.11 com um único POST sem autenticação, contra um script que só imprimia uma resposta.

Esse último ponto derruba o argumento mais comum que eu ouço sobre o PHP2Shell SaaS: "nossa aplicação valida tudo". A validação do Laravel ou do Symfony nem chega a rodar. O parsing do corpo multipart/form-data acontece no motor do PHP, antes do seu index.php.

Por que o PHP2Shell SaaS é pior do que um site comum

Em um site institucional, o worker PHP-FPM atende visitantes de uma única empresa. Em um SaaS multi-tenant, o mesmo pool atende todos os clientes, e cada worker processa em sequência requisições de tenants diferentes: o financeiro da empresa A, o login da empresa B, o webhook de pagamento da empresa C.

É aqui que o desenho do CVE-2026-109619 pesa. A falha é, por definição, entre requisições no mesmo worker. A Tenable registra que o PHP lista vazamento de memória como impacto confirmado dessa CVE. E a Sansec documentou que a cadeia PHP2Shell consegue devolver ao atacante pedaços da memória do worker em um cookie PHPSESSID, incluindo senhas, tokens de sessão, chaves de API e até chaves privadas TLS.

Até 24/10, nenhuma das fontes publicou um caso de vazamento entre tenants de um SaaS. Mas o raciocínio de quem opera é direto: se a memória do worker pode vazar, o que estava na memória daquele worker é o que os seus outros clientes acabaram de fazer. No PHP2Shell SaaS, o isolamento lógico que você construiu no banco (o tenant_id em todo WHERE, os global scopes do Eloquent, os voters do Symfony) não protege nada, porque o ataque acontece abaixo da aplicação.

O que fica na memória de um worker multi-tenant

Em poucos segundos, um worker de um PHP2Shell SaaS típico processa:

  • Credenciais de integração de cada tenant: token da API oficial do WhatsApp, chave do gateway de pagamento, credenciais SMTP.
  • Dados pessoais recém-lidos do banco: CPF, endereço, histórico de compras, notas de aluno.
  • Segredos da plataforma: APP_KEY do Laravel, APP_SECRET do Symfony, senha do banco, chaves de criptografia de campos.
  • Tokens de sessão de usuários logados de vários clientes ao mesmo tempo.

Com RCE (execução remota de código), o atacante lê o .env e tem a plataforma inteira. No PHP2Shell SaaS, um worker comprometido tem impacto multiplicado pelo número de clientes.

A linha do tempo do PHP2Shell SaaS que o time de produto precisa conhecer

Data Fato Fonte
17/10/2026 Primeira tentativa de exploração vista nos honeypots da Amazon Tenable / Amazon
20/10/2026 Identificadores das CVEs vazam; PHP publica aviso prévio php.net / Tenable
21/10/2026 Release 8.5.12, 8.4.27, 8.3.36 e 8.2.35; Cloudflare relata ataques às 07:43 UTC, antes do patch das 14:00 UTC php.net / Sansec
21/10/2026 Backports mínimos de código-fonte para 7.4, 8.0 e 8.1 php.net
23/10/2026 Alerta da CVE-2026-115560 (upload progress + serialize handler) php.net
31/12/2026 Fim de vida do PHP 8.2 php.net

Houve exploração antes da correção existir, então "atualizamos no dia 22" não encerra o assunto: a janela desde 17/10 precisa ser investigada. E o 8.2 morre em dois meses; quem instala o 8.2.35 agora já deveria agendar a migração.

Sobre a CVE-2026-115560: o php.net chama o vetor de improvável. Ele exige que a aplicação troque o session.serialize_handler para php com ini_set() antes do session_start(), com upload progress ligado. A correção vem na próxima release regular. Se você desligou o upload progress no dia 21, nada muda.

Mitigações para o PHP2Shell SaaS: o que ajuda, o que engana

Enquanto o pacote corrigido não chega ao repositório, as mitigações compram tempo, não segurança. O php.net é explícito: elas "reduzem a exposição a caminhos específicos de ataque, mas não tornam uma instalação segura".

Mitigação O que bloqueia O que não bloqueia Efeito colateral
memory_limit=-1 via php_admin_value A falha controlável de limite de memória (109618) Falhas de alocação de baixo nível, que ainda chegam ao caminho vulnerável Uma requisição pode consumir a RAM do servidor inteiro
session.upload_progress.enabled=0 Os caminhos de sessão confirmados (109619) e o vetor da 115560 Outras variantes da 109619 Some a barra de progresso nativa de upload
fatal_error_backtraces=0 (só PHP 8.5) O caminho confirmado via backtrace de erro fatal Qualquer outro caminho Diagnóstico de erro fatal mais pobre
post_max_size baixo (8M sem upload, 32M com upload) Reduz a superfície de requisições gigantes Não fecha nenhuma das CVEs Uploads grandes quebram
WAF da Cloudflare Vetores conhecidos, se o tráfego passa pela Cloudflare Tráfego direto à origem, variantes novas Falsos positivos em upload

As armadilhas mais comuns

  • Configurar no lugar errado. O php.net manda aplicar no php.ini, no pool do FPM ou na configuração do servidor, algo que vale antes do parsing da requisição. ini_set() no bootstrap do Laravel e .user.ini não servem.
  • Esquecer um pool. Todo PHP2Shell SaaS costuma ter mais de um: o do app, o do painel admin, o da API pública. Cada um precisa da configuração.
  • Não reiniciar os workers. Configuração nova em worker velho é configuração nenhuma.
  • Deixar memory_limit=-1 para sempre. A própria Sansec alerta que isso permite que uma requisição esgote a memória do servidor. Em multi-tenant, um tenant derruba todos. Use limite de cgroup ou de container como guarda (sem RLIMIT_AS, que o php.net desaconselha) e volte o limite depois do patch.
  • Achar que esconder erros ajuda. error_reporting, display_errors ou @ não mudam nada.

O checklist PHP2Shell SaaS para esta semana

A ordem importa. Esta é a sequência que sigo quando assumo um ambiente PHP2Shell SaaS em incidente:

  1. Inventário real. ls /etc/php e php-fpm8.x -v em cada servidor, contêiner e imagem base. Inclua o PHP que ninguém usa: o guia do Laravel Forge manda atualizar todas as versões instaladas, inclusive as ociosas.
  2. Atualizar para 8.5.12, 8.4.27, 8.3.36 ou 8.2.35. Em imagens Docker, isso significa rebuild da imagem base e redeploy, não apt upgrade dentro do contêiner rodando.
  3. Conferir a revisão do pacote nos ramos antigos. Em 8.1 ou anterior, o número da versão não muda depois do backport; o Forge orienta checar a revisão com dpkg -l. Atenção: as automações de segurança do Forge não atualizam o PHP.
  4. Reiniciar tudo que é PHP de longa duração. php artisan queue:restart, horizon:terminate, octane:reload, workers do Symfony Messenger, supervisord. Esses processos continuam com o binário antigo até morrerem.
  5. Investigar a janela a partir de 17/10. Procure POSTs multipart/form-data anômalos, workers que morreram por falta de memória, arquivos PHP novos em diretórios de upload e processos filhos estranhos do FPM.
  6. Rotacionar segredos se houver qualquer indício. APP_KEY, senhas de banco, tokens de API de cada tenant, chaves de webhook. Em SaaS, isso exige coordenação com clientes, porque parte das credenciais é deles.
  7. Decidir sobre LGPD. Se houver indício de acesso a dados pessoais, a comunicação à ANPD e aos titulares tem prazo. Deixo o roteiro no plano de resposta a vazamento de dados.

Quando NÃO fazer

  • Não aplique só a mitigação e feche o chamado. Ela é ponte, não destino.
  • Não suba direto para uma versão maior (8.2 para 8.5) em plena crise só para "aproveitar". Atualize o patch do ramo atual hoje; migre de ramo com testes, em sprint própria.
  • Não rotacione o APP_KEY do Laravel às cegas. Ele quebra sessões e dados cifrados com Crypt; planeje a recriptografia.

Isolamento entre clientes: a decisão de arquitetura que o PHP2Shell SaaS força

Atualizar fecha estas CVEs. A pergunta de produto que o PHP2Shell SaaS deixa é outra: quanto custa o próximo bug de memória do PHP na sua plataforma? Porque haverá outro. O CVE-2024-4577 e o CVE-2019-11043, ambos do PHP, estão no catálogo KEV da CISA.

Existem três desenhos possíveis:

Modelo Isolamento de memória entre clientes Custo operacional Para quem faz sentido
Um pool FPM para todos Nenhum Baixo Plataforma pequena, dados pouco sensíveis
Pools por faixa de cliente (ex.: enterprise isolado) Parcial, por grupo Médio SaaS B2B com contratos que exigem segregação
Pool, usuário Linux e contêiner por tenant Forte Alto Saúde, jurídico, educação com dados de menores

O meio-termo costuma ser o mais racional: clientes grandes ou com dados sensíveis ganham pool, usuário de sistema, open_basedir e segredos próprios; o resto compartilha. Assim, um worker comprometido não lê a memória nem os arquivos do vizinho.

O que o time de produto precisa colocar no roadmap

  • Segredos por tenant fora do .env global, num cofre, carregados sob demanda.
  • Recriação periódica de workers (pm.max_requests) para encurtar a vida útil de qualquer estado contaminado. É higiene, não correção.
  • Imagem base com dono, revisada a cada release de segurança do PHP.
  • Plano de saída do PHP 8.2 antes de 31/12/2026.

Se você avalia manter essa infraestrutura internamente, o raciocínio que uso com clientes está em sistema próprio ou SaaS: como decidir. E a base do servidor, que reduz o estrago quando o PHP falha, está no checklist de hardening de servidor Linux.

Quanto custa ignorar o PHP2Shell SaaS, e quanto custa resolver

Corrigir é barato: num servidor com repositório de pacotes saudável, atualizar o PHP e reiniciar workers leva minutos. O que encarece é o entorno:

  • Ambientes sem dono. Imagem de dois anos atrás, servidor que ninguém sabe quem configurou. O patch vira projeto.
  • PHP fora de suporte. Em 7.x, o backport é paliativo; migrar envolve dependências, testes e reescrita de trechos.
  • Investigação forense. Revisar logs, rotacionar credenciais de dezenas de tenants e avisar clientes consome dias de time sênior.

Do outro lado está o pior cenário do PHP2Shell SaaS: um incidente que atinge todos os seus clientes ao mesmo tempo, com comunicação à ANPD, quebra de contrato e churn. Isso não é custo de TI. É risco de continuidade do negócio.

Como a Agathas Web resolve isso

Trabalho com PHP desde 2008, e boa parte do que a Agathas Web opera roda nele: plataformas Moodle de instituições de ensino, sistemas em Laravel, hospedagem gerenciada e integrações com a API oficial do WhatsApp, onde o token de cada cliente é exatamente o segredo que não pode vazar. Esse dia a dia vai para o seu produto no serviço de desenvolvimento de sistemas sob medida.

Para um cliente com risco de PHP2Shell SaaS, o trabalho é dividido em duas frentes:

Resposta imediata (dias):

  • Inventário de todas as versões de PHP, pools, contêineres e workers de longa duração.
  • Atualização para a release corrigida do seu ramo, com rebuild de imagens e reinício controlado.
  • Aplicação correta das mitigações onde o patch ainda não for possível, com prazo para removê-las.
  • Revisão de logs a partir de 17/10 e recomendação objetiva sobre rotação de segredos.

Correção estrutural (semanas):

  • Desenho de isolamento por tenant ou por faixa de cliente, com pools e usuários de sistema separados.
  • Retirada de segredos do .env global e organização por tenant.
  • Plano de migração do PHP 8.2 ou de versões 7.x/8.0/8.1 para um ramo suportado, com testes automatizados.
  • Rotina de atualização de segurança documentada, para a próxima CVE não depender de alguém lembrar.

Funciona assim: você entra em contato, fazemos um diagnóstico PHP2Shell SaaS do ambiente com acesso de leitura e entregamos plano com escopo, prazo e preço fechados antes de mexer em produção. Se precisa de um time que mantenha o produto depois, isso cabe na nossa frente de desenvolvimento e sustentação.

Conclusão: atualize hoje, redesenhe o isolamento em seguida

O PHP2Shell SaaS expõe o que o multi-tenant costuma esconder: isolamento que mora só no código da aplicação não sobrevive a um bug no motor por baixo dela. A correção está disponível. O que define se o próximo incidente será um dia tranquilo ou uma semana de crise é a arquitetura que você decide agora.

Atualize para 8.5.12, 8.4.27, 8.3.36 ou 8.2.35, reinicie todos os workers, investigue desde 17/10 e coloque o isolamento por tenant no roadmap. Se quiser que a gente faça esse diagnóstico com você, fale com a equipe de desenvolvimento da Agathas Web.

Perguntas frequentes

O PHP2Shell afeta aplicações Laravel e Symfony mesmo com o framework atualizado?

Sim. As duas CVEs estão no núcleo do PHP, não no framework. O php.net informa que toda instalação que serve requisições web está em risco, e o Datadog reproduziu a falha contra um script que só imprimia uma resposta. O parsing da requisição acontece antes do código do Laravel ou do Symfony rodar, então atualizar o framework não ajuda. A correção é atualizar o PHP para 8.5.12, 8.4.27, 8.3.36 ou 8.2.35 e reiniciar todos os workers, inclusive filas, Horizon, Octane e Symfony Messenger.

Desligar session.upload_progress e usar memory_limit=-1 resolve o PHP2Shell?

Não. O próprio php.net diz que essas medidas reduzem a exposição a caminhos específicos, mas não tornam a instalação segura. session.upload_progress.enabled=0 bloqueia os caminhos de sessão confirmados, mas não outras variantes da CVE-2026-109619. memory_limit=-1 elimina a falha controlável de limite de memória, mas uma falha de alocação de baixo nível ainda chega ao código vulnerável, e ainda permite que uma requisição esgote a RAM do servidor. Use as mitigações só como ponte até a atualização.

Por que o risco do PHP2Shell é maior em SaaS multi-tenant?

Porque a CVE-2026-109619 é um use-after-free entre requisições no mesmo worker, e em SaaS multi-tenant o mesmo pool PHP-FPM atende todos os clientes. O PHP lista vazamento de memória como impacto confirmado, e a Sansec documentou vazamento de senhas, tokens e chaves de API da memória do worker. Até 24/10/2026 não havia caso público de vazamento entre tenants, mas a memória de um worker compartilhado contém dados de vários clientes, e uma execução remota de código dá acesso ao .env da plataforma inteira.

Estou no PHP 7.4 ou 8.1. Existe correção para o PHP2Shell?

Não há release oficial. O projeto PHP publicou backports mínimos de código-fonte para 7.4, 8.0 e 8.1, e algumas distribuições e fornecedores de suporte estendido empacotaram essas correções. Nesses casos, o número da versão não muda, então é preciso conferir a revisão do pacote. Do PHP 5.4 ao 7.3 não há correção do projeto PHP. A CISA recomenda tirar do ar sistemas em 8.1 ou anterior que não possam ser atualizados. O caminho seguro é migrar para um ramo suportado.

O que é a CVE-2026-115560 e preciso de patch emergencial?

É um alerta publicado pelo php.net em 23/10/2026 sobre session upload progress combinado com o serialize handler de sessão. O vetor é classificado como improvável: exige que a aplicação troque o session.serialize_handler para php em tempo de execução com ini_set() antes de session_start(), com upload progress ligado. A correção vem na próxima release regular. A recomendação é manter session.upload_progress.enabled=0 até lá; quem já aplicou essa configuração no dia 21 não precisa fazer mais nada.