Web App 7 min de leitura

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.

Também em ENESPT-BR
php2shell: como LFI, upload e filter chains se tornam RCE em PHP

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/require permite 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 .php e aceder-lhe diretamente.
  • Desserialização via phar://. Operações de ficheiro sobre um caminho phar:// 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=Off e 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.