Sobre a OFFCEPT
Construída por operadores que passaram anos a invadir redes antes de criarem uma empresa em torno disso.
Saber Mais
← Voltar
Investigação Técnica18 de julho de 20265 min de leitura

wp2shell (CVE-2026-63030 & CVE-2026-60137): Injeção SQL Não Autenticada no WordPress Core

Escrito por 0xM4L · Investigação de Segurança OFFCEPT

TL;DR

O wp2shell encadeia uma desincronização de validação do batch da REST API com um parâmetro WP_Query sem sanitização, resultando em injeção SQL anónima e não autenticada contra o WordPress Core. Provoca a fuga do nome de utilizador e do hash da password de admin. Chegar a uma shell completa a partir daí exige passos extra, não algo que qualquer dos CVEs conceda diretamente. Atualize para 6.9.5 ou 7.0.2 já.

O wp2shell foi descoberto por Adam Kues na Assetnote, parte da Searchlight Cyber, e reportado através do programa HackerOne do WordPress. Transporta dois CVEs. O CVE-2026-63030 é uma desincronização de validação no endpoint batch da REST API do WordPress. O CVE-2026-60137 é uma injeção SQL no parâmetro author__not_in do WP_Query. Encadeados, um atacante anónimo consegue executar blind SQL injection contra uma instalação WordPress por defeito e extrair dados diretamente da tabela de utilizadores, sem login, sem plugin, sem configuração especial. O investigador de segurança Andy Gill publicou uma análise completa ao nível do código do diff do patch no zsec.uk, que é a base da decomposição técnica abaixo.

O que os dois CVEs fazem realmente

  • CVE-2026-63030, desincronização de validação do batch. O endpoint batch da REST API (/wp-json/batch/v1) constrói arrays paralelos para acompanhar cada subpedido, a rota correspondente e o resultado da sua validação. Um caminho de subpedido malformado falha silenciosamente e só é adicionado a um desses arrays, não ao outro. Todos os subpedidos a seguir ficam emparelhados com o estado de match e validação da rota errada.
  • CVE-2026-60137, author__not_in sem sanitização. Com essa desincronização, um pedido dirigido ao endpoint público de posts pode ser despachado por uma rota cujo schema de parâmetros nunca correu, pelo que o author_exclude chega ao WP_Query como string crua em vez de array de inteiros. O ramo do array passa tudo por absint(). O ramo escalar salta-o completamente e é concatenado diretamente na cláusula SQL NOT IN (...).

O resultado é blind SQL injection, não um dump de dados visível. Não há output de erros nem resultado de query refletido, apenas um canal lateral de timing: envolva a condição injetada em SLEEP() e uma resposta lenta significa que a condição era verdadeira. Chega para extrair dados carácter a carácter, incluindo username:password_hash da tabela de utilizadores, mas são algumas centenas de pedidos por achado, não um único clique.

O registo do CVE chama-lhe remote code execution, e existe um caminho para uma shell: partir offline a password recuperada, autenticar-se normalmente com ela e depois usar a funcionalidade de upload de plugins da própria conta para largar e pedir diretamente um ficheiro PHP. Mas essa segunda metade corre sobre precondições próprias (uma password quebrável, sem MFA, permissões install_plugins, file mods e system() ambos ativados) que nada têm a ver com qualquer dos CVEs. Vale a pena saber, mas os CVEs em si são o motivo do patch, por isso é nisso que este artigo se foca.

Versões afetadas e corrigidas

EstadoVersõesNotas
Não afetado6.8.5 e anterioresConfirmado via diff do patch ao nível do código
Vulnerável6.9.0 – 6.9.4Atualizar para 6.9.5
Vulnerável7.0.0 – 7.0.1Atualizar para 7.0.2
Corrigido6.9.5, 7.0.2, 7.1 Beta 2Alinha os arrays do batch e normaliza o author__not_in no limite SQL

O que fazer agora

Existem PoCs públicos, e a maioria percorre a cadeia completa de ponta a ponta: blind SQLi, recuperação de credenciais, login, upload de plugin. Não espere por relatos confirmados in-the-wild. Se está sem patch e exposto à internet, assuma que já está a ser alvo de scans.

  • Corrija todas as instâncias WordPress que administra. 6.9.x → 6.9.5, 7.0.x → 7.0.2. Os hosts geridos costumam enviar isto automaticamente, mas verifique, e não se esqueça dos microsites e ambientes de staging de cuja existência se esqueceu.
  • Não consegue corrigir de imediato? Bloqueie o acesso anónimo a /wp-json/batch/v1 e ?rest_route=/batch/v1 no WAF como ponte de 24 a 48 horas. Pode partir integrações legítimas (editor de blocos, apps móveis), por isso remova-o no momento em que a versão corrigida estiver implementada.
  • Procure os IOCs específicos. Rajadas de pedidos POST /wp-json/batch/v1 quase idênticos com caminhos http://: malformados e um valor author_exclude contendo SLEEP, CHAR_LENGTH ou SUBSTRING. Um diretório de plugin correspondente a wp-content/plugins/wp2shell-*. Corpos de resposta contendo WP2SHELL_OUT_START. Qualquer destes significa que a cadeia foi além da divulgação de credenciais.
  • Se a sua password de admin alguma vez foi fraca ou reutilizada, rode-a já, tenha ou não encontrado IOCs, e ative o MFA se ainda não o fez. Esse único controlo quebra a cadeia mesmo depois de o SQLi já ter vazado o hash.
  • Considere DISALLOW_FILE_MODS em sites que não precisam de instalar plugins pela UI de administração. Remove uma das precondições de que esta cadeia depende, para este bug e para o próximo que chegue a uma sessão de admin por outro caminho.

Se quer que verifiquemos se o seu parque WordPress foi atingido antes de aplicar o patch, fale connosco.