
MySQL Community Server 26.7.0 - Alta - SET ROLE ALL EXCEPT residuo FILE - scrittura UID mysqld
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · mysql-set-role-leftover
Classe: Privilegio residuo (FILE come UID di mysqld; non LPE del SO) Raggiungibilità: Remota
MySQL Community Server mysqld 26.7.0 (06a5c1c) - Oracle
SET ROLE ALL EXCEPT rfile (o SET ROLE DEFAULT senza default) svuota la lista dei ruoli attivi, poi checkout_access_maps() ritorna senza set_master_access(user->access). CURRENT_ROLE() è NONE. I bit globali statici che il ruolo aggregava (FILE, PROCESS, SUPER, ...) restano in m_master_access. check_access legge quel residuo. Lab: il FILE residuo scrive INTO OUTFILE come l'UID di mysqld.
SET ROLE NONE è il percorso che ripristina ACL_USER::access. I privilegi dinamici (SYSTEM_USER) decadono. Il residuo a livello di DB è già chiuso (Bug#35386565). Gli account predefiniti non hanno ruoli.
| ID | nessuna CVE al momento |
| Classe | Privilegio residuo (FILE come UID di mysqld; non LPE del SO) |
| Raggiungibilità | Remota (SQL autenticato) |
| CWE | CWE-269 |
| CVSS | Alto: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
| Prodotto | MySQL Community Server mysqld |
| Affetto | 26.7.0 (06a5c1c99c377fc41b2eba1ea244e8b220bdc3c8) |
| Auth | autenticato; alla vittima è stato concesso un ruolo che porta ACL globali statiche (FILE nel lab) |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1. File testimone. Scrittura FILE residua. |
Possiedi un account a cui è stato concesso un ruolo con FILE (o un altro bit globale statico). Fai SET ROLE su quel ruolo, poi SET ROLE ALL EXCEPT su di esso. CURRENT_ROLE() riporta NONE. SELECT 'witness' INTO OUTFILE scrive comunque come l'UID di mysqld sotto secure_file_priv.
Un'applicazione che si isola con SET ROLE ALL EXCEPT dangerous_role o SET ROLE DEFAULT e poi si fida di CURRENT_ROLE() ha ancora quei bit statici. SET ROLE NONE li rimuove davvero.
Il residuo non concede FILE all'account che non l'ha mai posseduto tramite un ruolo. Non riesce a rimuovere FILE dopo la disattivazione.
Stessa caccia alla 26.7.0 dei tre residui lato client. Il daemon predefinito non pubblicato Crit/High era vuoto. ACL / ruoli avevano ancora questo early return a ruolo vuoto.
void Security_context::checkout_access_maps(void) {
if (m_acl_map != nullptr) {
get_global_acl_cache()->return_acl_map(m_acl_map);
m_acl_map = nullptr;
}
if (m_active_roles.size() == 0) return;
// ...
}
activate_role_all (ALL EXCEPT) e activate_role_default vuoto chiamano quel checkout. activate_role_none poi esegue set_master_access(user->access).
Pista sbagliata già registrata: il primo residuo SELECT note FROM lab.t INTO OUTFILE ha restituito 1142 (cache db_acl() 0). Il SELECT 'witness' INTO OUTFILE costante è l'oracolo di FILE.
cd lab
./run.sh
Immagine mysql:26.7.0. Pubblicata su 127.0.0.1:18630. Il ruolo rfile ha FILE. La vittima ha GRANT SELECT ON lab.* e GRANT rfile, file_priv=N, nessun ruolo predefinito. Outfile al login 1227. SET ROLE rfile outfile ok. SET ROLE ALL EXCEPT rfile rende CURRENT_ROLE() NONE; l'outfile residuo scrive /var/lib/mysql-files/MYSQL-SET-ROLE-LEFTOVER-WITNESS. SET ROLE NONE è di nuovo 1227.
SUCCESS mysql-set-role-leftover before-file=denied with-role=yes leftover-role=NONE leftover-file=yes after-none=denied dump=26.7.0 image=mysql:26.7.0 MYSQL-SET-ROLE-LEFTOVER-WITNESS
Quando m_active_roles è vuoto, checkout_access_maps() dovrebbe eseguire set_master_access(user->access) come già fa SET ROLE NONE. Un ALL EXCEPT / DEFAULT vuoto non dovrebbe mantenere la mappa aggregata precedente.
06a5c1c99c377fc41b2eba1ea244e8b220bdc3c8)sql/auth/sql_security_ctx.cc checkout_access_mapssql/auth/roles.cc activate_role_all / activate_role_none