# Docker lab per riprodurre CVE-2026-27541, un'escalation di privilegi autenticata in WooCommerce Wholesale Prices. Confronta le build vulnerabili e quelle patchate, include script PoC e analisi della causa principale.

Questo progetto è un laboratorio Docker locale per analizzare e riprodurre il comportamento di CVE-2026-27541 nel plugin WooCommerce Wholesale Prices / Wholesale Suite, confrontando le build vulnerabile e corretta fianco a fianco sulla stessa macchina.
Il problema principale è un Controllo degli Accessi Non Corretto (Broken Access Control) nel seguente endpoint REST API:
/wp-json/wwp/v1/admin/save
In base al codice sorgente utilizzato in questo laboratorio, quella rotta ha già un permission_callback sia nella build vulnerabile che in quella corretta. Tuttavia, la versione interessata utilizza un controllo delle capacità troppo ampio per un'azione di scrittura delle impostazioni admin:
2.2.6) → current_user_can( 'manage_woocommerce' )2.2.7) → current_user_can( 'manage_options' )In questo laboratorio, l'utente shopmgr, che ha il ruolo shop_manager, ha manage_woocommerce=true ma non manage_options. Di conseguenza, questo utente con privilegi bassi può utilizzare una sessione valida di accesso più un X-WP-Nonce valido per invocare l'endpoint di salvataggio delle impostazioni admin sulla build vulnerabile, mentre la build corretta restituisce 403 rest_forbidden per la stessa richiesta.
2.2.6): l'utente shopmgr può chiamare con successo POST /wp-json/wwp/v1/admin/save e modificare le impostazioni del plugin.2.2.7): la stessa richiesta da shopmgr viene respinta con 403.403, il che è coerente con un problema di escalation dei privilegi post-autenticazione.wwp_see_wholesale_prices_replacement_text=PWNED_BY_POC, mentre la build corretta restituisce ancora See wholesale prices.vuln → WordPress + WooCommerce + WooCommerce Wholesale Prices 2.2.6patched → WordPress + WooCommerce + WooCommerce Wholesale Prices 2.2.7db-vuln / db-patched → database MariaDB separatiseed-vuln / seed-patched → job di seeding wp-cli che installano WordPress, installano il plugin, creano utenti e creano un prodotto per i testhttp://localhost:8081 → vulnerabilehttp://localhost:8082 → correttawordpress:6.8.1-php8.2-apachemariadb:11.4.5wordpress:cli-php8.2.
├── docker-compose.yml
├── README.md
├── patched/
│ └── Dockerfile
├── vuln/
│ └── Dockerfile
├── scripts/
│ └── seed-wp.sh
└── poc.py
docker-compose.yml — definisce gli stack vulnerabile e corretto con database separatiscripts/seed-wp.sh — installa WordPress, WooCommerce, il plugin target e crea utenti di test e dati di prodottopoc.py — PoC a impatto minimo per login, estrazione nonce e invocazione dell'endpoint RESTUna volta che lo stack è pronto, lo script di seeding crea quanto segue:
admin / AdminPass!234shopmgr / ShopMgrPass!234lab-product10050WooCommerce: 10.6.0
WooCommerce Wholesale Prices:
2.2.62.2.7Lo script scrive anche lab-secrets.json in ogni container WordPress in modo che i dati preparati e le informazioni sulla versione possano essere verificati.
Questo PoC non tenta di prendere il controllo del sito, cambiare ruoli, installare plugin o eseguire una shell.
Fa solo quanto segue:
shopmgrwpApiSettings.noncewwp_see_wholesale_prices_replacement_text = PWNED_BY_POC
Questa impostazione viene utilizzata come marcatore osservabile per dimostrare che un utente con privilegi bassi può modificare una configurazione riservata agli admin.
POST /wp-json/wwp/v1/admin/saveSebbene l'endpoint richieda una sessione valida e un nonce, la versione vulnerabile consente comunque a un utente con privilegi bassi come shopmgr con il ruolo shop_manager di invocare un endpoint che dovrebbe essere riservato agli admin.
Questa non è una vulnerabilità non autenticata.
Se l'endpoint viene chiamato direttamente senza una sessione di accesso, sia la build vulnerabile che quella corretta respingono la richiesta. Il bug risiede nell'autorizzazione dopo l'autenticazione, non nell'autenticazione stessa.
La versione vulnerabile non manca di un permission_callback. Il difetto è che utilizza un controllo delle capacità troppo ampio (manage_woocommerce) per un'azione REST che scrive impostazioni lato admin.
Dal codice sorgente in includes/class-wwp-admin-settings.php:
POST /wp-json/wwp/v1/admin/savesave_registered_settings()permission_admin_check() come permission_callback2.2.6)if ( ! current_user_can( 'manage_woocommerce' ) ) {
return new WP_Error( 'rest_forbidden', ... );
}
2.2.7)if ( ! current_user_can( 'manage_options' ) ) {
return new WP_Error( 'rest_forbidden', ... );
}
In questo laboratorio, l'utente shopmgr, che ha il ruolo shop_manager, ha manage_woocommerce=true ma non manage_options, quindi supera il controllo vulnerabile ma fallisce quello corretto.
La versione corretta fa più che cambiare la risposta da 200 a 403. Modifica la logica di controllo degli accessi restringendo il requisito di capacità da manage_woocommerce a manage_options.
Inoltre, il percorso di salvataggio nella build corretta è ulteriormente rafforzato passando dal filtraggio basato su prefissi a liste bianche esplicite e a una sanificazione più forte.
Il PoC segue lo stesso flusso di un contesto browser reale:
shopmgrwpApiSettings.noncePOST /wp-json/wwp/v1/admin/savePoiché la build vulnerabile consente agli utenti con manage_woocommerce di invocare questa azione di scrittura delle impostazioni, la richiesta riesce e comporta una modifica persistente dell'opzione.
Un nonce aiuta a proteggere contro il CSRF, ma non è un controllo di autorizzazione.