Threat Hunting PHP2Shell: Assinaturas Suricata, Regras Falco e Guia Auditd
Threat Hunting PHP2Shell: Assinaturas Suricata, Regras Falco e Guia Auditd
Verificado em 23 de outubro de 2026.
PHP2Shell (CVE-2026-109618 e CVE-2026-109619) deixa quase nenhum rastro em logs de aplicação. As requisições parecem uploads multipart/form-data comuns e o comprometimento ocorre antes da execução do código do usuário. Quem olha apenas para erros de aplicação ou alertas de WAF perderá um ataque. Detecção confiável exige três camadas independentes: rede, runtime e audit de kernel. Este documento fornece regras concretas e prontas para produção e descreve onde estão seus limites.
1. Arquitetura de detecção
Camada 1 (rede): Suricata/Zeek/Corelight detectam body multipart com PHP_SESSION_UPLOAD_PROGRESS e POSTs pequenos repetidos em caminhos sem upload.
Camada 2 (runtime do host): Falco/Tetragon/eBPF detectam filho php-fpm iniciando sh, curl, wget, nc e conexões de saída inesperadas.
Camada 3 (audit de kernel): auditd/eBPF registram execve, connect, openat sob www-data para reconstrução forense.
As camadas não se substituem. Regras de rede podem ser contornadas por codificação, regras de runtime por rootkits de kernel, e o auditd não previne — documenta. É a correlação que produz um quadro confiável.
2. Camada de rede: Suricata
Regra de produção:
alert http any any -> $HOME_NET any (
msg:"PHP2Shell CVE-2026-109618/109619 multipart upload progress probe";
flow:established,to_server;
http.method; content:"POST";
http.content_type; content:"multipart/form-data"; nocase;
file.data; content:"PHP_SESSION_UPLOAD_PROGRESS"; nocase; distance:0;
threshold: type limit, track by_src, count 5, seconds 60;
classtype:attempted-admin;
reference:cve,2026-109618;
reference:cve,2026-109619;
sid:10261092; rev:1;
)
Segunda regra para POST multipart em caminhos que não deveriam aceitar uploads (api, static, assets, health), com threshold de 10 em 60 segundos, sid 10261093.
Deploy:
sudo cp php2shell.rules /etc/suricata/rules/
sudo sed -i 's/^#\\s*-\\s*php2shell.rules/- php2shell.rules/' /etc/suricata/suricata.yaml
sudo suricata -T -c /etc/suricata/suricata.yaml -v
sudo systemctl reload suricata
A regra depende de file.data, ou seja, do stream de arquivo reassemblado. Verifique stream.reassembly.depth. Se muito pequeno, bodies curtos geralmente são detectados, mas nomes de campo fragmentados podem passar. Alguns proxies normalizam http.content_type, outros não. Teste com requisições reais da sua infraestrutura.
Correlação com Zeek: event http_entity_data verifica se PHP_SESSION_UPLOAD_PROGRESS aparece em data de requisições originadas; emite NOTICE. Zeek é especialmente útil para correlação de longo prazo: um único hit é fraco, mas hits repetidos da mesma origem em poucos minutos são sinal forte.
3. Runtime do host: Falco
Workers PHP-FPM normalmente não iniciam shells. Se o fazem, é indício crítico.
Regras:
- PHP-FPM Child Spawns Shell or Downloader: spawned_process, proc.pname em php-fpm*, proc.name em sh/bash/dash/zsh/curl/wget/nc/ncat/socat. Prioridade CRITICAL, tags process, mitre_execution, php2shell.
- PHP-FPM Outbound Connection to Unusual Port: outbound, proc.pname php-fpm*, portas de origem/destino fora de 80/443/3306/6379/5432. Prioridade WARNING.
Deploy: sudo falcoctl artifact install falco-rules; sudo systemctl restart falco; filtrar journalctl por php2shell.
Em Kubernetes, inclua container.name e k8s.ns.name. Para jobs em batch que usam curl legitimamente, exceções estreitas via proc.cmdline. Documente cada exceção com justificativa e data de expiração.
4. Camada de kernel: Auditd
sudo auditctl -a always,exit -F arch=b64 -S execve -F auid=-1 -F euid=33 -k php2shell_exec
sudo auditctl -a always,exit -F arch=b64 -S connect -F euid=33 -k php2shell_net
sudo auditctl -w /tmp -p x -k php2shell_tmp_exec
Regras persistentes em /etc/audit/rules.d/php2shell.rules, carregar com augenrules --load. Investigar com ausearch -k php2shell_exec -ts recent e aureport -k -i --summary.
Auditd é poderoso mas caro. Limite regras aos UIDs e syscalls relevantes e envie logs para SIEM central. Logs locais são frequentemente os primeiros a desaparecer em ataque bem-sucedido.
5. Correlação e fluxo de incidente
Um único sinal não basta. Procure combinação de: (1) pelo menos cinco POSTs multipart com PHP_SESSION_UPLOAD_PROGRESS em 60 segundos; (2) término anormal de workers (SIGSEGV/SIGABRT) imediatamente depois; (3) inícios de processo sh, curl, wget sob www-data; (4) conexões de saída em portas incomuns.
Ordem de resposta: bloquear IP de origem no perímetro e invalidar IDs de sessão; reiniciar workers preservando core dump e snapshot; definir session.upload_progress.enabled = Off até o patch; bloquear egress e rotacionar credenciais; documentar forense e refinar regras.
6. Limiares, falsos positivos e pipeline de logs
O maior desafio prático não é escrever a regra, mas calibrá-la. Um limiar de cinco hits por minuto é sensível demais para blog pequeno e lento demais para portal de alto tráfego. Meça duas semanas em modo observacional e derive o limiar do percentil 99,9 do tráfego normal. Considere distribuição por caminho de destino.
Para o pipeline: as três camadas devem fluir para o mesmo normal de tempo e, idealmente, mesmo SIEM. Suricata fornece flow_id, Falco contexto de processo/container, auditd detalhes de syscall. Correlação comum por IP de origem, janela de tempo e ID de container é muito mais significativa que três dashboards separados. Garanta relógios sincronizados (chrony/NTP).
Teste regras regularmente com requisições inofensivas. Uma regra que nunca disparou pode estar mal configurada. Smoke test mensal protege contra degradação silenciosa.
7. FAQ
Suricata sozinho basta? Não. Nomes de campo codificados e boundaries fragmentados contornam verificações de assinatura. Falco, auditd e o patch são obrigatórios.
Falco não roda em container? Verifique driver eBPF ou módulo de kernel no host e capabilities. Em Kubernetes gerenciado, serviço de segurança de runtime do provedor costuma ser alternativa mais prática.
Auditd gera logs demais? Restrinja a euid=33 e execve, adicione -F success=1. Retenção local de 7 a 14 dias é comum; análise de longo prazo pertence ao SIEM.
Como testar sem risco em produção? Gere em staging requisições multipart inofensivas com o nome do campo e verifique alertas. Depois ajuste limiares ao volume normal.
8. Conclusão
PHP2Shell não deixa rastros óbvios. Apenas a combinação de rede, runtime e kernel, correlacionada no tempo e por origem, produz detecção confiável. E mesmo assim, a detecção é a última linha: o patch e a desativação do callback permanecem as medidas decisivas.
9. Detalhes de tuning do Suricata
Ajustar o Suricata para PHP2Shell exige atenção a três parâmetros. Primeiro, stream.reassembly.depth deve ser grande o suficiente para cobrir bodies pequenos mesmo quando fragmentados em múltiplos pacotes TCP. Valores abaixo de 64 KB podem perder campos em requisições lentas ou em conexões com alto RTT. Segundo, http.request-body-limit e file.data dependem de request-body-minimal-inspect-size; se configurado alto demais, o Suricata pode adiar a inspeção até acumular bytes suficientes, o que atrasa o alerta. Terceiro, o threshold com type limit evita tempestades de alertas, mas pode mascarar ataques lentos (low-and-slow). Para detectar esses, adicione uma regra paralela sem threshold e com prioridade mais baixa, usada apenas para telemetria.
Outro ponto importante é a normalização de HTTP. O Suricata aplica decodificação de chunked transfer encoding e normalização de headers, mas a ordem dos campos e a capitalização da boundary podem variar. Teste suas regras com pelo menos três variantes: boundary curta, boundary longa com caracteres especiais e campo PHP_SESSION_UPLOAD_PROGRESS em caixa mista. Documente quais variantes foram cobertas para evitar falsa sensação de segurança.
10. Integração com SIEM e resposta automatizada
Regras de detecção só geram valor se os alertas chegarem ao lugar certo no tempo certo. Integre Suricata (eve.json), Falco (JSON via gRPC ou syslog) e auditd (ausearch ou plugin audisp) em um SIEM comum, com normalização de timestamps em UTC. Crie correlações explícitas: alerta Suricata + crash de worker em janela de 60 segundos = incidente de alta confiança. Automatize o bloqueio de IP apenas após confirmação (playbook SOAR), para evitar auto-bloqueio por falso positivo. Mantenha runbooks com comandos exatos para isolamento, preservação de evidência e rollback, testados em exercícios trimestrais.
11. Métricas de eficácia
Meça taxa de detecção (quantos ataques simulados geram alerta), tempo médio de detecção (MTTD) e taxa de falsos positivos. Compare com o volume de tráfego normal e com o número de endpoints de upload legítimos. Revise métricas mensalmente e ajuste limiares. Documente mudanças com data e justificativa para manter histórico auditável.