找回密码
 立即注册
首页 业界区 业界 MySQL权限管理的坑你踩了没有?

MySQL权限管理的坑你踩了没有?

锟及 2025-11-25 14:55:01
假设有这么一个需求,开发人员要求你创建一个账号test,要求这个账号有创建表,查询,更新,删除表的权限, 如下例子所示
  1. mysql> select version();
  2. +-----------+
  3. | version() |
  4. +-----------+
  5. | 8.4.5     |
  6. +-----------+
  7. 1 row in set (0.00 sec)
  8. mysql> create database if not exists kerry   
  9.     -> default character set utf8mb4
  10.     -> default collate utf8mb4_general_ci;
  11. query ok, 1 row affected (0.02 sec)
  12. mysql> create user `test`@`%` identified by  'Test@#$123456';
  13. Query OK, 0 rows affected (0.02 sec)
  14. mysql>
  15. mysql> grant create, drop ,select,update on kerry.* to test@'%';
  16. Query OK, 0 rows affected (0.00 sec)
  17. mysql> flush privileges;
  18. Query OK, 0 rows affected (0.01 sec)
  19. mysql>
复制代码
然后我们以test用户登录数据库, 此时你执行下面SQL,你会发现,你不光有drop掉表的权限,甚至连数据库kerry都可以drop掉.如下所示
  1. mysql> select current_user();
  2. +----------------+
  3. | current_user() |
  4. +----------------+
  5. | test@%         |
  6. +----------------+
  7. 1 row in set (0.00 sec)
  8. mysql> create table t1(id int, name varchar(12));
  9. Query OK, 0 rows affected (0.02 sec)
  10. mysql> drop table t1;
  11. Query OK, 0 rows affected (0.01 sec)
  12. mysql> drop database kerry;
  13. Query OK, 0 rows affected (0.01 sec)
  14. mysql>
复制代码
然后你会发现,test用户不光有drop掉数据库kerry的权限,而且有创建数据库kerry的权限(仅仅是创建/删除kerry这个数据库.没有创建/删除其它数据库的权限),如下所示:
  1. mysql> select current_user();
  2. +----------------+
  3. | current_user() |
  4. +----------------+
  5. | test@%         |
  6. +----------------+
  7. 1 row in set (0.00 sec)
  8. mysql> create database if not exists kerry
  9.     -> default character set utf8mb4
  10.     -> default collate utf8mb4_general_ci;
  11. query ok, 1 row affected (0.01 sec)
  12. mysql> drop database kerry;
  13. query ok, 0 rows affected (0.00 sec)
  14. mysql> create database kkk;
  15. error 1044 (42000): access denied for user 'test'@'%' to database 'kkk'
  16. mysql> drop database k2;
  17. ERROR 1044 (42000): Access denied for user 'test'@'%' to database 'k2'
  18. mysql>
复制代码
其实具体原因是你没有留意MySQL官方文档关于CREATE/DROP权限的详细说明,你以为的CREATE权限是创建表的权限,DROP权限是DROP表的权限.其实不然, 如下截图所示,CREATE权限包含创建数据库、表或索引的权限,而DROP权限包DROP数据库、表或视图的权限. 至于为什么MySQL没有细化这些权限.我们也不清楚.但是从上面实验来看, 我都倾向于这个是一个逻辑上的"Bug".
1.png

那么如果这样授权,会有什么问题呢?  **如果账号授予了DROP权限,那么这就是一个安全权限的"漏洞", SQL注入式攻击都可以利用这个"漏洞"直接将数据库给删除了. **
解决方案

MySQL中没有单独的CREATE TABLE, DROP TABLE的权限,我们只能另避蹊径,先收回账号test的DROP权限,然后创建一个角色drop_tab,这个角色授予数据库kerry中具体每一个表的DROP权限,最后授予用户这个角色. 如下所示:
  1. mysql> select current_user();
  2. +----------------+
  3. | current_user() |
  4. +----------------+
  5. | root@localhost |
  6. +----------------+
  7. 1 row in set (0.01 sec)
  8. mysql> show grants for test@'%';
  9. +---------------------------------------------------------------+
  10. | Grants for test@%                                             |
  11. +---------------------------------------------------------------+
  12. | GRANT USAGE ON *.* TO `test`@`%`                              |
  13. | GRANT SELECT, UPDATE, CREATE, DROP ON `kerry`.* TO `test`@`%` |
  14. +---------------------------------------------------------------+
  15. 2 rows in set (0.00 sec)
  16. mysql> revoke drop on  `kerry`.* from `test`@`%`;
  17. Query OK, 0 rows affected (0.06 sec)
  18. mysql> flush privileges;
  19. Query OK, 0 rows affected (0.01 sec)
  20. mysql> create role drop_tab;
  21. Query OK, 0 rows affected (0.01 sec)
  22. mysql> select
  23.     ->      table_name
  24.     ->     ,table_type
  25.     ->     ,concat('grant drop on ', table_schema, '.', table_name , ' to test@''%'';') as grant_cmd
  26.     -> from information_schema.tables
  27.     -> where table_schema='kerry';
  28. +------------+------------+-------------------------------------+
  29. | TABLE_NAME | TABLE_TYPE | grant_cmd                           |
  30. +------------+------------+-------------------------------------+
  31. | t1         | BASE TABLE | grant drop on kerry.t1 to test@'%'; |
  32. | t2         | BASE TABLE | grant drop on kerry.t2 to test@'%'; |
  33. +------------+------------+-------------------------------------+
  34. 2 rows in set (0.00 sec)
  35. mysql>
  36. mysql> grant drop on kerry.t1 to test@'%';
  37. Query OK, 0 rows affected (0.01 sec)
  38. mysql> grant drop on kerry.t2 to test@'%';
  39. Query OK, 0 rows affected (0.00 sec)
  40. mysql> grant drop_tab to test@'%';
  41. Query OK, 0 rows affected (0.00 sec)
  42. mysql> flush privileges;
  43. Query OK, 0 rows affected (0.00 sec)
  44. mysql>
复制代码
此时,账号test就没有删除数据库kerry的权限了.
  1. mysql> select current_user();
  2. +----------------+
  3. | current_user() |
  4. +----------------+
  5. | test@%         |
  6. +----------------+
  7. 1 row in set (0.00 sec)
  8. mysql> drop table t1;
  9. Query OK, 0 rows affected (0.02 sec)
  10. mysql> drop database kerry;
  11. ERROR 1044 (42000): Access denied for user 'test'@'%' to database 'kerry'
  12. mysql>
复制代码

总结

关于数据库的权限,我们还是要细心与谨慎. 数据库授权,一般要秉着权限越小越好的原则,避免权限过大带来不必要的麻烦. 另外,就是MySQL这种权限设计,        其实是设计上的一大缺陷.很容易让人踩一个大坑.
扫描上面二维码关注我如果你真心觉得文章写得不错,而且对你有所帮助,那就不妨帮忙“推荐"一下,您的“推荐”和”打赏“将是我最大的写作动力!本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接.
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册