Description:
Users without any permissions can retrieve table names via the error message of the DROP TRIGGER statement.
For example, if the table `test.tbl` has a trigger named `before_insert_tbl`, a user without any permissions can retrieve the table name by executing the statement `DROP TRIGGER test.before_insert_tbl`. The error message displayed is "ERROR 1142 (42000): TRIGGER command denied to user 'foo'@'localhost' for table 'tbl'", which reveals the table name `tbl` to the user.
How to repeat:
The Proof of Concept (PoC):
```sql
# Use the root user to connect to MySQL and create a trigger and an empty user
# Example:
# docker run -e MYSQL_ALLOW_EMPTY_PASSWORD=1 -p 3306:3306 -itd --name some-mysql mysql:9.1.0
# docker exec -it some-mysql mysql -uroot
CREATE DATABASE test;
CREATE TABLE test.tbl (x INT);
CREATE TRIGGER test.before_insert_tbl -- Create a trigger
BEFORE INSERT ON test.tbl FOR EACH ROW
INSERT INTO test SELECT 1;
CREATE USER foo; -- Create a empty user
QUIT; -- Exit
# Login with the user `foo` and try to drop trigger
# Example:
# docker exec -it some-mysql mysql -ufoo
DROP TRIGGER test.test; -- Drop a non-existing trigger
-- Error message: ERROR 1360 (HY000): Trigger does not exist
DROP TRIGGER test.before_insert_tbl; -- Drop an existing trigger
-- Error message: ERROR 1142 (42000): TRIGGER command denied to user 'foo'@'localhost' for table 'tbl'
```
From the error message when dropping an existing trigger, the user `foo` (who has no permissions) can infer the existence of the database `test`, the table `test.tbl`, and the trigger `test.before_insert_tbl`.
If the user can "guess" a trigger name (e.g., via brute-force enumeration or by attempting commonly-used names) and the trigger name exists, the user can infer the existence of the trigger and retrieve the corresponding table name via the `DROP TRIGGER` statement.
Since the user has no permissions, it seems unreasonable that they can obtain information about databases, tables, and triggers. Maybe it is a bug or issue?
Suggested fix:
Instead, other statements like the DROP INDEX statment can protect such information:
```
# Create index with the root user
CREATE INDEX w ON test.tbl(x);
QUIT; -- Exit
# Connect with the empty user
# Example:
# docker exec -it some-mysql mysql -ufoo
# Attempting DROP INDEX
DROP INDEX w ON test.tbl;
-- ERROR 1142 (42000): INDEX command denied to user 'foo'@'localhost' for table 'tbl'
DROP INDEX w ON testx.tbl;
-- ERROR 1142 (42000): INDEX command denied to user 'foo'@'localhost' for table 'tbl'
DROP INDEX w ON `???`.tbl;
-- ERROR 1142 (42000): INDEX command denied to user 'foo'@'localhost' for table 'tbl'
DROP INDEX w ON `???`.`???`;
-- ERROR 1142 (42000): INDEX command denied to user 'foo'@'localhost' for table '???'
DROP INDEX w ON `test`.`???`;
-- ERROR 1142 (42000): INDEX command denied to user 'foo'@'localhost' for table '???'
DROP INDEX `???` ON testx.tbl;
-- ERROR 1142 (42000): INDEX command denied to user 'foo'@'localhost' for table 'tbl'
```
For the `DROP INDEX` statement, the user without permissions cannot retrieve any information about the database, table, or index because the error messages are always generic. This seems to be the correct behavior for `DROP` statements.
So, maybe current error message of DROP TRIGGER need to be improved?