Description:
I have found a serious bug in version 4.1.0. So far, I have only verified it on Solaris 8 but it may be also present in other platforms. Due to this bug, the privileges that a user has on one database can be extended to other databases that have A NAME WITH THE SAME NUMBER OF CHARACTERS. The bug can be exploited locally as well as remotely. It is possible to gain remote root access this way.
Example:
--------
You have three databases named 'aaa', 'bbb', 'ccc' on your server. If a user has access rights to the database 'aaa' (the first in alphabetical order, this is important!), he/she will have the same access rights to 'bbb' and 'ccc'. In fact, he/she will have the same access rights on all databases that have a name with exactly three characters. This only works if the user logs in through the TCP/IP port.
How to repeat:
I have only verified this on Solaris 8/Sparc:
- Install a fresh version of 4.1.0-alpha-standard and create the empty default data base with the mysql_install_db script.
- Log in as root and type in the following commands:
CREATE DATABASE aaa;
CREATE DATABASE bbb;
CREATE DATABASE ccc;
USE mysql;
DELETE FROM db;
DELETE FROM user;
GRANT ALL ON *.* TO 'root'@'localhost';
GRANT ALL ON `aaa`.* TO 'test'@'%';
FLUSH PRIVILEGES;
This will create the three databases and a user 'test' that should only have access to 'aaa'.
- Verify your actual access rights by connectin through the TCP/IP port. This also works remotely and with clients before MySQL 4.1:
----- Output from 'mysql -h <servername> -u test --password=""' -----
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 5 to server version: 4.1.0-alpha-standard-log
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> show grants for test@'%';
+-----------------------------------------------+
| Grants for test@% |
+-----------------------------------------------+
| GRANT USAGE ON *.* TO 'test'@'%' |
| GRANT ALL PRIVILEGES ON `aaa`.* TO 'test'@'%' |
+-----------------------------------------------+
2 rows in set (0.00 sec)
mysql> show databases;
+----------+
| Database |
+----------+
| aaa |
| bbb |
| ccc |
+----------+
3 rows in set (0.00 sec)
[Note: we would only expect to see 'aaa' here!]
mysql> use bbb;
Database changed
mysql> CREATE TABLE illegal ( forbidden int );
Query OK, 0 rows affected (0.01 sec)
[Note: we should not even be able to use this data base!]
mysql> SHOW TABLES;
+---------------+
| Tables_in_bbb |
+---------------+
| illegal |
+---------------+
1 row in set (0.00 sec)
mysql> INSERT INTO illegal VALUES( 123 ),( 456 ),( 789 );
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM illegal;
+-----------+
| forbidden |
+-----------+
| 123 |
| 456 |
| 789 |
+-----------+
3 rows in set (0.00 sec)
mysql> DROP TABLE illegal;
Query OK, 0 rows affected (0.01 sec)
mysql> exit
Bye
----- End of log file -----
Notes:
------
- This does not work if the user has only privileges on 'bbb' or 'ccc'.
- If the user has no access rights on 'aaa', he/she will not be able to access any of the three databases through the TCP/IP port.
- If the user connects through 'localhost', everything works as expected.
- If the database had been called 'aaaaa' instead, the user would have had full access to the 'mysql' data base.
Suggested fix:
Sorry, no idea.