
MySQL Community Server 26.7.0 – Hoch – SET ROLE ALL EXCEPT verbleibende FILE – mysqld UID-Schreibzugriff
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · mysql-set-role-leftover
Write-up: https://abraxaslabs.tech/research/mysql-set-role-leftover
Klasse: Privilegien-Überbleibsel (FILE als mysqld-UID; keine OS-LPE) Erreichbarkeit: Remote
MySQL Community Server mysqld 26.7.0 (06a5c1c) - Oracle
SET ROLE ALL EXCEPT rfile (oder SET ROLE DEFAULT ohne Defaults) leert die Liste der aktiven Rollen, dann kehrt checkout_access_maps() zurück, ohne set_master_access(user->access) aufzurufen. CURRENT_ROLE() ist NONE. Statische globale Bits, die die Rolle aggregiert hat (FILE, PROCESS, SUPER, ...), bleiben in m_master_access erhalten. check_access liest dieses Überbleibsel. Labor: Das übrig gebliebene FILE schreibt INTO OUTFILE als die mysqld-UID.
SET ROLE NONE ist der Pfad, der ACL_USER::access wiederherstellt. Dynamische Privilegien (SYSTEM_USER) entfallen. Das Überbleibsel auf DB-Ebene ist bereits geschlossen (Bug#35386565). Standardkonten haben keine Rollen.
| ID | noch keine CVE |
| Klasse | Privilegien-Überbleibsel (FILE als mysqld-UID; keine OS-LPE) |
| Erreichbarkeit | Remote (authentifiziertes SQL) |
| CWE | CWE-269 |
| CVSS | Hoch: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
| Produkt | MySQL Community Server mysqld |
| Betroffen | 26.7.0 (06a5c1c99c377fc41b2eba1ea244e8b220bdc3c8) |
| Auth | authentifiziert; dem Opfer wird eine Rolle gewährt, die statische globale ACLs trägt (FILE im Labor) |
| Lizenz | GNU Affero GPL v3.0 |
| Labor | nur 127.0.0.1. Witness-Datei. Schreiben mit übrig gebliebenem FILE. |
Ein Konto besitzen, dem eine Rolle mit FILE (oder einem anderen statischen globalen Bit) gewährt wurde. SET ROLE auf diese Rolle ausführen, dann SET ROLE ALL EXCEPT darauf. CURRENT_ROLE() meldet NONE. SELECT 'witness' INTO OUTFILE schreibt weiterhin als die mysqld-UID unter secure_file_priv.
Eine Anwendung, die mit SET ROLE ALL EXCEPT dangerous_role oder SET ROLE DEFAULT sandboxt und dann CURRENT_ROLE() vertraut, besitzt diese statischen Bits weiterhin. SET ROLE NONE entfernt sie tatsächlich.
Das Überbleibsel gewährt FILE nicht einem Konto, das es nie über eine Rolle besaß. Es versäumt, FILE nach der Deaktivierung zu entfernen.
Dieselbe 26.7.0-Jagd wie bei den drei Client-Überbleibseln. Das unveröffentlichte Crit/High des Standard-Daemons war leer. ACL / Rollen hatten noch immer diesen Early Return bei leerer Rolle.
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 (ALLE AUSSER) und ein leerer activate_role_default-Aufruf, der diesen Checkout ausführt. activate_role_none führt dann set_master_access(user->access) aus.
Bereits festgehaltene Fehlentwicklung: Das erste übrig gebliebene SELECT note FROM lab.t INTO OUTFILE lieferte 1142 zurück (db_acl()-Cache 0). Das konstante SELECT 'witness' INTO OUTFILE ist das FILE-Orakel.
cd lab
./run.sh
Image mysql:26.7.0. Veröffentlicht 127.0.0.1:18630. Rolle rfile hat FILE. Opfer hat GRANT SELECT ON lab.* und GRANT rfile, file_priv=N, keine Standardrolle. Login outfile 1227. SET ROLE rfile outfile ok. SET ROLE ALL EXCEPT rfile macht CURRENT_ROLE() NONE; übrig gebliebene outfile-Schreibvorgänge nach /var/lib/mysql-files/MYSQL-SET-ROLE-LEFTOVER-WITNESS. SET ROLE NONE ist wieder 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
Wenn m_active_roles leer ist, sollte checkout_access_maps() set_master_access(user->access) aufrufen, so wie es SET ROLE NONE bereits tut. Ein leeres ALL EXCEPT / DEFAULT sollte nicht die zuvor aggregierte Map beibehalten.
06a5c1c99c377fc41b2eba1ea244e8b220bdc3c8)sql/auth/sql_security_ctx.cc checkout_access_mapssql/auth/roles.cc activate_role_all / activate_role_none