
CVE-2025-4396 - Inyección SQL ciega basada en tiempo en WordPress Relevanssi
Descargo de responsabilidad: Este repositorio está destinado únicamente a pruebas de penetración autorizadas, investigación de seguridad y fines educativos. El acceso no autorizado a sistemas informáticos es ilegal y poco ético.
Un exploit de prueba de concepto para una vulnerabilidad de inyección SQL ciega basada en tiempo en el plugin Relevanssi 4.24.4 de WordPress. Esta implementación está diseñada específicamente para entornos endurecidos donde:
SUBSTR(str, pos, len) e IF(cond, true, false)SLEEP() antes de evaluar la expresión completa, produciendo falsos positivosEn ciertos entornos (p. ej., el laboratorio DVWP), las cargas útiles (payloads) estándar de inyección SQL fallan por dos razones clave:
| Problema | Efecto |
|---|---|
| Eliminación de comas | Rompe SUBSTR(str, pos, len) e IF(cond, true, false) |
SLEEP() codicioso | MySQL ejecuta el sleep antes de la expresión booleana completa, causando falsos positivos |
Ambos problemas requieren soluciones específicas, cubiertas por los enfoques manual y automatizado que se presentan a continuación.
asy.py)Un script asíncrono de Python que permite una extracción quirúrgica carácter por carácter. Evita la sobrecarga de las herramientas automatizadas y omite el filtrado de comas mediante la lógica CASE WHEN.
| Característica | Implementación |
|---|---|
| E/S asíncrona | aiohttp para solicitudes no bloqueantes |
| Payloads sin comas | Sintaxis SUBSTR(str FROM pos FOR len) |
| Lógica no codiciosa | CASE WHEN garantiza que SLEEP() solo se active cuando la condición sea TRUE |
# Comma-less, CASE WHEN-based time-based payload
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 qué CASE WHEN en lugar de IF()?
IF() usa comas y está sujeto a una evaluación codiciosa. CASE WHEN evalúa de forma diferida, asegurando que SLEEP() solo se dispare cuando la condición sea realmente TRUE.
SQLMap puede automatizar el descubrimiento en este entorno utilizando scripts tamper y 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 | Reescribe los payloads en SQL sin comas; reemplaza IF() con CASE WHEN |
--tamper=between | Reemplaza las comparaciones > con BETWEEN para una evasión adicional del WAF |
--technique=T | Restringe únicamente a inyección ciega basada en tiempo |
--no-cast | Evita los envoltorios CAST() que introducen comas prohibidas |
--threads=1 | Garantiza la precisión de los tiempos: las solicitudes concurrentes provocan retardos de sleep superpuestos |
Nota sobre
--threads=1: Esto es esencial para una extracción fiable. El uso de varios hilos provoca que los retardos de sleep se superpongan, corrompiendo la sincronización de la búsqueda binaria y produciendo una salida distorsionada.
| Campo | Valor |
|---|---|
| Objetivo | Tabla wp_users de WordPress |
| Usuario | admin (ID = 1) |
| Hash extraído | REDACTED |
| Algoritmo | phpass (hash de contraseñas estándar de WordPress) |
hashcat -m 400 -a 0 hash.txt /usr/share/wordlists/rockyou.txt
-m 400 apunta a los hashes phpass-a 0 es un ataque de diccionario directo con rockyou.txt