MySQL数据表的授权注意事项

2024年 3月 21日 76.5k 0

数据库的权限控制很重要,像Oracle、MySQL这种相对成熟的产品,权限控制体系相当完善,技术社群的这篇文章《技术分享 | MySQL 授权表运维注意事项》给我们讲解一些和数据表授权相关的内容,值得学习借鉴。

1基础背景

我们在做权限授权时需要给到应用用户增删改查权限,例如下面的授权语句。这样的好处是当实例创建多个业务库时,无需再次给新的业务库授权,该权限默认对所有库有增删改查权限,主打一个方便,但实际这种授权方式会带来较大的权限风险,甚至导致数据库被攻击破坏。

create user 'app'@'%' identified by 'app';
grant select,update,delete,insert on *.* to 'app'@'%';

2演示验证

我们基于以上的授权来做一个业务用户 提权(自己给自己增加额外的权限)操作,下面是操作的时序表格(建议 PC 端查看)。

场景1

管理用户触发 flush privileges
 刷新内存授权表触发提权。

操作/用户 root 用户 app 用户
登录 mysql -S data/mysql/3306/data/mysqld.sock mysql -h127.0.0.1 -uapp -papp -P3306
app 用户给自己提权。这里 update
 成功了,但由于缺少 reload 或 super 权限,导致刷新到内存中失败了。
mysql> update mysql.user set Select_priv='Y',Insert_priv='Y',Update_priv='Y',Delete_priv='Y',Create_priv='Y',Drop_priv='Y',Reload_priv='Y',Shutdown_priv='Y',Process_priv='Y',File_priv='Y',Grant_priv='Y',References_priv='Y',Index_priv='Y',Alter_priv='Y',Show_db_priv='Y',Super_priv='Y',Lock_tables_priv='Y' where user='app' and host='%';

Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> flush privileges;
ERROR 1227 (42000): Access denied; you need (at least one of) the RELOAD privilege(s) for this operation

某天 root 用户做了个 flush privileges 操作 mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
app 用户重新登录数据库查看自己的权限,提权成功。 mysql> show grantsG
*************************** 1. row ***************************
Grants for app@%: GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, LOCK TABLES ON . TO app@% WITH GRANT OPTION
1 row in set (0.00 sec)

场景2

重启数据库重新加载授权表到内存触发提权。

操作/用户 root 用户 app 用户
登录 mysql -S data/mysql/3306/data/mysqld.sock mysql -h127.0.0.1 -uapp -papp -P3306
app 用户给自己提权,这里 update 成功了,但由于缺少 reload 或 super 权限,导致刷新到内存中失败了。 mysql> update mysql.user set Select_priv='Y',Insert_priv='Y',Update_priv='Y',Delete_priv='Y',Create_priv='Y',Drop_priv='Y',Reload_priv='Y',Shutdown_priv='Y',Process_priv='Y',File_priv='Y',Grant_priv='Y',References_priv='Y',Index_priv='Y',Alter_priv='Y',Show_db_priv='Y',Super_priv='Y',Lock_tables_priv='Y' where user='app' and host='%';

Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> flush privileges;
ERROR 1227 (42000): Access denied; you need (at least one of) the RELOAD privilege(s) for this operation

重启数据库 mysql> restart;
Query OK, 0 rows affected (0.00 sec)
app 用户重新登录数据库查看自己的权限,提权成功。 mysql> show grantsG
*************************** 1. row ***************************
Grants for app@%: GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, LOCK TABLES ON . TO app@% WITH GRANT OPTION
1 row in set (0.00 sec)

3场景总结

  • 给普通用户授予 MySQL 鉴权相关表的权限均会带来风险
    • 备注:鉴权表除了 user
       表,还包括 db
      columns_priv
      tables_priv
      procs_priv
      proxies_priv
       表。
  • 即使只对鉴权表授予只读权限,如 user
     表,也会被获取到 authentication_string
     字段的密文串,通过其他方式做密码库匹配破解。
    • 曾经遇到过一个场景,普通用户仅有 user
       的查询权限,其通过查询该表信息发现 root@localhost
       用户密码为空,于是直接用 root 用户访问数据库,类似于进行了提权操作。

4规避方式

  • 不要对非管理员用户授予任何鉴权表的访问权限,即使是只读权限。
  • 授权遵循最小权限原则。
  • MySQL 8.0 增加了回收部分权限的参数 partial_revokes
    ,可单独将 mysql
     库的权限回收。示例如下:

-- 创建app用户并授予所有数据库增删改查权限
create user 'app'@'%' identified by 'app';
grant select,update,delete,insert on *.* to 'app'@'%';

-- 开启部分权限回收的参数
set global partial_revokes=on;

-- 单独回收app用户对mysql库的权限
revoke select,update,delete,insert on mysql.* from 'app'@'%';

-- 查看当前app用户的授权信息
-- 这里的权限是以交集的形式存在,必须两者都满足
show grants for app;
+-------------------------------------------------------------------+
| Grants for app@%                                                  |
+-------------------------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO `app`@`%`          |
| REVOKE SELECT, INSERT, UPDATE, DELETE ON `mysql`.* FROM `app`@`%` |
+-------------------------------------------------------------------+

-- 以app用户登录数据库访问mysql.user表,报错无权限
mysql> select user,host from mysql.user;
ERROR 1142 (42000): SELECT command denied to user 'app'@'127.0.0.1' for table 'user'

如果您认为这篇文章有些帮助,还请不吝点下文章末尾的"点赞"和"在看",或者直接转发pyq,

近期更新的文章:《链路抖动问题的处理路径》《MySQL的skip-networking配置影响》
《应用运维值班体系的思考》《我的老朋友,天堂之上,愿你安好》
《MySQL分区和分表的基础介绍》
近期的热文:《推荐一篇Oracle RAC Cache Fusion的经典论文》
《"红警"游戏开源代码带给我们的震撼》
文章分类和索引:《公众号1400篇文章分类和索引》

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论