暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL8.0的新特性——使用部分撤销授权,提高数据库的安全性

背景

前段时间,我遇到一个很麻烦的 MySQL 授权需求,如下:

一个库里有 2000 张表,但有 10 张表涉敏,客户希望普通用户可以读取任何一张表,但这 10 张涉敏表除外。

要做到客户的需求,在 MySQL5.7 下特别麻烦,需要梳理除了那 10 张涉密表之外的 1990 张表的表名,然后给他们都授权,那 10 张涉密表则不授权。

grant select on db.tb1 to user1@'10.%';
grant select on db.tb2 to user1@'10.%';
grant select on db.tb3 to user1@'10.%';
...
grant select on db.tb1990 to user1@'10.%'; #第1990行授权,第1990张表

这非常不优雅,一个普通用户 user1 下就有 1990 行授权,那么 user2 也要这个同样的授权怎么办?在 MySQL8.0 里,我们可以使用角色,先把权限授权给角色,成为一个权限模板,然后再把角色授给用户,例如:

# 建角色
create role 'app_read';

# 授权权限模板给角色
grant select on db.tb1 to 'app_read';
grant select on db.tb2 to 'app_read';
grant select on db.tb3 to 'app_read';
...
grant select on db.tb1990 to 'app_read'; #第1990行授权,第1990张表

# 把角色授给用户
grant 'app_read' to user1@'10.%';
grant 'app_read' to user2@'10.%';

相对于 MySQL5.7,MySQL8.0 的角色可以避免把相同的授权语句重复的写很多次,授权给用户时稍微优雅了一些。但处女座的 DBA 同学们在授权角色时还是很别扭,1990 行的授权,无论授权和查看授权都特别难受。如果这个时候业务同事创建一个新表,例如仅仅是做数据维护,创建了一张表叫 db.tb1990bak,怎么办?业务同事得 call DBA,“哥,麻烦再来一张表的授权”?

所以,这个需求对于 MySQL5.7 来说几乎可以说——做不了!

8.0新特性介绍:Partial Revokes——部分撤销授权

在 MySQL8.0 中,官方提供了一个新的功能,叫做“Partial Revokes”,中文名我就称之为“部分撤销授权”吧。

这个功能,看起来是,允许我们在给定了授权后,再挖走不想要的授权。

还是以文章开头授权需求的例子,使用“Partial Revokes”功能,我猜,我们的需求可以这么实现

grant select on db.* to user1@'10.%';
revoke all on db.sheminbiao1 from user1@'10.%';
revoke all on db.sheminbiao2 from user1@'10.%';
revoke all on db.sheminbiao3 from user1@'10.%';
revoke all on db.sheminbiao4 from user1@'10.%';
revoke all on db.sheminbiao5 from user1@'10.%';
revoke all on db.sheminbiao6 from user1@'10.%';
revoke all on db.sheminbiao7 from user1@'10.%';
revoke all on db.sheminbiao8 from user1@'10.%';
revoke all on db.sheminbiao9 from user1@'10.%';
revoke all on db.sheminbiao10 from user1@'10.%';

我们先授权 user1 对整个 DB 可读,然后再挖走 user1 对 10 张涉密表的所有权限。

是这样用么?我们看看报错!

mysql> revoke all on db.sheminbiao1 from user1@'%';
ERROR 1147 (42000): There is no such grant defined for user 'user1' on host '%' on table 'sheminbiao1'

事与愿违,“Partial Revokes”功能并不是我想象中那么用的,他仅仅能针对 schema 做部分撤销。下面是他的真正用法:

set persist partial_revokes = ON;

grant select,insert,update,delete on *.* to user1@'10.%';
revoke select on db.* from user1@'10.%';

mysql> show grants for user1@'10.%';
+---------------------------------------------------------------+
| Grants for user1@10.% |
+---------------------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO `user1`@`10.%` |
| REVOKE SELECT ON `db`.* FROM `user1`@`10.%` |
+---------------------------------------------------------------+
2 rows in set (0.00 sec)

他允许我先授权一个全局(所有库)的权限,然后挖走某个库的权限。

注意看例子红字部分:

  1. 部分撤销的授权必须是授权里的子集,例如你 grant select,insert,update,delete
    ,你不可能 revoke all
  2. 部分撤销的授权必须撤销某个 "库.*" 的库级授权,不能是 "库.表" 这种表级授权。

所以这个新特性,并不能解决我的需求!!(得解决提出需求的人,换个需求来实现,例如把涉密表挪到一个集中的 db 里,那么我们就可以使用部分撤销授权功能,撤销整个 db.*
的授权)

使用 Partial Revokes 功能构建更安全的私有云数据库服务

那么 Partial Revokes 真正的用途是什么?答案就是,构建更安全的私有云数据库服务。

我们 DBA 在部署完一套数据库服务后,交付给客户之前,我们需要创建一个给客户使用的较为高权的用户,使客户可以玩转整个数据库服务。整个权限大概是这样:

GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, 
REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, 
REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, 
ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO `fander`@`%` WITH GRANT OPTION;

为什么使用 *.*
,是因为我们并不知道客户需要创建什么数据库的库名。但 *.*
不安全。

这个其实就是阿里云上的阉割版高权

阿里云RDS 真正的高权实际上是 aliyun_root@'127.0.0.1',作为对比,阿里云给我们的高权,主要是阉割掉了以下权限:

这里看起来已经阉割掉很多高权了,那么数据库是真的安全了么? 我们发现,我们是持有 SELECT, INSERT, UPDATE, DELETE on *.*
的,而实际上,任何用户持有 SELECT on mysql.user
都已经足够危险了,如果我有这个权限,我是可以查询到阿里云的 root 的密码,从而使用 root 来登录的。

结果是,我确实可以查到阿里云高权账号 aliyun_root 的密码,密码就是为"空"!真是艺高人胆大啊。。但可信IP的 host 是 127.0.0.1, 意味着只有阿里云的管理员可以通过本地主机无密码登录高权,我是没办法偷偷登录了。

很快,我们能发现,我持有 UPDATE on mysql.user
的权限,这个权限就更变态了,我可以修改 MySQL 的权限表,任意提权。我先给自己的账号加个 SUPER 权限试试吧!

结果是,改不了,阿里云是有 SQL 防火墙的,这个 SQL防火墙具体是做在 DMS 上,还是做在 MySQL 内核里,我就不得而知了。但无论如何,就这个 SQL 防火墙的拦截功能,是需要开发的。

现在,我们在 MySQL8.0 上不需要 SQL 防火墙,也可以实现这个禁止修改 mysql 库的所有表,那就是 Partial Revokes 功能了。我们在开启了 Partial Revokes 功能后,只需要以下授权,取消掉 mysql 库的所有权限,就可以交付我们的数据库服务了。这对于私有云的建设节省了个功能的开发。

GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO `客户高权账号`@`%` WITH GRANT OPTION;
REVOKE SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON mysql.* FROM `客户高权账号`@`%`;


最后修改时间:2023-05-26 16:27:13
文章转载自芬达的数据库学习笔记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论