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
wp2shell — CVE-2026-63030 + CVE-2026-60137 - “wp2shell”: RCE não autenticado no núcleo do WordPress | Kitploit
Ferramentas/GitHubGitHub/0xsha/wp2shell
Quebra de SenhasAnálise de VulnerabilidadesExploraçãoExploração de Aplicações WebTestes de PenetraçãoComando e ControleAprendizado e EducaçãoRed TeamingDesenvolvimento de PayloadsLabs e Prática
GitHub
963037há 2 mesesRevisado pelo Kitploit

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
0xsha/wp2shell

wp2shell

CVE-2026-63030 + CVE-2026-60137 - “wp2shell”: RCE não autenticado no núcleo do WordPress

Ver Repositório

CVE-2026-63030 + CVE-2026-60137 - “wp2shell”: RCE não autenticado no núcleo do WordPress

Confusão de rotas da API REST (CVE-2026-63030) encadeada com uma injeção SQL no WP_Query author__not_in (CVE-2026-60137) → execução remota de código pré-autenticação contra uma instalação padrão do WordPress.

Descoberto por Adam Kues (Assetnote / Searchlight Cyber), divulgado em 2026-07-17. Avisos: GHSA-ff9f-jf42-662q, GHSA-fpp7-x2x2-2mjf.

Encadeamento (RCE não autenticado)WordPress 6.9.0 - 6.9.4 e 7.0.0 - 7.0.1
Apenas SQLi (necessita de um plugin/tema facilitador)6.8.0 - 6.8.5
Não afetados≤ 6.8 para a confusão de lotes; 6.9.5 / 7.0.2 / 7.1-beta2 (corrigido)
Pré-condiçõesAPI REST acessível; sem cache de objeto persistente (Redis/Memcached); ≥1 post publicado
Autenticação necessárianenhuma
Impactonão autenticado → criar um novo administrador → execução de código (a SQLi também extrai o hash do admin)

Demonstração

https://github.com/user-attachments/assets/7f9cc52c-3f31-4339-9192-e31e506684f6

O que este repositório adiciona

  • Uma ferramenta original, apenas com stdlib (wp2shell.py) que unifica o melhor de seis PoCs públicos num único ficheiro, sem dependência requests e sem funcionalidades quebradas.
  • O RCE completo sem quebra de hash, verificado de ponta a ponta em laboratório: shell sem credenciais forja um WP_Post falso através da confusão UNION de um único post, contorna o personalizador para criar um administrador novo (POST /wp/v2/users), faz login e envia um webshell com token. A extração do hash do admin via SQLi (read --preset users) é mantida como um segundo caminho verificado.
  • Um detector de confusão independente de versão (block_cannot_read) usado como verificação primária e não destrutiva.
  • Transporte de produção em cada comando: TLS auto-assinado, cabeçalhos personalizados, User-Agent personalizado, proxy, repetições, atraso de requisição.
  • Um caminho SQLi facilitado verificado para 6.8.x (sqli) que os outros PoCs não têm.
  • Laboratórios Docker reproduzíveis mais uma matriz de confiabilidade por versão/DB, com cada resultado verificado em laboratório.
  • O modo hashcat para o novo hash de senha $wp$2y$ (-m 35500).
wp2shell/
├── README.md              ← você está aqui
├── wp2shell.py            ← o PoC unificado (ficheiro único, apenas stdlib, por 0xsha)
└── lab/                   ← laboratórios Docker reproduzíveis + matriz de confiabilidade
    ├── docker-compose.yml         (laboratório padrão 6.9.4)
    ├── docker-compose.matrix.yml  (parametrizado: qualquer versão × MySQL/MariaDB)
    ├── docker-compose.sqli.yml    (laboratório "Apenas SQLi" 6.8.3)
    ├── matrix.sh                  (executa toda a matriz de confiabilidade)
    └── sqli-only/facilitator.php  (mu-plugin: o sumidouro facilitador 6.8.x)

Os seis PoCs públicos dos quais esta ferramenta se baseia não estão aqui vendidos; eles estão vinculados em Créditos.

Tudo abaixo foi verificado no laboratório Docker local (ver §4; alegações que não foram executadas em laboratório estão assim rotuladas.


1. Detalhes da vulnerabilidade - mergulho profundo no código

O encadeamento solda dois bugs independentes. Os números de linha são do código fonte real do WordPress 6.9.4 (extraído de wordpress:6.9.4-apache).

Bug A - Injeção SQL no author__not_in (CVE-2026-60137)

wp-includes/class-wp-query.php, WP_Query::get_posts():

2403  if ( ! empty( $query_vars['author__not_in'] ) ) {
2404      if ( is_array( $query_vars['author__not_in'] ) ) {                 // ← guarda só dispara para ARRAYS
2405          $query_vars['author__not_in'] = array_unique( array_map( 'absint', $query_vars['author__not_in'] ) );
2406          sort( $query_vars['author__not_in'] );
2407      }
2408      $author__not_in = implode( ',', (array) $query_vars['author__not_in'] );   // ← string passa direto
2409      $where         .= " AND {$wpdb->posts}.post_author NOT IN ($author__not_in) ";  // ← interpolação bruta
2410  } elseif ( ! empty( $query_vars['author__in'] ) ) {
...
2415      $author__in = implode( ',', array_map( 'absint', array_unique( (array) $query_vars['author__in'] ) ) );  // ← absint DENTRO do implode

Uma string author__not_in ignora a guarda is_array() (2404); implode(',', (array)"…") retorna-a inalterada (2408) e é concatenada diretamente no SQL (2409). O irmão author__in (2415) reaplica array_map('absint', …) dentro do implode e está seguro - aquele array_map faltante é o bug. O valor chega como ... post_author NOT IN (<valor>) ..., portanto 0) <sql>-- - fecha a lista e anexa SQL.

Colocar uma string lá é a parte difícil: o endpoint REST de posts mapeia author_exclude → author__not_in (class-wp-rest-posts-controller.php:247) mas declara-o como 'type' => 'array' de inteiros, então o núcleo coage/rejeita uma string:

GET /wp-json/wp/v2/posts?author_exclude=1) OR SLEEP(3)-- -
→ 400 "author_exclude[0] is not of type integer."      (verificado em 6.8.3)

É por isso que o Bug A sozinho é apenas "facilitado". O Bug B introduz a string passando pela validação em 6.9+.

Bug B - Confusão de rotas em lote na REST API (CVE-2026-63030)

wp-includes/rest-api/class-wp-rest-server.php, serve_batch_request_v1():

1720  if ( false === $parsed_url ) {
1721      $requests[] = new WP_Error( 'parse_path_failed', … );   // um caminho inválido torna-se um WP_Error em $requests

1749  foreach ( $requests as $single_request ) {
1750      if ( is_wp_error( $single_request ) ) {
1752          $validation[] = $single_request;     // ← adicionado a $validation …
1753          continue;                            // ← … mas $matches é PULADO
1754      }
1757      $matches[] = $match;                     // ← $matches só cresce para requisições VÁLIDAS

1825  foreach ( $requests as $i => $single_request ) {   // indexado por posição em $requests
1841      $match = $matches[ $i ];                        // ← $matches é MAIS CURTO → +1 deslocamento
1861      $result = $this->respond_to_request( $single_request, $route, $handler, $error );

Uma sub-requisição WP_Error é adicionada a $validation[] (1752) mas não a $matches[] (o continue em 1753 pula 1757), então $matches fica mais curto e $matches[$i] (1841) contém o manipulador da próxima requisição. A requisição i é despachada com o manipulador da requisição i+1, carregando seus próprios parâmetros e seu próprio veredito de validação (que passou).

Origem da regressão (verificado no diff 6.8.3 → 6.9.4): em 6.8.3 o loop adiciona $matches[] = $match para todas as requisições e caminhos inválidos são descartados no primeiro loop - os arrays permanecem alinhados, sem dessincronização. A refatoração em 6.9.0 introduziu o deslocamento. É exatamente por isso que 6.8.x é "apenas SQLi" e a cadeia RCE começa em 6.9.0.

A correção documentada (6.9.5 / 7.0.2)

O patch adiciona $matches[] também para entradas de erro, endurece a reentrância e analisa author__not_in com um auxiliar de lista de IDs. (6.9.5 não estava no Docker Hub na hora do teste, então isso vem dos avisos, não de um diff em laboratório.)


2. Método de exploração

2.1 A dupla confusão de rotas

O esquema de lote só permite sub-requisições POST/PUT/PATCH/DELETE, mas get_items de posts (o sumidouro author_exclude) é apenas GET, então a confusão é aninhada duas vezes:

Baixar ferramenta