PHP2Shell em ambiente AWS: simular, detectar e corrigir com serviços AWS
Contexto rápido da falha (para este post ser autossuficiente). PHP2Shell é o apelido de divulgação para duas vulnerabilidades críticas e não autenticadas de RCE no interpretador PHP, CVE-2026-109618 e CVE-2026-109619. São bugs de memory safety no motor C, não bugs de aplicação: a 109618 é corrupção de memória disparada quando uma condição de falta de memória (OOM) interrompe o PHP no meio da inicialização e o cleanup opera sobre estado parcial; a 109619 é estado "velho" (stale) / use-after-free exposto através da reutilização de worker (uma requisição posterior atendida pelo mesmo worker longevo usa estado liberado antes da reinicialização). As consequências que guiam tudo abaixo: não há input para "sanitizar", então a única correção completa é atualizar o binário do interpretador e reiniciar os workers; controles de borda (WAF, limites de forma de requisição) apenas estreitam a janela; e a detecção confiável precisa olhar o host (crashes/OOM anômalos, árvore de processo, rede de saída), não assinaturas de URL.
Objetivo
Operacionalizar na AWS os três trabalhos defensivos contra o PHP2Shell:
- Descobrir exposição na frota (quais hosts/imagens/funções rodam PHP afetado).
- Reduzir a janela na borda enquanto o patch não chega (WAF/CloudFront/ALB).
- Corrigir em escala por tipo de compute (EC2, containers, Beanstalk, Lambda, Lightsail) e detectar uso da janela (GuardDuty/CloudWatch/Security Hub).
Tudo sem exploit, estritamente defensivo: descobrir, conter, corrigir, detectar.
Posição oficial da AWS (boletim 2026-143-AWS)
A AWS afirma: "AWS services are not impacted by these issues", mas clientes que rodam versões de PHP afetadas dentro de serviços podem ser impactados. Não havia propagação cross-customer estabelecida até a data.
Fonte: AWS Security Bulletin 2026-143-AWS.
Orientação por serviço (do boletim):
╔════════════════════╦══════════════════════════════════════════════════════════╗
║ Serviço ║ Situação / ação ║
╠════════════════════╬══════════════════════════════════════════════════════════╣
║ Amazon WorkMail ║ AWS aplicou controles e subiu p/ PHP 8.3.36. Sem ação. ║
║ Elastic Beanstalk ║ Novas platform versions p/ PHP 8.2–8.5. Managed Platform ║
║ ║ Updates: chega na próxima janela. Senão: atualizar manual. ║
║ AWS Lambda ║ NÃO há runtime PHP gerenciado. PHP via custom runtime / ║
║ ║ container: atualizar PHP e reimplantar. ║
║ Amazon Linux ║ Pacotes PHP atualizados nas regiões comerciais. ║
║ Amazon Lightsail ║ Blueprints atualizados. NÃO atualiza instância em execução ║
║ ║ no lugar → criar nova instância e migrar. ║
╚════════════════════╩══════════════════════════════════════════════════════════╝
Fonte: AWS Security Bulletin 2026-143-AWS.
Versões afetadas e corrigidas (ranges confirmados pelo boletim):
PHP 8.5: afetado 8.5.0–8.5.11 → corrigido 8.5.12
PHP 8.4: afetado 8.4.0–8.4.26 → corrigido 8.4.27
PHP 8.3: afetado 8.3.0–8.3.35 → corrigido 8.3.36
PHP 8.2: afetado 8.2.0–8.2.34 → corrigido 8.2.35
PHP 5.4–8.1: SEM correção upstream (EOL) → "Migration to a supported branch is required."
Fonte: AWS Security Bulletin 2026-143-AWS.
AWS WAF: o AWS WAF PHP Managed Rule Group está sendo atualizado para as duas CVEs. Clientes na default version são protegidos automaticamente; quem fixou (pinned) uma versão precisa atualizar para receber a proteção. Acompanhe o AWS WAF Managed Rules changelog e assine o tópico SNS de Managed Rules. O boletim reforça: patch é a única correção completa; WAF é controle compensatório.
Fonte: AWS Security Bulletin 2026-143-AWS.
Mapa: os 3 trabalhos e os serviços AWS
┌──────────────────────── BORDA ────────────────────────┐
Internet ──▶ CloudFront ──▶ AWS WAF ──▶ ALB ──▶ PHP em EC2 / ECS / EKS
│ (PHP Managed Rule Group + Size + Rate) │
└── reduz a janela (NÃO corrige) ──────────────┘
│
DESCOBRIR REDUZIR JANELA │ logs DETECTAR USO
───────── ───────────── ▼ ───────────
Inspector (EC2/ECR) AWS WAF (managed+custom) CloudWatch Logs GuardDuty Runtime
SSM Inventory Shield / CloudFront + Logs Insights (processo/rede)
│ (crash/OOM) │
└──────────────┐ └───────┐ │
▼ ▼ ▼
CORRIGIR EM ESCALA: SSM Patch Manager (EC2) · Image Builder/CI (containers) ·
Beanstalk platform update · Lambda redeploy · Lightsail migrar
│ │
└────────▶ Security Hub (agrega achados) ◀──┘
│
▼ EventBridge → SSM Automation / SNS (resposta)
1. Descobrir o que está vulnerável (Amazon Inspector + SSM Inventory)
O Amazon Inspector escaneia EC2, imagens em ECR e funções Lambda, cruzando pacotes com 50+ feeds (NVD, MITRE, advisories de fornecedor), atualizados ao menos 1x/dia. PHP é uma linguagem suportada para EC2 (agentless/VM Scanner) e para ECR.
Fonte: Amazon Inspector — Supported OS and languages.
Dois detalhes que mudam sua estratégia:
- Detecções de pacote de SO em Linux cobrem só o repositório padrão (rpm/dpkg), não incluem aplicações de terceiros, repositórios de suporte estendido nem application streams, salvo exceção documentada. Ou seja: PHP instalado via repositório de terceiros (Remi, PPA ondrej/sury) pode não ser flagrado como pacote de SO.
- Lambda não tem runtime PHP gerenciado; o Inspector não lista PHP entre os runtimes Lambda. PHP em Lambda só existe via custom runtime/container → quem escaneia é o Inspector na imagem em ECR, não o scan de runtime Lambda.
Fonte: Amazon Inspector — Supported OS and languages ; AWS Security Bulletin 2026-143-AWS.
Prático — filtrar achados pelas CVEs:
# Achados do Inspector para as duas CVEs em toda a conta/região
aws inspector2 list-findings \
--filter-criteria '{"vulnerabilityId":[
{"comparison":"EQUALS","value":"CVE-2026-109618"},
{"comparison":"EQUALS","value":"CVE-2026-109619"}]}' \
--query 'findings[].{res:resources[0].id,sev:severity,pkg:packageVulnerabilityDetails.vulnerablePackages[0].name}' \
--output table
Prático — inventário de versão de PHP na frota (SSM Inventory / Run Command):
# Coleta a versão de PHP servida/instalada em instâncias gerenciadas pelo SSM
aws ssm send-command \
--document-name "AWS-RunShellScript" \
--targets '[{"Key":"tag:app","Values":["web-php"]}]' \
--parameters 'commands=["php -v | head -1 || true","(php-fpm -v 2>/dev/null | head -1) || true"]' \
--comment "inventario versao PHP - php2shell"
Recomendação de ferramenta — Amazon Inspector
(a) Faz bem: scan contínuo multi-alvo (EC2/ECR/Lambda) com correlação automática de CVE e integração nativa com Security Hub; já reconhece PHP.
(b) Limita: SO só repo padrão → gap para PHP de repositório de terceiros; exige SSM agent/role para EC2 agent-based; não "corrige", só acha; não enxerga a versão realmente servida por cada pool (ophp -vdo CLI pode diferir do pool do FPM / módulo Apache que atende um site, verifique por pool, veja §3.1).
(c) Alternativa open-source: Trivy ou Grype no pipeline de build e contra imagens/host (cobre pacotes de terceiros melhor em muitos casos);syftpara SBOM.
(d) Para este contexto: em frota AWS existente, Inspector é o de menor atrito para cobertura ampla; adicione Trivy no CI para fechar o gap de PHP de terceiros em imagens.
2. Reduzir a janela na borda (AWS WAF + CloudFront/ALB)
Caminho de menor esforço: garantir o AWS WAF PHP Managed Rule Group na default version (atualizado para as duas CVEs); se você fixou versão, atualize; assine o SNS de Managed Rules.
Fonte: AWS Security Bulletin 2026-143-AWS.
Como complemento, regras custom de forma de requisição (a orientação interina do PHP mapeia para limites que você pode impor na borda: tamanho de requisição decodificada, contagem de campos, número de partes multipart, headers por parte e profundidade de aninhamento): limite de tamanho de corpo, rate-based, e opcionalmente bloqueio/throttle de multipart/form-data. Um estudo público com ALB implementou exatamente isso via CloudFormation (bloqueio de POST multipart por AndStatement método+content-type, rate-based por IP e por JA4, regra de país).
Fonte: Classmethod — AWS WAF rules on ALB after the php2shell advisory.
Limitações honestas desse WAF (do mesmo estudo): a regra de multipart também bloqueia uploads legítimos (apps com formulário de arquivo não podem usá-la); regras rate-based deixam passar requisições antes de bloquear (nos testes, de 23 a 52 POSTs passaram); o autor não verificou proteção efetiva contra o php2shell e reforça que a correção fundamental é atualizar o PHP.
Fonte: Classmethod.
Prático — regra de limite de tamanho de corpo (reduz a janela da 109618/OOM):
{
"Name": "limit-body-size",
"Priority": 10,
"Action": { "Block": {} },
"Statement": {
"SizeConstraintStatement": {
"FieldToMatch": { "Body": { "OversizeHandling": "MATCH" } },
"ComparisonOperator": "GT",
"Size": 1048576,
"TextTransformations": [{ "Priority": 0, "Type": "NONE" }]
}
},
"VisibilityConfig": { "SampledRequestsEnabled": true, "CloudWatchMetricsEnabled": true, "MetricName": "limitBodySize" }
}
Observação: o AWS WAF inspeciona por padrão só os primeiros ~8 KB do corpo (configurável conforme o tipo de associação); por isso
OversizeHandlingimporta e por isso isto é redução de janela, não blindagem.Recomendação de ferramenta — AWS WAF Managed Rule Group
(a) Faz bem: atualizado e operado pela AWS, ativa proteção p/ vetores conhecidos com baixo esforço; integra com CloudFront/ALB/API GW e logging.
(b) Limita: baseado em assinatura/vetores conhecidos, e uma falha de corrupção de memória não autenticada pode ter variações novas; regras custom de multipart/size podem barrar tráfego legítimo; rate-based vaza requisições. Não corrige.
(c) Alternativa open-source: ModSecurity + OWASP CRS (no Nginx/Apache) com os limites de forma de requisição acima (ex.:client_max_body_size, tetos de header/buffer, rejeição de aninhamento inesperado).
(d) Para este contexto: se já está em CloudFront/ALB, habilite o managed group + limite de tamanho de corpo como compra de tempo, com WAF logging para o CloudWatch; trate como ponte até o patch.
3. Corrigir em escala, por tipo de compute
A correção muda conforme onde o PHP roda. A regra que vale para todos: atualizar o binário e reiniciar o que serve (workers longevos continuam com o binário antigo em memória, exatamente o vetor da 109619).
3.1 EC2 — Systems Manager Patch Manager + Run Command
Pacotes PHP atualizados estão disponíveis para Amazon Linux nas regiões comerciais.
Fonte: AWS Security Bulletin 2026-143-AWS.
Fluxo típico com Patch Manager: patch baseline → patch groups por tag → maintenance window (ou on-demand) com operação Scan e depois Install. O restart dos workers você garante com Run Command logo após.
Prático — patch on-demand + restart dos workers:
# 1) instalar atualizações (inclui o PHP do repo padrão) via Patch Manager
aws ssm send-command \
--document-name "AWS-RunPatchBaseline" \
--parameters 'Operation=Install' \
--targets '[{"Key":"tag:app","Values":["web-php"]}]'
# 2) reiniciar os workers para o binário novo entrar em uso
aws ssm send-command \
--document-name "AWS-RunShellScript" \
--targets '[{"Key":"tag:app","Values":["web-php"]}]' \
--parameters 'commands=[
"systemctl restart php*-fpm 2>/dev/null || systemctl restart php-fpm 2>/dev/null || true",
"systemctl restart apache2 2>/dev/null || systemctl restart httpd 2>/dev/null || true",
"php -v | head -1"]'
Cuidado com o gap de repositório: o Inspector e o Patch Manager se apoiam no repositório padrão (rpm/dpkg). PHP instalado via Remi/ondrej/sury pode não ser atualizado por AWS-RunPatchBaseline nem flagrado pelo Inspector como pacote de SO; nesses hosts, atualize pelo mesmo repositório de onde veio o PHP.
Fonte: Amazon Inspector — Supported OS and languages.
3.2 Containers (ECS/EKS) — reconstruir a imagem, não "patchar" o container
Containers não se corrigem em execução. O fluxo é: atualizar o PHP na imagem base → rebuild → push para ECR → Inspector escaneia a imagem → redeploy forçando nova task/pod. Tasks/pods em execução seguem vulneráveis até o redeploy.
Prático — forçar novo deployment no ECS após imagem corrigida:
aws ecs update-service --cluster prod --service web-php --force-new-deployment
Em EKS:
kubectl rollout restart deployment/web-phpapós a nova tag de imagem corrigida ser referenciada. GarantaimagePullPolicyque puxe a tag nova (evite:latestambíguo, fixe digest).
3.3 Elastic Beanstalk — atualizar a platform version
A AWS liberou novas platform versions para PHP 8.2–8.5. Com Managed Platform Updates habilitado, chega na próxima janela de manutenção; senão, atualize a platform version do ambiente manualmente.
Fonte: AWS Security Bulletin 2026-143-AWS.
3.4 Lambda — rebuild + redeploy (não há runtime PHP gerenciado)
Não existe runtime PHP gerenciado. Se você roda PHP via custom runtime (ex.: Bref/camada) ou imagem de container, atualize o PHP e reimplante.
Fonte: AWS Security Bulletin 2026-143-AWS.
3.5 Lightsail — criar nova instância e migrar
Blueprints atualizados em todas as regiões, mas a AWS não atualiza instâncias em execução no lugar → crie nova instância a partir do blueprint atualizado e migre.
Fonte: AWS Security Bulletin 2026-143-AWS.
Recomendação de ferramenta — SSM Patch Manager
(a) Faz bem: patch em escala por tag, agendado em maintenance windows, com relatório de compliance; integra com Run Command para o restart.
(b) Limita: depende do timing do advisory da distro e do repo padrão (gap de PHP de terceiros); não cobre containers nem Lambda; não reinicia workers sozinho.
(c) Alternativa: EC2 Image Builder para gerar AMI dourada já corrigida (substituição imutável), Ansible/config mgmt para hosts com repositório de terceiros, e rebuild no CI para imagens de container.
(d) Para este contexto: EC2 mutável → Patch Manager + Run Command; frota imutável/ASG → Image Builder + rotação de AMI; containers → CI rebuild + ECR + redeploy.
4. Detectar uso da janela (GuardDuty + CloudWatch Logs + Security Hub)
O GuardDuty Runtime Monitoring (EC2, ECS/Fargate, EKS) observa execução de processo e atividade de rede no host/container e gera achados para comportamento suspeito em runtime, sendo o equivalente gerenciado de uma regra de host que alerta quando um worker web (php-fpm, apache2/httpd, lsphp, frankenphp) gera um shell ou abre uma conexão de saída. O GuardDuty usa inteligência de ameaça da AWS; foi o MadPot (honeypot da AWS) que registrou a tentativa de exploração em 17/10/2026, quatro dias antes da divulgação pública.
Nomes exatos de finding types de Runtime Monitoring (ex.: execução suspeita, reverse shell, mineração) mudam e devem ser confirmados na documentação do GuardDuty antes de você escrever automações que dependem do nome do achado. Não cite o nome de memória, valide no console/docs.
Prático — detectar rajada de SIGSEGV/OOM no CloudWatch Logs Insights (envie os logs de php-fpm/Apache via CloudWatch agent):
fields @timestamp, @message
| filter @message like /SIGSEGV|SIGABRT|Segmentation fault|Allowed memory size .* exhausted/
| stats count() as eventos by bin(5m)
| sort eventos desc
Alerte sobre padrão anômalo (clusterização por 5 min), não evento isolado; faça baseline antes, pois muitos crashes/OOMs são legítimos (picos de tráfego, libs pesadas). Como os logs já estão no CloudWatch, você também atende o requisito de encaminhar logs para fora do host (um atacante com permissão adultera log local).
Agregar e responder: mande achados de Inspector + GuardDuty para o Security Hub; dispare resposta com EventBridge → SSM Automation (ex.: isolar instância trocando o security group, snapshot do volume para forense, notificar via SNS). Isso materializa a postura "assuma que a janela esteve aberta": como houve exploração antes da divulgação, após o patch procure .php novos/alterados em web roots e diretórios de upload, cron jobs inesperados e conexões de saída do uid web, agora com telemetria central.
Recomendação de ferramenta — GuardDuty Runtime Monitoring
(a) Faz bem: visibilidade de processo/rede gerenciada, com threat intel da AWS (inclui MadPot), sem você manter regras; integra com Security Hub/EventBridge.
(b) Limita: Runtime Monitoring exige agente (coverage varia por plataforma); achados são de comportamento, não específicos do php2shell; custo por volume.
(c) Alternativa open-source: Falco/Tracee/auditd (uma regra auditd deexecveescopada ao usuário web, mais Falco para a árvore de processo) encaminhando para um SIEM (OpenSearch), com as regras de árvore de processo você mesmo.
(d) Para este contexto: AWS-nativo e pouca equipe → GuardDuty Runtime Monitoring; se já roda Falco no cluster, use-o como segundo sinal e reserve GuardDuty para a camada de conta/rede.
Exemplo prático — runbook AWS end-to-end (em ordem)
Execute em conta/VPC isolada de laboratório antes de rodar em produção (sem IGW, sem dados reais, sem credenciais reais, isole de verdade).
1. DESCOBRIR aws inspector2 list-findings (filtra CVE-2026-109618/619)
+ SSM Run Command inventariando php -v / php-fpm -v por tag
→ lista de hosts/imagens/ambientes afetados, por tipo de compute
2. CONTER WAF: PHP Managed Rule Group na default version (ou atualizar pin)
(borda) + regra limit-body-size (1 MB) + rate-based; WAF logging → CloudWatch
→ reduz janela; NÃO fecha
3. DETECTAR GuardDuty Runtime Monitoring ligado nos alvos
+ Logs Insights alertando SIGSEGV/OOM anômalo
→ você passa a ver tentativa/crash
4. CORRIGIR EC2: Patch Manager Install + Run Command restart workers
ECS/EKS: rebuild imagem → ECR → Inspector → force-new-deployment
Beanstalk: platform update Lambda: redeploy Lightsail: migrar
→ fecha a falha (binário novo + restart)
5. VERIFICAR Inspector re-scan (achado some) + endpoint diag por pool
+ varredura pós-comprometimento → rotacionar segredos se houver IOC
Armadilhas comuns (específicas de AWS)
-
"O Inspector não acusou, logo estou limpo." O scan de SO cobre só o repo padrão; PHP de Remi/ondrej/sury e application streams podem passar batido, e containers/Lambda são cobertos por caminhos diferentes (imagem em ECR, não runtime Lambda). Evite: cruze Inspector com inventário de versão por pool (Run Command) e com Trivy no CI.
-
"Atualizei a AMI / a imagem base." Mas as tasks ECS/pods em execução e os workers FPM longevos seguem com o binário antigo. Reconhecer:
php -vdo host novo diz corrigido, mas o endpoint servido ainda crasha/serve versão velha. Evite: force-new-deployment/rollout restart e restart dos workers (a 109619 vive justamente na reutilização de worker). -
Tratar o WAF Managed Rule Group como a correção. É controle compensatório: assinatura cobre vetor conhecido, a regra de multipart quebra uploads legítimos e a rate-based vaza requisições. A própria AWS diz que patch é a única correção completa. Evite: WAF = ponte; patch + restart = fim.
-
Supor atualização in-place onde não existe. Lightsail não atualiza instância em execução (tem que migrar); Beanstalk precisa de platform version nova; Lambda precisa de redeploy. Evite: trate cada compute pelo seu caminho (seção 3).
Recursos para aprofundar
Fontes primárias AWS:
- AWS Security Bulletin 2026-143-AWS: orientação por serviço, versões afetadas/corrigidas, WAF Managed Rule Group. A referência canônica AWS desta CVE; declara-se em evolução, então volte nela.
- Amazon Inspector — Supported OS and programming languages: confirma PHP suportado em EC2/ECR, ausência de runtime PHP em Lambda, e o limite de "repo padrão".
- AWS WAF Managed Rules changelog + tópico SNS de Managed Rules (citados no boletim): para saber quando a proteção da regra PHP entrou e versioná-la.
Prático / alta autoridade (com limitações declaradas):
- Classmethod — WAF rules on ALB after php2shell: CloudFormation de WAF (multipart/rate/country) com medições e limitações honestas; o autor não comprova proteção e aponta patch como correção fundamental.