
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
Análisis: https://abraxaslabs.tech/research/mysql-set-role-leftover
Clase: Privilegio residual (FILE como UID de mysqld; no es LPE de SO) Alcance: Remoto
MySQL Community Server mysqld 26.7.0 (06a5c1c) - Oracle
SET ROLE ALL EXCEPT rfile (o SET ROLE DEFAULT sin roles predeterminados) vacía 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 | aún sin CVE |
| Clase | Privilegio residual (FILE como UID de mysqld; no es LPE de 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; a la víctima se le concede un rol que conlleva ACL 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 concedió un rol con FILE (u otro bit global estático). Ejecutar SET ROLE sobre ese rol y luego SET ROLE ALL EXCEPT sobre él. CURRENT_ROLE() informa NONE. SELECT 'witness' INTO OUTFILE sigue escribiendo como el UID de mysqld bajo secure_file_priv.
Una aplicación que aplica sandbox con SET ROLE ALL EXCEPT dangerous_role o SET ROLE DEFAULT y luego confía en CURRENT_ROLE() todavía conserva esos bits estáticos. SET ROLE NONE sí los elimina.
El residuo no concede FILE a una cuenta que nunca lo tuvo mediante un rol. Falla en eliminar FILE tras la desactivación.
La misma búsqueda en 26.7.0 que los tres residuos de cliente. El daemon predeterminado sin publicar de severidad Crítica/Alta estaba vacío. ACL / roles todavía tenían 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 (TODOS EXCEPTO) y la llamada vacía a activate_role_default que ejecutan ese checkout. Luego activate_role_none hace set_master_access(user->access).
Giro incorrecto ya registrado: el primer SELECT note FROM lab.t INTO OUTFILE sobrante devolvió 1142 (caché de db_acl() en 0). El SELECT 'witness' INTO OUTFILE constante es el oráculo de FILE.
cd lab
./run.sh
Imagen mysql:26.7.0. Publicada en 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. Inicio de sesión outfile 1227. SET ROLE rfile outfile ok. SET ROLE ALL EXCEPT rfile hace que CURRENT_ROLE() sea NONE; las escrituras outfile residuales escriben /var/lib/mysql-files/MYSQL-SET-ROLE-LEFTOVER-WITNESS. SET ROLE NONE vuelve a ser 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
Cuando m_active_roles está vacío, checkout_access_maps() debería hacer set_master_access(user->access) de la misma forma en que ya lo hace SET ROLE NONE. Un 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