Bug #119248 CHECK TABLE command can be executed by users with the table-level GRANT OPTION privilege
Submitted: 27 Oct 16:46 Modified: 27 Oct 16:54
Reporter: Jingzhou Fu Email Updates:
Status: Open Impact on me:
None 
Category:MySQL Server: Security: Privileges Severity:S3 (Non-critical)
Version:9.4.0 OS:Any
Assigned to: CPU Architecture:Any

[27 Oct 16:46] Jingzhou Fu
Description:
The CHECK TABLE command can be executed by users who only have the table-level GRANT OPTION privilege.

How to repeat:
1. Login as the root user:

-- Create a database and a table
CREATE DATABASE test;
CREATE TABLE test.xxx (yyy INT);

-- Create two new users and grant the GRANT OPTION privilege
-- One for table-level (to reproduce the issue) and one for global-level (for comparison)
CREATE USER table_level_priv;
CREATE USER global_level_priv;
GRANT CREATE, GRANT OPTION ON *.* TO global_level_priv;
GRANT GRANT OPTION ON test.xxx TO table_level_priv;

2. Login as the global_level_priv user. This user has the global CREATE and GRANT OPTION privilege, but cannot run the CHECK TABLE command:
mysql> SHOW GRANTS;
+------------------------------------------------------------------+
| Grants for global_level_priv@%                                   |
+------------------------------------------------------------------+
| GRANT CREATE ON *.* TO `global_level_priv`@`%` WITH GRANT OPTION |
+------------------------------------------------------------------+
1 row in set (0.000 sec)

mysql> CHECK TABLE test.xxx;
ERROR 1142 (42000): SELECT command denied to user 'global_level_priv'@'localhost' for table 'xxx'

3. Login as the table_level_priv user (the result seems inconsistent with the global-level user)

mysql> SHOW GRANTS;
+-------------------------------------------------------------------------+
| Grants for table_level_priv@%                                           |
+-------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO `table_level_priv`@`%`                            |
| GRANT USAGE ON `test`.`xxx` TO `table_level_priv`@`%` WITH GRANT OPTION |
+-------------------------------------------------------------------------+
2 rows in set (0.000 sec)

mysql> CHECK TABLE test.xxx;
+----------+-------+----------+----------+
| Table    | Op    | Msg_type | Msg_text |
+----------+-------+----------+----------+
| test.xxx | check | status   | OK       |
+----------+-------+----------+----------+
1 row in set (0.001 sec)
[27 Oct 16:54] Jingzhou Fu
Another example (the user has the table-level CREATE privilege without GRANT OPTION):

Login as the root user:

DROP USER table_level_priv;
CREATE USER table_level_priv;
GRANT CREATE ON test.xxx TO table_level_priv;

Login as the table_level_priv user:
mysql> show grants;
+--------------------------------------------------------+
| Grants for table_level_priv@%                          |
+--------------------------------------------------------+
| GRANT USAGE ON *.* TO `table_level_priv`@`%`           |
| GRANT CREATE ON `test`.`xxx` TO `table_level_priv`@`%` |
+--------------------------------------------------------+
2 rows in set (0.000 sec)

mysql> check table test.xxx;
+----------+-------+----------+----------+
| Table    | Op    | Msg_type | Msg_text |
+----------+-------+----------+----------+
| test.xxx | check | status   | OK       |
+----------+-------+----------+----------+
1 row in set (0.000 sec)

The behavior of table-level and global-level is inconsistent, since the user with the global-level CREATE privilege cannot execute the CHECK TABLE command.