
phpMyAdmin 5.2.3 - Alta - Remota - CSRF - rimozione del token su /sql
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · phpmyadmin-csrf-sql
Classe: CSRF Portata: Remota
phpMyAdmin 5.2.3 (tag RELEASE_5_2_3, commit 962857e). Common.php costruisce la richiesta PSR-7 dalle variabili globali prima di checkTokenRequestParam. In caso di mancata corrispondenza, Sanitize::removeRequestVars cancella $_POST e $_GET ma non quella copia. $sql_query viene poi copiato da $request->getParsedBodyParam('sql_query'). Le POST AJAX si interrompono in caso di mancata corrispondenza del token. Le POST non-AJAX continuano. SqlController preferisce $_POST['sql_query'] ripulito e altrimenti mantiene la variabile globale.
È sufficiente una vittima con il cookie di sessione di phpMyAdmin. Inviare una POST a index.php?route=/sql con sql_query e senza un token valido, e senza ajax_request. La SELECT viene eseguita come quell'utente MySQL. Il valore predefinito CookieSameSite=Strict in 5.2.3 blocca molti browser cross-site. Same-site, Lax, None o HTTP-auth lo colpiscono comunque. In ogni caso si tratta di un controllo CSRF non funzionante.
| ID | nessuna CVE al momento |
| Classe | CSRF |
| Portata | Remota. Il valore predefinito CookieSameSite=Strict blocca molti browser cross-site. Same-site / Lax / None / HTTP-auth rimangono. |
| CWE | CWE-352 |
| CVSS | Alto: 8.1 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N |
| Prodotto | phpMyAdmin |
| Affetto | 5.2.3 tag RELEASE_5_2_3 (962857e) |
| Auth | Cookie di sessione phpMyAdmin della vittima (o HTTP auth). Nessun token CSRF valido. |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1:19240 |
Chiunque possa indurre il browser della vittima a inviare una POST a phpMyAdmin senza ajax_request può eseguire SQL come quell'utente MySQL.
| Privilegio | Metodo / percorso | Provato in lab o dedotto |
|---|---|---|
| Eseguire SQL dell'attaccante come l'account MySQL della vittima (integrità + ricognizione di quel box SQL) | POST index.php?route=/sql sql_query=... db=... senza token, senza ajax_request | Provato in lab. Il corpo dei risultati conteneva PMA-CSRF-SQL-WITNESS. Il general log ha mostrato la SELECT come appuser |
| Interrompere lo stesso handler su AJAX | Stessa POST con ajax_request=1 | Provato in lab. Token mismatch. Riga marcatore INSERT assente. Il general log non ha eseguito quell'INSERT |
Saltare gli handler che leggono solo $_POST ripulito | POST /database/structure/drop-table senza token | Provato in lab. keepme ancora presente |
Stessa lacuna su export (SaveDir), DROP/TRUNCATE di partizione, blocco account, /config/set, creazione pmadb | Qualsiasi handler che legge il corpo PSR-7 dopo la pulizia | Dedotto. Non testato |
Chiuso su questo lab: PMA non autenticato (è prima necessario il login con cookie), route AJAX (escono in caso di mancata corrispondenza), drop-table senza token, shell del sistema operativo. Il valore predefinito Strict SameSite significa che un classico form cross-site spesso non invierà il cookie; il residuo è comunque un controllo CSRF fallito su deploy same-site e Lax/None.
Otto ricerche parallele nel codice di RELEASE_5_2_3. Common.php crea $request = createFromGlobals() prima di checkTokenRequestParam(). In caso di mancata corrispondenza, Sanitize::removeRequestVars() cancella solo $_POST/$_GET. Le non-AJAX continuano. SqlController usa la variabile globale $sql_query se $_POST è vuoto. Route GET|POST /sql.
Vicoli ciechi: considerare AJAX /sql come il residuo (si interrompe con Token mismatch); considerare drop-table come il residuo (quell'handler legge solo $_POST ripulito); considerare il valore predefinito Strict SameSite come "CSRF è chiuso" (il controllo è comunque rotto; same-site / Lax / None rimangono).
python3 phpmyadmin-csrf-sql-Abraxas-Labs.py
oppure
cd lab
./run.sh
Solo loopback: http://127.0.0.1:19240. Immagini phpmyadmin:5.2.3 e mysql:8.0. Progetto Compose phpmyadmin-csrf-sql. Il PoC è una POST loopback same-site (Strict SameSite invia comunque il cookie). Witness PMA-CSRF-SQL-WITNESS.
SUCCESS phpmyadmin-csrf-sql sql-ran=yes ajax-abort=yes drop-held=yes PMA-CSRF-SQL-WITNESS
In caso di mancata corrispondenza, sostituire la richiesta con un corpo vuoto, oppure rifiutare tutte le POST, non solo quelle AJAX. Non copiare sql_query da una richiesta obsoleta. Fallire in modo sicuro come al logout.
962857e)libraries/classes/Common.php snapshot della richiesta prima della pulizia del tokenSanitize::removeRequestVars cancella solo $_POST/$_GETSqlController variabile globale $sql_queryGNU Affero GPL v3.0. Vedi LICENSE. Solo lab loopback. Nessuna garanzia.