php2shell: como LFI, upload e filter chains se tornam RCE em PHP
Guia defensivo sobre php2shell: como LFI, upload inseguro, phar e PHP filter chains se tornam RCE, CVEs reais e ferramentas públicas para validar e corrigir.

Procura as CVE PHP2Shell de outubro de 2026 (CVE-2026-109618 e CVE-2026-109619)? Leia o que fazer já.
Resumo: "php2shell" não é uma ferramenta única, mas uma família de técnicas que transformam uma falha PHP comum — Local/Remote File Inclusion, upload inseguro, desserialização via
phar://, envenenamento de logs e as modernas PHP filter chains — em execução de código (RCE) ou web shell. Este guia é defensivo: explica como detetar, validar com ferramentas públicas e corrigir cada caminho, sem fornecer exploits prontos.
Quase todas as cadeias de compromisso grave em aplicações PHP terminam no mesmo sítio: o atacante consegue que o interpretador execute código seu. O ponto de partida varia — um parâmetro que entra num include, um formulário de carregamento mal validado, uma biblioteca que abre ficheiros com phar:// — mas o destino é sempre a shell. Compreender estas pontes é o primeiro passo para as fechar.
O que significa "php2shell"
O termo descreve a transição de uma primitiva fraca para RCE. Uma leitura arbitrária de ficheiros, por si só, já é grave; mas a preocupação real da equipa de defesa surge quando essa leitura (ou escrita, ou inclusão) pode ser escalada até executar comandos no servidor. Mapear estas transições é precisamente o que fazemos num teste de intrusão a aplicação web.
As pontes mais comuns
- Local File Inclusion (LFI) para RCE. Um parâmetro controlado pelo utilizador que chega a
include/requirepermite incluir ficheiros do servidor. Antigamente exigia um ficheiro "envenenável" (logs, sessões). Hoje, a técnica de PHP filter chain eliminou esse pré-requisito. - Carregamento inseguro. Validação por extensão ou
Content-Type, diretórios de upload executáveis ou nomes previsíveis permitem carregar um.phpe aceder-lhe diretamente. - Desserialização via
phar://. Operações de ficheiro sobre um caminhophar://controlado podem acionar desserialização de metadados e cadeias de gadgets. - Envenenamento de logs/sessões. Injetar PHP num recurso que depois é incluído.
PHP filter chains: porque a LFI ficou mais perigosa
A técnica de filter chain, publicada pela Synacktiv em 2022, foi um ponto de viragem. Encadeando conversões de charset iconv dentro de php://filter, é possível forjar bytes arbitrários em memória a partir de um sink que apenas lê um ficheiro. Na prática: uma LFI antes considerada "só leitura" passou a permitir RCE sem necessidade de upload, sem ficheiro gravável e sem acesso a logs. Para o defensor, a lição é clara: não trate nenhuma inclusão de ficheiros como baixo risco. Fonte: thehacker.recipes — PHP wrappers and streams.
Técnica, CVE de exemplo e como validar
| Técnica | CVE / exemplo | Como validar (ambiente autorizado) | Correção |
|---|---|---|---|
| Upload inseguro para web shell | CVE-2024-11635 (WP File Upload, RCE, CVSS 10) | Tentar enviar ficheiro inesperado e verificar se fica em diretório servido/executável | Allow-list por magic bytes, diretório sem execução, nomes aleatórios |
| Upload não autenticado via REST | CVE-2025-13329 (File Uploader for WooCommerce, CVSS 9.8) | Verificar endpoints REST que recebem ficheiros sem capability/nonce |
Autenticação e autorização no endpoint; validar tipo no servidor |
| Injeção em parâmetro de comando (mailer) | CVE-2016-10033 (PHPMailer < 5.2.18, CVSS 9.8) | Confirmar versão da dependência (composer.lock) |
Atualizar a biblioteca; validar/sanitizar o remetente |
| LFI para RCE (filter chain) | Técnica Synacktiv (classe, não CVE única) | Verificar se parâmetros alcançam include/require com wrappers php:///data:// |
Allow-list de ficheiros incluíveis; nunca concatenar input em include |
Desserialização phar:// |
GHSA phar-stream-wrapper | Mapear chamadas de ficheiro que aceitam caminho controlado | stream_wrapper_unregister('phar') quando não usado |
Ferramentas públicas para validar (uso defensivo)
Use estas ferramentas apenas em sistemas que está autorizado a testar.
synacktiv/php_filter_chain_generator
Script Python que gera cadeias de php://filter para avaliar se um sink de inclusão é explorável. Em contexto defensivo, serve para provar a acessibilidade de um parâmetro suspeito até ao include e priorizar a correção. Repositório: https://github.com/synacktiv/php_filter_chain_generator.
PayloadsAllTheThings (categoria File Inclusion)
Coleção de referência muito reputada com a taxonomia de LFI/RFI e wrappers PHP, útil para montar casos de teste e checklists de revisão. Repositório: https://github.com/swisskyrepo/PayloadsAllTheThings.
projectdiscovery/nuclei
Scanner baseado em templates YAML, com templates públicos para LFI, path traversal e padrões de RCE. Execute nuclei -u https://alvo -tags lfi,rce para triagem rápida e reproduzível em pipeline. Repositório: https://github.com/projectdiscovery/nuclei.
wpscanteam/wpscan
Para o ecossistema WordPress, onde surge a maioria dos CVEs de upload/RCE em plugins. wpscan --url https://alvo --enumerate vp lista plugins vulneráveis conhecidos. Repositório: https://github.com/wpscanteam/wpscan.
sullo/nikto
Scanner de servidor web clássico, útil para encontrar ficheiros expostos, diretórios de upload abertos e configurações por omissão. Repositório: https://github.com/sullo/nikto.
semgrep, Psalm e PHPStan (análise estática)
A validação mais barata é no próprio código. Semgrep (https://github.com/semgrep/semgrep) deteta input que chega a include/system. Psalm (https://github.com/vimeo/psalm) e PHPStan (https://github.com/phpstan/phpstan) rastreiam taint e tipos, sinalizando dados não confiáveis que alcançam sinks perigosos. Corra-os no CI.
O que mudou no PHP 8.x
O PHP 8 reduziu — mas não eliminou — alguns caminhos. A desserialização automática de metadados phar em operações de ficheiro comuns foi removida; o RCE só regressa se o código invocar explicitamente Phar::getMetadata(). allow_url_include mantém-se Off por omissão, dificultando a RFI remota direta. Mas filter chains, uploads inseguros e LFI local continuam plenamente viáveis. Fonte: pentesterlab — PHAR Deserialization.
Lista de correção
- Nunca concatene input em
include/require; use allow-list fixa. - Valide uploads por magic bytes e sirva-os de um diretório sem execução de PHP.
- Mantenha
allow_url_include=Offe remova wrappers não usados. - Corra análise estática no CI e scanners na homologação.
- Atualize dependências e monitorize CVEs dos plugins/bibliotecas que usa.
Validar estas pontes exige método e autorização — é o que separa um teste de intrusão de um scanner automático. Se corre APIs além do app PHP, veja também o nosso guia de teste de intrusão a API e de BOLA/IDOR.
Perguntas frequentes
"php2shell" é um malware?
Não. É um termo guarda-chuva para técnicas que escalam uma falha PHP até à execução de código. O risco é a classe de vulnerabilidade na sua aplicação.
Atualizar para PHP 8 protege-me?
Ajuda em phar e RFI, mas não resolve upload inseguro, LFI local nem filter chains.
Um WAF é suficiente?
Reduz ruído e trava payloads óbvios, mas filter chains e uploads bem construídos passam com frequência. Trate o WAF como camada, não como correção.
Quanto custa validar isto num teste de intrusão?
Depende do tamanho da aplicação e do número de sinks. Veja quanto custa um teste de intrusão.