Bug #113349 Non-super user can grant binlog_admin to others even if itself has no such priv
Submitted: 6 Dec 2023 7:50 Modified: 7 Dec 2023 1:39
Reporter: Fan Lyu Email Updates:
Status: Not a Bug Impact on me:
None 
Category:MySQL Server: Security: Privileges Severity:S3 (Non-critical)
Version:8.0 OS:Any
Assigned to: CPU Architecture:Any

[6 Dec 2023 7:50] Fan Lyu
Description:
Summary:

Non-super priv users can grant themselves and other users  binlog_admin, even when itself has no such priv.

How to repeat:
reproduce

//Step1: create user 'testlf'@'%' with super user, grant it with several privs, except binlog_admin; also grant this user with grant option
mysql> create user 'testlf'@'%' identified by '123456';
Query OK, 0 rows affected (0.13 sec)

mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO `testlf`@`%` WITH GRANT OPTION;
Query OK, 0 rows affected (0.01 sec)

 
//Step2: login with 'testlf'@'%'
mysql> show grants;
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Grants for testlf@%                                                                                                                                                                                                                                                                                                              |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO `testlf`@`%` WITH GRANT OPTION |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

// obviously it has no binlog_admin priv.
// step3: login with 'testlf'@'%', create a new user 'lftest2'@'%', grant binlog_admin to 'lftest2'@'%' 
mysql> create user 'lftest2'@'%' identified by '123456';
Query OK, 0 rows affected (0.01 sec)

mysql> grant binlog_admin on *.* to 'lftest2'@'%' ;
Query OK, 0 rows affected (0.02 sec)

mysql> show grants for lftest2;
+--------------------------------------------+
| Grants for lftest2@%                       |
+--------------------------------------------+
| GRANT USAGE ON *.* TO `lftest2`@`%`        |
| GRANT BINLOG_ADMIN ON *.* TO `lftest2`@`%` |
+--------------------------------------------+

// step3: login with 'testlf'@'%', grant binlog_admin to itself
mysql> grant binlog_admin on *.* to 'testlf'@'%' ;
Query OK, 0 rows affected (0.01 sec)

mysql> show grants;
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Grants for testlf@%                                                                                                                                                                                                                                                                                                              |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO `testlf`@`%` WITH GRANT OPTION |
| GRANT BINLOG_ADMIN ON *.* TO `testlf`@`%`                                                                                                                                                                                                                                                                                        |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

Suggested fix:
I am wondering whether this is an acceptable design or a bug?

According to my knowledge,'with grant option' can only 'inherit' privs of one user itself to others.
[6 Dec 2023 7:52] Fan Lyu
typo
we also found 

mysql> revoke binlog_admin on *.* from 'testlf'@'%' ;
Query OK, 0 rows affected (0.01 sec)

has 0 rows affected.
[6 Dec 2023 10:48] MySQL Verification Team
Hi Mr. Lyu,

Thank you for your bug report.

However, this is not a bug.

All that you need to grant ANY privilege in our system is to add ........ WITH GRANT OPTION.

BINLOG_ADMIN is intended for the totally different purposes. To quote from our Manual:

----------------------------------------------------
BINLOG_ADMIN

Enables binary log control by means of the PURGE BINARY LOGS and BINLOG statements.
---------------------------------------------------

Hence, if your 'testlf' user is able to execute the above two statements, then it would have been a bug.

We hope that we were clear enough.
[6 Dec 2023 13:54] MySQL Verification Team
HI,

Please do not follow the above advice, since you should NOT use any DML statements directly on any table in the Data Dictionary.

Hence, no use of UPDATE or similar .......

This is why the above comment is now hidden ......
[7 Dec 2023 1:39] Fan Lyu
Hi MySQL Team

Maybe I have not described my issue clearly since English is not my mother tongue.

According to community doc:
https://dev.mysql.com/doc/refman/8.0/en/grant.html

To grant a privilege with GRANT, you must have the GRANT OPTION privilege, and 【you must have the privileges that you are granting】.

exactly, as mentioned in reproduction steps:
I was login with 【//Step2: login with 'testlf'@'%'】

and grant binlog_admin priv to [lftest2] and [testlf itself] with this 【'testlf'@'%'】,which itself has no binlog_admin.
 
before granting binlog_admin to  [lftest2] and [testlf itself], we show grants for 【'testlf'@'%'】 and 'testlf'@'%' has no binlog_admin.

This means 'testlf'@'%' is granting one priv to other, which itself does not have
[7 Dec 2023 11:05] MySQL Verification Team
Hi,

We can only repeat what we replied before .....

All that you need to grant ANY privilege in our system is to add ........ WITH GRANT OPTION.

BINLOG_ADMIN is intended for the totally different purposes. To quote from our Manual:

----------------------------------------------------
BINLOG_ADMIN

Enables binary log control by means of the PURGE BINARY LOGS and BINLOG statements.
---------------------------------------------------

Hence, if the user with GRANT OPTION has only SELECT (for example) privilege, that user can grant any privilege to any other user.

This is all described in our Reference Manual. And finally:

Not a bug.