# 22、等保测评2.0_Mysql访问控制理解解读

LLMS index: [llms.txt](/wikis/llms.txt)

---

## **一、说明**
**本篇文章主要说一说**[MySQL](https://cloud.tencent.com/product/cdb?from=20065&from_column=20065)**中访问控制控制点的相关内容和理解。，其余层面要求项见**[**https://cloud.tencent.com/developer/column/2006**](https://cloud.tencent.com/developer/column/2006)

## **二、测评项**
a)应对登录的用户分配账户和权限； b)应重命名或删除默认账户，修改默认账户的默认口令； c)应及时删除或停用多余的、过期的账户，避免共享账户的存在； d)应授予管理用户所需的最小权限，实现管理用户的权限分离； e)应由授权主体配置访问控制策略，访问控制策略规定主体对客体的访问规则；f)访问控制的粒度应达到主体为用户级或进程级，客体为文件、[数据库](https://cloud.tencent.com/solution/database?from=20065&from_column=20065)表级； g)应对重要主体和客体设置安全标记，并控制主体对有安全标记信息资源的访问。

## **三、测评项a**
a)应对登录的用户分配账户和权限；

### **3.1. 要求1**
如果从字面意思来看，就是一个废话，用户都登录账户了，自然就存在着账户。

这里的意思是应该是你本来就存在“多个账户”，然后当用户使用时要适当的“分配账户”给用户，而账户再拥有不一样的权限，这样就实现了将权限通过账户分配给用户（自然人）。

所以，该测评项就需要MySQL中存在至少两个账户，且这两个账户的权限不一样。

### **3.2. 要求2**
在测评要求中测评实施如下：

![](/wikis/_resources/22%E3%80%81%E7%AD%89%E4%BF%9D%E6%B5%8B%E8%AF%842.0_MySQL%E8%AE%BF%E9%97%AE%E6%8E%A7%E5%88%B6%E7%90%86%E8%A7%A3%E8%A7%A3%E8%AF%BB/acf77c08e2db6a62c315f11ffbcd60e1_MD5.png)

在MySQL中，安装完成后默认存在的账户一般有3个，都是root：

![](/wikis/_resources/22%E3%80%81%E7%AD%89%E4%BF%9D%E6%B5%8B%E8%AF%842.0_MySQL%E8%AE%BF%E9%97%AE%E6%8E%A7%E5%88%B6%E7%90%86%E8%A7%A3%E8%A7%A3%E8%AF%BB/039f8bdeb04b47e68c10f889077d22b6_MD5.png)

先不管其中是否存在多余账户，这个账户如果使用的话一般当做超级管理员来用，默认状况下root账户也拥有着所有的全局权限，也不需要对root账户的权限做什么限制。

全局权限存储在user表中，里面有着权限列： 

![](/wikis/_resources/22%E3%80%81%E7%AD%89%E4%BF%9D%E6%B5%8B%E8%AF%842.0_MySQL%E8%AE%BF%E9%97%AE%E6%8E%A7%E5%88%B6%E7%90%86%E8%A7%A3%E8%A7%A3%E8%AF%BB/f8e464df4f90ced86a72f42f47f7ad96_MD5.png)

## **四、测评项b**
b)应重命名或删除默认账户，修改默认账户的默认口令；

默认账户root当然是可以修改用户名的，但是一般数据库和实际业务关联比较深，修改数据库用户的用户名肯定会影响到业务。

所以从实际角度来说，应该是建议修改root的用户名，但不强制要求。

如果没有修改用户名或者禁用账户的话，似乎MySQL安装好后root账户存在一个初始口令（随机生成的）。

无论存不存在初始口令，现在使用的口令应该是强口令，才符合测评要求。

## **五、测评项c**
c)应及时删除或停用多余的、过期的账户，避免共享账户的存在；

默认账户一般就是root账户，这里个人觉得是存在多余账户的：

![](/wikis/_resources/22%E3%80%81%E7%AD%89%E4%BF%9D%E6%B5%8B%E8%AF%842.0_MySQL%E8%AE%BF%E9%97%AE%E6%8E%A7%E5%88%B6%E7%90%86%E8%A7%A3%E8%A7%A3%E8%AF%BB/ab7bdf68822ec0e3d8fe61c0fe7344f8_MD5.png)

在等保测评2.0：MySQL身份鉴别（上）中有说过：

对于MySQL来说，如上文所言，用户的身份标识为username + host，MySQL并没有禁止出现完全一样的username + host行，所以这里是可能出现身份标识不唯一的情况的。 这三个用户的User都是root，虽然Host看上去不一样，实际上也都是本机地址。 127.0.0.1就是本地的ip地址，localhost则是在hosts文件里（linux系统中）和ip地址进行了映射，其实映射的还是127.0.0.1地址，至于::1应该是ipv6格式的本机地址。 ::1这个我不知道要如何才能连上，当用户名为root的行只剩下host值为::1的行的时候，使用用户名root怎么连都不可能连上。 对于127.0.0.1和localhost，在windows系统上没啥区别，登录时其排序是不确定的（对于这种，应该是谁先创建谁在前）。 对于127.0.0.1和localhost，好像在linux上有一点区别：MySQL主机127.0.0.1与localhost区别总结 从正常的业务需求来说，明显这三个用户的身份标识是不唯一的，应该删掉::1和另外一个。 至于非默认账户，可以通过访谈或者权限查询来判断是否为多余账户。

## **六、测评项d**
d)应授予管理用户所需的最小权限，实现管理用户的权限分离；

### **6.1. MySQL的权限结构**
MySQL的权限是有多个层级的，分别是，存储在各个表当中。

分别是：mysql.user表（全局权限）、mysql.db表（数据库权限）、mysql.tables_priv（表权限）、mysql.columns_priv（列权限）。

权限判断过程大概是这样的：

客户端操作核实阶段，当客户端的连接请求被MySQL[服务器](https://cloud.tencent.com/product/cvm?from=20065&from_column=20065)端通过其身份认证后。那么接下来就可以发送数据库的操作命令给服务器端处理，服务器检查用户要执行的操作，在确认权限时，MySQL首先检查user表，如果指定的权限没有在user表中被授权；MySQL将检查db表，db表时下一安全层级，其中的权限限定于数据库层级，在该层级的SELECT权限允许用户查看指定数据库的所有表中的数据；如果在该层级没有找到限定的权限，则MySQL继续检查tables_priv表以及columns_priv表，如果所有权限表都检查完毕，但还是没有找到允许的权限操作，MySQL将返回错误信息，用户请求的操作不能执行，操作失败。其过程大概如下图： 

![](/wikis/_resources/22%E3%80%81%E7%AD%89%E4%BF%9D%E6%B5%8B%E8%AF%842.0_MySQL%E8%AE%BF%E9%97%AE%E6%8E%A7%E5%88%B6%E7%90%86%E8%A7%A3%E8%A7%A3%E8%AF%BB/74362c3dc189e5fc3ea0615718098252_MD5.png)

查询某用户的权限的话，可以去上述几个权限表中查看数据。

也可以使用show grants for ‘xx’@’xx’语句，这个语句应该会把某用户在这些表中的权限全部列出来：



```javascript
+---------------------------------------------------------------------------------------------+| Grants for dba@localhost                                                                    |
+---------------------------------------------------------------------------------------------+| GRANT RELOAD, SUPER, REPLICATION CLIENT ON *.* TO 'dba'@'localhost'                         |
| GRANT CREATE TEMPORARY TABLES ON `mysql`.* TO 'dba'@'localhost'                             |
|---|
| GRANT SELECT, INSERT, UPDATE, CREATE, DROP ON `mysql`.`backup_history` TO 'dba'@'localhost' |
| GRANT INSERT, UPDATE, CREATE, DROP ON `mysql`.`ibbackup_binlog_maker` TO 'dba'@'localhost'  |
| GRANT INSERT, UPDATE, CREATE, DROP ON `mysql`.`backup_progress` TO 'dba'@'localhost'        |
+---------------------------------------------------------------------------------------------+
```

其中第一行是全局权限，第二行是mysql数据库的权限，第三、四行则是表一级的权限。

两种查询方法如下图： 

![](/wikis/_resources/22%E3%80%81%E7%AD%89%E4%BF%9D%E6%B5%8B%E8%AF%842.0_MySQL%E8%AE%BF%E9%97%AE%E6%8E%A7%E5%88%B6%E7%90%86%E8%A7%A3%E8%A7%A3%E8%AF%BB/c0ac3e0d0405454b30b95fd9a0f894a2_MD5.png)

### **6.2. 测评项要求**
那么怎么才算是符合呢？应该要根据应用程序业务复杂程度来判断，应用程序业务越复杂或者越庞大，则数据库账户的权限就应该划分得越细致。

反正，一个root账户从头用到尾，那肯定是不符合的。

其余的内容，可以参考下初级教程： 

![](/wikis/_resources/22%E3%80%81%E7%AD%89%E4%BF%9D%E6%B5%8B%E8%AF%842.0_MySQL%E8%AE%BF%E9%97%AE%E6%8E%A7%E5%88%B6%E7%90%86%E8%A7%A3%E8%A7%A3%E8%AF%BB/70f7047fa9ca0a5e13d072b80c279564_MD5.png)

## **七、测评项e**
e)应由授权主体配置访问控制策略，访问控制策略规定主体对客体的访问规则；

授权主体在数据库中也就是拥有设置用户权限的账户，也就是查看user表、db表中的grant_priv字段。

赋予用户权限的时候，加上With Grant Option，即该用户则拥有了将获得的权限再赋予其它人的权限（其实就是同时修改了grant_priv字段）：

比如



```javascript
mysql>grant all on *.* to test@’192.168.1.20’ identified by ‘123456’ WITH GRANT OPTION
mysql>flush privileges;
结果显示：Grant_priv为"Y"
```

对于测评项而言，也就看数据库内是否设置了此类账户，由此类账户（安全管理员）来制定访问控制策略。

## **八、测评项f**
f)访问控制的粒度应达到主体为用户级或进程级，客体为文件、数据库表级；

就是看权限控制粒度，对于客体，要看是否达到了数据库表的级别，也即单独对数据库表设置权限（视图、存储过程也可以）。如果仅达到了数据库级别或者服务器级别的权限，那肯定是不符合要求的。

至于主体就不说了，MySQL中也没存在用户组。

## **九、测评项g**
g)应对重要主体和客体设置安全标记，并控制主体对有安全标记信息资源的访问。

MySQL自身应该不具备这个功能，可能要依靠操作系统或者第三方的什么软件来实现了。
