
MySQL Community Server 26.7.0 - Alta - SET ROLE ALL EXCEPT FILE residual - escritura de UID de mysqld
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · mysql-set-role-leftover
Clase: Privilegio residual (FILE como UID de mysqld; no es LPE del SO) Alcance: Remoto
MySQL Community Server mysqld 26.7.0 (06a5c1c) - Oracle
SET ROLE ALL EXCEPT rfile (o SET ROLE DEFAULT sin roles predeterminados) limpia la lista de roles activos, luego checkout_access_maps() retorna sin set_master_access(user->access). CURRENT_ROLE() es NONE. Los bits globales estáticos que el rol agregaba (FILE, PROCESS, SUPER, ...) permanecen en m_master_access. check_access lee ese residuo. Laboratorio: el FILE residual escribe INTO OUTFILE como el UID de mysqld.
SET ROLE NONE es la ruta que restaura ACL_USER::access. Los privilegios dinámicos (SYSTEM_USER) se eliminan. El residuo a nivel de base de datos ya está cerrado (Bug#35386565). Las cuentas predeterminadas no tienen roles.
| ID | sin CVE aún |
| Clase | Privilegio residual (FILE como UID de mysqld; no es LPE del SO) |
| Alcance | Remoto (SQL autenticado) |
| 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 |
| Producto | MySQL Community Server mysqld |
| Afectado | 26.7.0 (06a5c1c99c377fc41b2eba1ea244e8b220bdc3c8) |
| Autenticación | autenticado; la víctima tiene otorgado un rol que conlleva ACLs globales estáticas (FILE en el laboratorio) |
| Licencia | GNU Affero GPL v3.0 |
| Laboratorio | solo 127.0.0.1. Archivo testigo. Escritura FILE residual. |
Poseer una cuenta a la que se le otorgó un rol con FILE (u otro bit global estático). SET ROLE a ese rol, luego SET ROLE ALL EXCEPT sobre él. CURRENT_ROLE() reporta NONE. SELECT 'witness' INTO OUTFILE sigue escribiendo como el UID de mysqld bajo secure_file_priv.
Una aplicación que aísla con SET ROLE ALL EXCEPT dangerous_role o SET ROLE DEFAULT y luego confía en CURRENT_ROLE() todavía tiene esos bits estáticos. SET ROLE NONE sí los elimina.
El residuo no otorga FILE a la cuenta que nunca lo tuvo a través de un rol. Falla en eliminar FILE después de la desactivación.
La misma búsqueda en 26.7.0 que los tres residuos de cliente. El daemon predeterminado sin publicar Crit/High estaba vacío. ACL / roles todavía tenía este retorno temprano de rol vacío.
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) y activate_role_default vacío llaman a ese checkout. activate_role_none luego hace set_master_access(user->access).
Giro equivocado ya registrado: el primer residuo SELECT note FROM lab.t INTO OUTFILE devolvió 1142 (caché db_acl() 0). El SELECT 'witness' INTO OUTFILE constante es el oráculo de FILE.
cd lab
./run.sh
Imagen mysql:26.7.0. Publicado 127.0.0.1:18630. El rol rfile tiene FILE. La víctima tiene GRANT SELECT ON lab.* y GRANT rfile, file_priv=N, sin rol predeterminado. Outfile de inicio de sesión 1227. SET ROLE rfile outfile ok. SET ROLE ALL EXCEPT rfile hace que CURRENT_ROLE() sea NONE; el outfile residual escribe /var/lib/mysql-files/MYSQL-SET-ROLE-LEFTOVER-WITNESS. SET ROLE NONE es 1227 de nuevo.
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
Cuando m_active_roles está vacío, checkout_access_maps() debería hacer set_master_access(user->access) de la misma forma que SET ROLE NONE ya lo hace. ALL EXCEPT / DEFAULT vacío no debería conservar el mapa agregado anterior.
06a5c1c99c377fc41b2eba1ea244e8b220bdc3c8)sql/auth/sql_security_ctx.cc checkout_access_mapssql/auth/roles.cc activate_role_all / activate_role_none