
Detector de PoC & validador seguro para a cadeia de vulnerabilidades WP2Shell do WordPress: CVE-2026-63030 (confusão de rota de lote REST) + CVE-2026-60137 (injeção SQL author__not_in). Apenas para testes de segurança autorizados.
Cobertura de CVE: CVE-2026-63030 e CVE-2026-60137 Uso pretendido: Somente testes de segurança autorizados, validação defensiva e laboratórios descartáveis localhost
WP2Shell é uma cadeia de vulnerabilidades do WordPress Core que combina um bug de confusão de rota em lote da REST API pré-autenticação (CVE-2026-63030) com uma primitiva de injeção SQL author__not_in do WP_Query (CVE-2026-60137). Este repositório fornece um scanner de prova de conceito em Python e um validador seguro para que defensores possam identificar instalações afetadas do WordPress, confirmar o comportamento vulnerável em um laboratório isolado e verificar a correção — sem precisar extrair dados ou obter execução de código.
Este projeto identifica instalações do WordPress e valida as duas primitivas de vulnerabilidade associadas à cadeia de vulnerabilidades WP2Shell do WordPress Core:
WP_Query::author__not_in, que pode resultar em injeção SQL quando uma entrada controlada pelo atacante atinge o parâmetro.Quando ambas as condições estão presentes, uma requisição não autenticada pode alcançar a construção SQL vulnerável através do endpoint de lote da REST API do WordPress. Avisos públicos descrevem o impacto combinado como potencialmente levando à execução remota de código.
Este repositório deve ser usado apenas em sistemas que você possui ou está explicitamente autorizado a testar. Prefira um laboratório isolado em Docker ou máquina virtual vinculado a 127.0.0.1.
O arquivo fonte atual contém funcionalidades de alteração de estado, incluindo tentativas de extração de dados do banco de dados, tentativas de escrita de arquivo, fluxos de autenticação, criação de administrador, upload de plugin e execução de comandos.
Versões afetadas do WordPress podem perder o alinhamento entre matrizes internas usadas para rastrear:
Quando um membro de lote malformado é aceito em uma matriz interna mas não em outra, requisições posteriores podem se associar ao manipulador errado. Uma requisição pode, portanto, ser validada como uma rota, mas executada usando o callback de outra rota.
Impacto de segurança:
author__not_inA implementação afetada do WP_Query não normaliza consistentemente author__not_in antes de usá-lo para construir uma condição SQL NOT IN (...).
O parâmetro normalmente espera uma lista de IDs de autor inteiros. Se uma string escalar atingir a construção da consulta vulnerável sem a validação de esquema REST pretendida, uma estrutura SQL insegura pode sobreviver na consulta ao banco de dados.
Impacto de segurança:
O WordPress lançou correções em 17 de julho de 2026 e habilitou atualizações automáticas forçadas para instalações afetadas devido à gravidade.
Unauthenticated client | v WordPress REST batch endpoint | v Malformed batch member creates request/handler misalignment | v Later request is validated against one route but dispatched using another route's handler | v Scalar author_exclude reaches WP_Query as author__not_in | v Unsafe value reaches SQL NOT IN (...) construction | v Blind SQL timing or Boolean oracle | v Potential database compromise | v Potential application-level compromise and RCE
O detector deve parar após confirmar as primitivas de rota-confusão e injeção SQL. Não é necessário extrair dados ou executar comandos para estabelecer que uma instalação afetada é vulnerável.
---
## Fluxo de Trabalho de Detecção
### Fase 1 — Normalizar o alvo
A ferramenta:
1. Adiciona um esquema `http` ou `https` padrão se estiver ausente.
2. Normaliza o caminho de instalação do WordPress.
3. Rejeita esquemas de URL não suportados e credenciais embutidas.
4. Aplica políticas de redirecionamento, proxy, TLS e tempo limite.
### Fase 2 — Identificar WordPress
O scanner verifica:
- referências a `wp-content/`.
- referências a `wp-includes/`.
- metadados do gerador WordPress.
- links de descoberta da API REST.
- estrutura do índice REST do WordPress.
- o namespace `wp/v2`.
- impressões digitais opcionais de feed e `readme.html`.
### Fase 3 — Determinar a versão
Evidências de versão podem vir de:
- metadados do gerador HTML.
- metadados do gerador de feed.
- strings de consulta de ativos principais do WordPress.
- cabeçalhos do gerador HTTP.
- `readme.html`.
- um arquivo local `wp-includes/version.php`.
As evidências são pontuadas e reconciliadas. Indicadores conflitantes de versão remota diminuem a confiança.
### Fase 4 — Verificar exposição de rota batch
O scanner tenta descobrir `/batch/v1` através de:```text
/?rest_route=/
/wp-json/
A rota pode ser tratada usando uma das seguintes:```text /?rest_route=/batch/v1 /wp-json/batch/v1
### Phase 5 — Sonda segura de confusão de rota
A sonda segura contém:
1. Um caminho interno deliberadamente malformado.
2. Uma requisição a um ID de post inválido com um `GET` público aninhado inofensivo.
3. Uma requisição seguinte `/batch/v1`.
Um servidor vulnerável retorna uma resposta externa `207 Multi-Status` na qual a requisição de post inválida é processada como uma requisição batch aninhada.
O detector reporta:```text
route-confusion-observed
quando vê:
parse_path_failed.207.responses aninhado mostrando que a requisição interna inofensiva foi executada.Um validador de SQLi não destrutivo deve enviar requisições emparelhadas que diferem apenas por uma condição Booleana constante:```text False control -> no deliberate database delay True test -> deliberate database delay
O validador deve:
- Aceitar o `207` HTTP externo esperado.
- Analisar tanto os envelopes de lote externo quanto os aninhados.
- Verificar os marcadores de requisição malformada.
- Garantir que a requisição aninhada com SQLi retornou uma resposta válida.
- Coletar múltiplas amostras verdadeiras e falsas.
- Randomizar ou intercalar a ordem das amostras.
- Comparar medianas em vez de uma única requisição.
- Relatar medições insuficientes como `inconclusivo`.
Uma lacuna repetível entre amostras verdadeiras e falsas confirma que a entrada controlada pelo atacante chegou à avaliação SQL. Nenhum conteúdo de banco de dados precisa ser selecionado ou extraído.
---
## Requisitos
- Python 3.9 ou posterior.
- Nenhum pacote Python de terceiros é necessário pelo script fornecido.
- Acesso de rede à instalação autorizada do WordPress.
- Para teste local:
- Um laboratório descartável com WordPress 7.0.1 ou 6.9.4.
- Um contêiner de banco de dados ou banco de dados de teste dedicado.
- O serviço web vinculado a `127.0.0.1`.
- Nenhuma credencial ou dado de produção.
Verifique o Python:```bash
python3 --version
Validação de sintaxe opcional:```bash python3 -m py_compile WP2Shell_CVE-2026-63030_POC.py
---
## Instalação
Renomeie o script fornecido para um nome de arquivo previsível:```bash
mv 'poc(1).py' WP2Shell_CVE-2026-63030_POC.py
chmod +x WP2Shell_CVE-2026-63030_POC.py
Exibir ajuda global:```bash python3 WP2Shell_CVE-2026-63030_POC.py --help
Exibir a versão:```bash
python3 WP2Shell_CVE-2026-63030_POC.py --version
O script define três comandos:```text remote Fingerprint and scan HTTP(S) WordPress targets. local Read the installed WordPress version from a source tree. exploit State-changing proof-of-concept path.
### Status da Build Atual
| Comando | Status |
|---|---|
| `local` | Implementado |
| `remote` | CLI está definido, mas `run_remote()` atualmente é um esboço e retorna um erro |
| `exploit` | Contém funcionalidade de alteração de estado; restrinja a um laboratório local descartável e separe-o da varredura defensiva |
O código atualmente exibe o seguinte para `remote`:
???```text
Remote scanning not fully implemented in this snippet. Use 'local' or 'exploit'.
Restaure uma implementação completa de run_remote() antes de anunciar a varredura remota em massa como funcional.
O comando local lê:```text
/wp-includes/version.php
e extrai `$wp_version`.
## Uso básico```bash
python3 WP2Shell_CVE-2026-63030_POC.py local \
--wordpress-root /var/www/html
python3 WP2Shell_CVE-2026-63030_POC.py local
--wordpress-root /var/www/html
--format json
--output local-result.json
## Instalação do WordPress baseada em Docker
Quando o contêiner do WordPress for nomeado `wordpress`, copie ou monte a árvore de origem para o host, ou execute a verificação de versão dentro do contêiner:```bash
docker compose exec wordpress php -r \
'require "/var/www/html/wp-includes/version.php"; echo $wp_version, PHP_EOL;'
Use o compose.yaml fornecido para executar um laboratório local descartável vinculado a 127.0.0.1:8080:```bash
docker compose up -d
Assim que a configuração inicial do WordPress for concluída no navegador em `http://127.0.0.1:8080`, você pode executar:```bash
python3 WP2Shell_CVE-2026-63030_POC.py remote \
--authorized \
--target http://127.0.0.1:8080 \
--active-probe \
--format json
Para parar e remover o laboratório:```bash docker compose down -v
## Opções de comando local
| Opção | Descrição |
|---|---|
| `--wordpress-root PATH` | Diretório obrigatório contendo `wp-includes/version.php` |
| `-f, --format` | `table`, `json`, `jsonl` ou `csv` |
| `-o, --output FILE` | Escreve o relatório em um arquivo |
| `--fail-on` | Política de código de saída: `never`, `vulnerable` ou `unknown` |
## Exemplo de saída do vulnerable-version```json
[
{
"selected_version": "7.0.1",
"version_assessment": "affected-wp2shell",
"verdict": "CONFIRMED_AFFECTED_VERSION",
"severity": "critical"
}
]
Uma versão local confirma que a versão instalada está dentro da faixa afetada publicada. Isso não demonstra, por si só, explorabilidade em tempo de execução ou o efeito de um patch backportado.
O analisador remote suporta os seguintes argumentos, mas a implementação run_remote() fornecida está atualmente incompleta.
Interface esperada após restaurar run_remote():```bash
python3 WP2Shell_CVE-2026-63030_POC.py remote
--authorized
--target https://wordpress.example
--active-probe
## Múltiplos alvos explícitos```bash
python3 WP2Shell_CVE-2026-63030_POC.py remote \
--authorized \
--target https://site-one.example \
--target https://site-two.example \
--active-probe
Crie targets.txt:```text
https://site-one.example/
https://site-two.example/blog/
Interface esperada:```bash
python3 WP2Shell_CVE-2026-63030_POC.py remote \
--authorized \
--targets-file targets.txt \
--active-probe \
--format jsonl \
--output results.jsonl
cat targets.txt | python3 WP2Shell_CVE-2026-63030_POC.py remote
--authorized
--stdin
## Uso de Proxy```bash
python3 WP2Shell_CVE-2026-63030_POC.py remote \
--authorized \
--target https://wordpress.example \
--active-probe \
--proxy http://127.0.0.1:8081
python3 WP2Shell_CVE-2026-63030_POC.py remote
--authorized
--target https://wordpress.example
--header 'Authorization: Bearer TEST_TOKEN'
## Opções remotas
| Opção | Finalidade |
|---|---|
| `-u, --target URL` | URL alvo; repetível |
| `-l, --targets-file FILE` | Um alvo por linha; repetível |
| `--stdin` | Ler alvos da entrada padrão |
| `--authorized` | Reconhecimento de autorização necessário |
| `--default-scheme` | Esquema aplicado quando omitido |
| `-c, --concurrency` | Workers simultâneos por alvo |
| `--rate` | Taxa agregada de requisições |
| `--timeout` | Tempo limite por requisição |
| `--retries` | Número de tentativas |
| `--max-targets` | Número máximo de alvos aceitos |
| `--max-body-bytes` | Tamanho máximo do corpo da resposta retido |
| `-k, --insecure` | Desabilitar verificação TLS |
| `--no-redirects` | Desabilitar redirecionamentos |
| `--allow-cross-host-redirects` | Permitir redirecionamentos para outro host |
| `--proxy` | Proxy HTTP/HTTPS |
| `-H, --header` | Cabeçalho personalizado; repetível |
| `--user-agent` | Substituir User-Agent |
| `--fingerprint-level` | `quick`, `standard` ou `extended` |
| `--active-probe` | Enviar a sonda segura de confusão de rota |
| `--rest-endpoint` | `query`, `pretty` ou `both` |
| `--include-request-log` | Adicionar metadados de URL, status e tempo |
| `-f, --format` | `table`, `json`, `jsonl` ou `csv` |
| `-o, --output` | Escrever saída em um arquivo |
| `--fail-on` | Política de código de saída |
---
# Validação Segura em Tempo de Execução
Para uma validação local não destrutiva de ambas as primitivas, use um validador dedicado que:
- Recusa hosts que não sejam de loopback.
- Confirma a confusão de rota primeiro.
- Executa amostras de tempo de condição constante somente após a confusão de rota ter sucesso.
- Não extrai dados nem executa comandos.
Exemplo de fluxo de trabalho:```bash
python3 wp2shell_local_validator.py check \
--authorized \
--target http://127.0.0.1:8080 \
--sqli \
--delay 2 \
--samples 4 \
--warmups 2 \
--debug \
--dump-dir evidence \
--output result.json
Padrão de temporização esperado do laboratório vulnerável:```text False controls: approximately 0.03–0.10 seconds True tests: consistently delayed
Veredito esperado:```text
FULL_VULNERABILITY_PRIMITIVES_CONFIRMED
Um teste de temporização pode executar a expressão de atraso mais de uma vez, de modo que um atraso configurado de dois segundos pode produzir um atraso observado próximo a quatro segundos. O sinal importante é a separação repetível entre condições verdadeiras e falsas.
Melhor para uso interativo no terminal:```bash --format table
### JSON
Melhor para evidências e integração:```bash
--format json --output result.json
Melhor para grandes conjuntos de alvos:```bash --format jsonl --output results.jsonl
### CSV
Melhor para planilhas e relatórios:```bash
--format csv --output results.csv
O scanner usa códigos de saída baseados em política.
Uma descoberta de vulnerabilidade pode, portanto, retornar intencionalmente um status diferente de zero.
Exemplo:```bash
python3 WP2Shell_CVE-2026-63030_POC.py local
--wordpress-root /var/www/html
--fail-on vulnerable
echo $?
---
## Teste Diferencial Vulnerável-versus-Corrigido
Uma validação robusta compara dois ambientes limpos.
### Ambiente vulnerável```text
WordPress 7.0.1
Esperado:```text route-confusion-observed repeatable true/false SQL timing difference
### Ambiente fixo```text
WordPress 7.0.2
Esperado:```text route-confusion-not-observed SQLi timing test not reached or no valid timing oracle
Sempre recrie o volume do WordPress ao alterar as versões. Reutilizar um volume pode preservar arquivos principais antigos ou atualizados automaticamente.```bash
docker compose down -v
docker compose pull
docker compose up -d
Atualize imediatamente para uma das versões corrigidas ou uma versão suportada posterior:
Controles temporários devem cobrir ambas as formas de endpoint em lote:```text /wp-json/batch/v1 /?rest_route=/batch/v1
Ações defensivas adicionais:
1. Revise os logs em busca de requisições anônimas em lote, URLs internas malformadas, estruturas de lote aninhadas e valores incomuns de `author_exclude`.
2. Revise contas de administrador, alterações em plugins, arquivos PHP inesperados e acesso ao banco de dados após qualquer período de exposição.
3. Verifique os checksums do WordPress Core e restaure a partir de um backup confiável se houver suspeita de comprometimento.
4. Rotacione segredos e credenciais armazenados no banco de dados do WordPress quando pode ter ocorrido exploração de injeção SQL.
Bloquear o endpoint é uma mitigação temporária, não um substituto para atualizar o WordPress Core.
---
## Ideias de Detecção
Indicadores potenciais incluem:
- Requisições POST anônimas para qualquer um dos formulários de endpoint em lote.
- Respostas HTTP 207 contendo arrays `responses` aninhados.
- URLs internas malformadas no corpo das requisições em lote.
- Objetos `requests` aninhados dentro de outro membro do lote.
- Valores escalares ou com formato SQL em `author_exclude`.
- Requisições pareadas repetidas com respostas alternando entre rápidas e atrasadas.
- Criação inesperada de administrador do WordPress.
- Instalação ou ativação inesperada de plugins.
- Novos arquivos PHP em diretórios graváveis do WordPress.
- Consultas ao banco de dados contendo expressões incomuns de `author__not_in`.
---
## Limitações Conhecidas no Script Fornecido
- O tratamento de cookies não equivale a uma sessão de navegador persistente.
- Prefixos de tabelas do banco de dados são assumidos em alguns caminhos de código.
- O privilégio `FILE` do banco de dados e os caminhos do sistema de arquivos variam conforme a implantação.
- `INTO OUTFILE` normalmente é restrito e não pode sobrescrever arquivos existentes.
- O WordPress pode desabilitar a instalação de plugins através de `DISALLOW_FILE_MODS`.
- Os limites de tempo podem ser afetados por proxies, WAFs, timeouts do PHP, timeouts do banco de dados e carga.
- Strings de versão podem estar ocultas, falsificadas, em cache ou inconsistentes.
- Uma versão afetada observada não prova a ausência de um backport de segurança.
- A ausência de um sinal de tempo não prova que o servidor foi corrigido.
---
## Referências
- Lançamento de Segurança do WordPress 7.0.2:
https://wordpress.org/news/2026/07/wordpress-7-0-2-release/
- Documentação do WordPress 7.0.2 e arquivos alterados:
https://wordpress.org/documentation/wordpress-version/version-7-0-2/
- NVD — CVE-2026-63030:
https://nvd.nist.gov/vuln/detail/CVE-2026-63030
- NVD — CVE-2026-60137:
https://nvd.nist.gov/vuln/detail/CVE-2026-60137
- Arquivo de versões do WordPress:
https://wordpress.org/download/releases/
---
## Uso Legal e Ético
Use este projeto apenas quando:
- Você possui o sistema, ou
- Você tem autorização explícita por escrito, e
- A atividade de teste solicitada está dentro do escopo acordado.
Não exponha instalações do WordPress deliberadamente vulneráveis à Internet pública. Use credenciais descartáveis, dados sintéticos, redes isoladas e snapshots limpos. Destrua ou reinicie o laboratório após o teste.
A prova mais segura de vulnerabilidade é a evidência mínima necessária para demonstrar o problema:```text
Affected version
+
Route-confusion behavior
+
Repeatable constant-condition SQL timing oracle
Roubo de credenciais, persistência, instalação de webshell e execução de comandos são desnecessários para confirmar que a vulnerabilidade existe.
| Ramo do WordPress | Afetado | Versão corrigida |
|---|
| 6.8.x | Apenas CVE-2026-60137: 6.8.0–6.8.5 | 6.8.6 |
| 6.9.x | Ambos os problemas: 6.9.0–6.9.4 | 6.9.5 |
| 7.0.x | Ambos os problemas: 7.0.0–7.0.1 | 7.0.2 |
| 7.1 pré-lançamento | Beta 1 afetado | Beta 2 |
| Anteriores ao 6.8 | Não afetado por esses dois CVEs | N/A |
| Veredito | Significado |
|---|
CONFIRMED_VULNERABLE_BEHAVIOR | Comportamento de confusão de rota em tempo de execução observado |
CONFIRMED_AFFECTED_VERSION | Versão local da fonte está em uma faixa afetada |
LIKELY_VULNERABLE | Evidência de versão remota indica uma versão afetada |
VULNERABLE_SQLI_ONLY | Versão afetada pelo CVE-2026-60137, mas fora da faixa completa de confusão de rota |
AFFECTED_VERSION_BUT_BEHAVIOR_NOT_OBSERVED | Versão afetada detectada, mas comportamento seguro em tempo de execução ausente |
PATCHED_VERSION | Versão atende ao limite de correção publicado |
NOT_AFFECTED | Versão está fora do ramo afetado |
POTENTIALLY_EXPOSED_VERSION_UNKNOWN | WordPress e a rota de lote foram encontrados, mas a versão está oculta |
WORDPRESS_VERSION_UNKNOWN | WordPress detectado sem evidência confiável de versão |
ERROR | O alvo não pôde ser avaliado |
NOT_WORDPRESS_OR_NOT_DETECTED | Nenhuma evidência confiável de WordPress |
| Código | Significado |
|---|
0 | Nenhum resultado que ative a política, ou --fail-on never |
2 | Resultado vulnerável ou afetado sob a política padrão |
3 | Resultado desconhecido ou inconclusivo quando --fail-on unknown é selecionado |
1 | Erro de argumento, entrada ou comando incompleto |