Question

I have discovered a difference between show grants for user@host and the mysql.db table. Why is this?

How can I resolve this? We are worried about security.

I ran a show grants against users in mysql.users. In mysql.users the user is user@xxx.xxx.xxx.xx and when I run show grants it says GRANT USAGE TO user@xxx.xxx.xxx.xx

This worried me as this user also seems to be able to access a database.

When I looked in mysql.db and information_schema.schema_privileges I can see the same user as user with a host of xxx.xxx.% with full access to that database.

What gives?

Edit - Deeper Explanation:

Here is what I have:

show grants for 'myuser'@'xxx.xxx.xxx.xxx';

It returns:

GRANT USAGE ON *.* TO 'myuser'@'xxx.xxx.xxx.xxx' IDENTIFIED BY PASSWORD 'xxxxxxxxxxxxxxxxx'

If I run:

select host,db,user from mysql.db where user='myuser';

I get:

+----------+------------+------------+
| host     | db         | user       |
+----------+------------+------------+
|xxx.xxx.% | somedb     | myuser     |
+----------+------------+------------+
Was it helpful?

Solution

Don't worry.

The mysql.user table mitigates specific global privileges on all databases.

If a user is restricted to a specific database, you will only see database specific grants in the mysql.db table. A user restricted to a database does not need SUPER, PROCESS, SHUTDOWN, and privileges like these.

If you create a user withglobal privileges (thus landing the user in mysql.user), you cannot revoke global privileges only to demote the user to a specfic database. If you try to do so with REVOKE commands, you will see the user in mysql.user with the original Y values on all columns and the same user in mysql.db with Y values on database specific privileges.

You must completely drop the user and create the user fresh with the lower privileges.

Here is an example based on the comments

mysql> show grants for advdb@'%';
+-----------------------------------------------------------------------------+
| Grants for advdb@%                                                          |
+-----------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'advdb'@'%' IDENTIFIED BY PASSWORD '................' |
| GRANT ALL PRIVILEGES ON `advertpro`.* TO 'advdb'@'%'                        |
+-----------------------------------------------------------------------------+

The GRANT USAGE simply allows you to know what MD5 password is involved with authentication (if the password is not blank). Note that advdb can login from any IP address and only access the advertpro database.

The user does not need PROCESS privilege unless you want the user to see all processes in the processlist, even the one that belong to others.

The user does not need SUPER privilege unless you want the user to write in a read-only mysql instance, start and stop replication, zap binary logs, and things like these.

The user does not need SHUTDOWN privilege unless you want the user to shutdown mysql from the OS command line user the mysqladmin client program.

To copy the priv you are looking for,

  • SHOW GRANTS FOR 'user'@'xxx.xxx.xxx.%';
  • Copy the output to text file
  • Edit the host to xxx.xxx.xxx.xx
  • Add a semicolon
  • Paste that to the other server

OK let's hack that:

UPDATE mysql.db
    SET host='xxx.xxx.xxx.xxx'
    WHERE user='myuser'
    AND host='xxx.xxx.%'
    AND db='somedb';
FLUSH PRIVILEGES;

This should it !!!

To dump the MySQL Grants in SQL, you can do pt-show-grants It is much better to port the mysql grants using pt-show-grants.

Here is my personal emulation of what pt-show-grants does

mysql -hhostaddr -umyuserid -pmypassword --skip-column-names -A -e"SELECT CONCAT('SHOW GRANTS FOR ''',user,'''@''',host,''';') FROM mysql.user WHERE user<>''" | mysql -hhostaddr -umyuserid -pmypassword --skip-column-names -A | sed 's/$/;/g' > MySQLUserGrants.sql
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top