MySQL安全配置规范

3.1.1  基线目标

通过在系统生命周期不同阶段对目标系统展开各类安全检查,找出不符合基线定义的安全配置项并选择和实施安全措施来控制安全风险,并通过对历史数据的分析获得系统安全状态和变化趋势。

3.1.2  适用版本

本安全基线的适用版本为:MySQL 5.7 Community Server 社区版本。

3.1.3  基本安全配置 

3.1.4.1  修改root用户名

名称

修改root用户名

说明

MySQL默认用户root应该修改名称,以减小攻击面。

问题影响

防止黑客针对用户名进行密码猜测攻击。

检查方法

执行sql检查数据库是否有默认用户root:

mysql> SELECT user from mysql.user where user=’root’;

如果有返回行则需要修改

参考值

Empty set (0.00 sec)

实施步骤

mysql> update user set user=’newname’ where user=’oldname’;

mysql> flush privileges;

3.1.4.2  MySQL操作系统账号权限最小化

名称

MySQL操作系统账号权限最小化

说明

MySQL在操作系统上的账号权限最小化有助于减小MySQL数据库漏洞造成的影响。

问题影响

防止黑客利用MySQL漏洞入侵操作系统,造成更大损失。

检查方法

假设MySQL账号为mysql,执行命令

ps -ef | egrep “^mysql.*$”

如果没有返回行,则权限存在问题

参考值

存在返回行

实施步骤

创建一个仅用于运行MySQL和直接相关进程的用户

回退方案

3.1.4.3  禁止MySQL链接历史记录

名称

禁止MySQL链接历史记录

说明

MySQL会把客户端登陆的交互执行记录保存在.mysql_history文件中。

问题影响

该记录有可能会暴露登陆过程中的敏感信息。建议删除该记录

检查方法

检查.mysql_history文件是否存在(默认在home下):

find /home -name “.mysql_history”

如果有返回行说明存在.mysql_history文件,建议删除。

参考值

无返回行

实施步骤

1. 如果存在.mysql_history,则删除

rm –f . mysql_history

2. 创建链接,防止.mysql_history再次生成

ln -s /dev/null $HOME/.mysql_history

或采用修改mysql_history的环境变量让他的值等于 /dev/null

3.1.4.4  禁止MySQL操作系统账号登陆

名称

禁止MySQL操作系统账号登陆

说明

MySQL做系统账号在安装完数据库后,不应该有其他用途。建议禁止该账号登陆操作系统。

问题影响

此举在防止黑客利用MySQL数据库漏洞反射shell有极佳效果。

检查方法

假设MySQL数据库操作系统账号就是mysql,执行下列命令:

getent passwd mysql | egrep “^.*[ \ /bin\ / false| \ / sbin \ / nologin]$”

如果没有返回行则说明存在安全隐患。

参考值

实施步骤

执行下列语句禁止mysql登陆:

usermod -s /sbin/nologin mysql

回退步骤

usermod -s /bin/bash mysql

3.1.4.5  更改MySQL默认端口

名称

更改MySQL默认端口

说明

使用默认端口,会更容易被黑客在网络中发现数据库

问题影响

改成其他端口有助于隐藏数据库,防止被黑客入侵。

检查方法

show global variables like ‘port’;

如果返回是3306,则说明需要修改端口

参考值

除3306以外的任何端口

实施步骤

1. 修改配置文件vi /etc/my.cnf,添加以下安全参数

port=XXXX (除3306以外的任何端口)

2. 重启mysql服务

systemctl restart mysqld

回退步骤

修改配置前使用以下命令备份配置文件

cp /etc/my.cnf /etc/my.cnf.bak

回退操作:

cp /etc/my.cnf.bak /etc/my.cnf

3.1.4  文件系统权限

3.1.5.1  log-bin二进制日志

名称

log-bin二进制日志

说明

log-bin就是binary log,二进制日志文件,这个文件记录了mysql所有的dml操作。

问题影响

限制二进制日志文件的权限将有益于保护数据信息不泄露,或被恶意修改。

检查方法

1. 执行sql查看log-bin日志文件状态及相关配置

    mysql> show variables like ‘log_bin%’;

2. 检查日志文件的权限是660并且属于mysql:mysql

参考值

log_bin=ON

log_bin_basename=/var/lib/mysql/mysql-bin

log_bin_index=/var/lib/mysql/mysql-bin.index

文件权限=660

文件所属mysql:mysql

实施步骤

1. 修改配置文件vi /etc/my.cnf,添加以下安全参数

log_bin= /var/lib/mysql/mysql-bin   // 5.7默认未开启binlog

server-id=1 //随机指定不和其他集群中机器重名的字符串,如果只有一台机器,那就可以随便指定了。

2. 重启mysql服务

systemctl restart mysqld

3. chmod 660 <file_name>

chown mysql:mysql <file_name>

回退步骤

将文件权限还原为之前的权限

备注

备注:自动设置log_bin_index文件为你指定的文件名后跟.index

5.7版本若不添加server-id,重启mysql服务会报错

8.0版本默认情况下已开启binlog,文件权限为640,所属mysql:mysql

3.1.5.2  log-err错误日志

名称

log-err错误日志

说明

错误日志记录了MySQL Server每次启动和关闭的详细信息以及运行过程中所有较为严重的警告和错误信息

问题影响

限制日志文件的权限将有益于保护数据信息不泄露,或被恶意修改。

检查方法

1. 执行sql查看log-err日志文件状态及相关配置

mysql> show global variables like ‘log_error’;

2. 检查日志文件的权限是660并且属于mysql:mysql

参考值

log_error=/var/log/mysqld.log //默认开启log_error,默认径/var/log/mysqld.log

文件权限=660

文件所属mysql:mysql

实施步骤

chmod 660 <file_name>

chown mysql:mysql <file_name>

回退步骤

将文件权限还原为之前的权限

3.1.5.3  log-slow-queries慢查询日志

名称

log-slow-queries慢查询日志

说明

它用来记录在MySQL中响应时间超过阀值(long_query_time)的语句

问题影响

限制日志文件的权限将有益于保护数据信息不泄露,或被恶意修改。

检查方法

1. 执行sql查看log-slow-queries慢查询日志文件状态及相关配置

mysql> show variables like ‘%slow_query_log_file%’;

2. 检查日志文件的权限是660并且属于mysql:mysql

参考值

slow_query_log=ON //默认为OFF

log-slow-queries= /var/lib/mysql/localhost-slow.log //默认路径

文件权限=660

文件所属mysql:mysql

实施步骤

1. 执行SQL语句:mysql> set global slow_query_log = on; //开启慢查询日志

2. chmod 660 <file_name>

3. chown mysql:mysql <file_name>

回退步骤

将文件权限还原为之前的权限

3.1.5.4  relay-log中继日志

名称

relay-log中继日志

说明

MySQL进行主主复制或主从复制的时候会在home目录下面产生相应的relay log

问题影响

限制日志文件的权限将有益于保护数据信息不泄露,或被恶意修改。

检查方法

1. 执行sql查看中继日志文件状态及相关配置

mysql> show variables like ‘relay_log_basename’;

2. 检查日志文件的权限是660并且属于mysql:mysql

参考值

relay_log_basename = /var/lib/mysql/localhost-relay-bin //默认路径

文件权限=660

文件所属mysql:mysql

实施步骤

chmod 660 <file_name>

chown mysql:mysql <file_name>

回退步骤

将文件权限还原为之前的权限

3.1.5.5  general query log查询日志

名称

查询日志

说明

记录建立的客户端连接和执行的语句。

问题影响

限制日志文件的权限将有益于保护数据信息不泄露,或被恶意修改。

检查方法

1. 执行sql查看查询日志文件状态及相关配置

mysql> show variables like ‘%general_log%’;

2. 检查日志文件的权限是660并且属于mysql:mysql

参考值

general_log=on //默认为off

general_log_file = /var/lib/mysql/localhost.log //默认关闭,文件名为主名.log

文件权限=660

文件所属mysql:mysql

实施步骤

1. 执行SQL语句:mysql> set global general_log = on; //开启慢查询日志

2. chmod 660 <file_name>

chown mysql:mysql <file_name>

回退步骤

将文件权限还原为之前的权限

3.1.5  日志审计

3.1.6.1  确保log_raw被设置成off

名称

确保log_raw被设置成off

说明

语句中的密码在写入一般查询日志时会被服务器重写,不会以明文方式记录。

问题影响

如果log-raw被设置成ture,则会记成明文。

检查方法

打开数据库配置文件 /etc/my.cnf,确定log_raw被设置成off

如果是off是安全的,但如果是on则需要修复

参考值

log_raw=OFF

实施步骤

1. 修改配置文件vi /etc/my.cnf,添加以下安全参数

log_raw=OFF

2. 重启mysql服务

systemctl restart mysqld

回退步骤

修改配置前使用以下命令备份配置文件

cp /etc/my.cnf /etc/my.cnf.bak

回退操作:

cp /etc/my.cnf.bak /etc/my.cnf

3.1.6.2  确保log_warnings被设置成2

名称

确保log_warnings被设置成2

说明

log_warnings适用于决定日志中记录的内容的。

问题影响

随着级别的调整会记录更多信息,调整到2有助于通过日志追查安全问题。

检查方法

mysql> SHOW GLOBAL VARIABLES LIKE ‘log_warnings’;

如果返回值是1需要调整到2

参考值

log_warning=2 //默认为2

实施步骤

1. 修改配置文件vi /etc/my.cnf,添加以下安全参数

log_warning=2

2. 重启mysql服务

systemctl restart mysqld

回退步骤

修改配置前使用以下命令备份配置文件

cp /etc/my.cnf /etc/my.cnf.bak

回退操作:

cp /etc/my.cnf.bak /etc/my.cnf

备注

MySQL 8.0新特性:

log_warnings 参数调整为log_error_verbosity

3.1.6  MySQL权限安全

3.1.7.1  确保只有管理员账号有所有数据库的访问权限

名称

确保只有管理员账号有所有数据库的访问权限

说明

除了管理员账号,其他用户没必要有所有数据库的访问权限。

问题影响

过高的权限会导致安全问题。

检查方法

mysql> SELECT user, host FROM mysql.user WHERE (Select_priv = ‘Y’) OR (Insert_priv = ‘Y’) OR (Update_priv = ‘Y’) OR (Delete_priv = ‘Y’) OR (Create_priv = ‘Y’) OR (Drop_priv = ‘Y’);

如果返回的都是管理员账号说明安全,否则需要对用户清除权限

参考值

返回的都是管理员账号

实施步骤

清除非管理员账号的过高部分权限

3.1.7.2  非管理员账号File_priv不应该设置成Y

名称

非管理员账号File_priv不应该设置成Y

说明

File_priv权限允许MySQL用户对磁盘进行读写操作

问题影响

黑客很可能利用这一点盗取数据库中敏感数据。

检查方法

mysql> select user, host from mysql.user where File_priv = ‘Y’;

如果返回的都是管理员账号说明安全,否则需要对用户清除权限

参考值

返回的都是管理员账号

实施步骤

mysql> REVOKE FILE ON *.* FROM ‘<user>’; //<user>为需要撤销权限的用户

回退步骤

mysql> GRANT FILE ON *.* TO user@localhost; //<user>为需要增加权限的用户

3.1.7.3  非管理员账号Process_priv不应该设置成Y

名称

非管理员账号Process_priv不应该设置成Y

说明

Process_priv权限允许委托账号查看当前正在执行的sql语句

问题影响

使用超越当前用户权限的权利。可以被攻击者所利用。

检查方法

mysql> select user, host from mysql.user where Process_priv = ‘Y’;

如果返回的都是管理员账号说明安全,否则需要对用户清除权限

参考值

返回的都是管理员账号

实施步骤

mysql> REVOKE PROCESS ON *.* FROM ‘<user>’; //<user>为需要撤销权限的用户

回退步骤

mysql> GRANT PROCESS ON *.* TO user@localhost; //user为需要增加权限的用户

3.1.7.4  非管理员账号Super_priv不应该设置成Y

名称

非管理员账号Super_priv不应该设置成Y

说明

super_priv权限允许委托账号执行任意语句,非管理员不应该具备该权限。

问题影响

使用超越当前用户权限的权利。可以被攻击者所利用。

检查方法

mysql> select user, host from mysql.user where Super_priv = ‘Y’;

如果返回的都是管理员账号说明安全,否则需要对用户清除权限

参考值

返回的都是管理员账号

实施步骤

mysql> REVOKE SUPER ON *.* FROM ‘<user>’; //<user>为需要撤销权限的用户

回退步骤

mysql> GRANT SUPER ON *.* TO user@localhost; //user为需要增加权限的用户

备注

‘mysql.session‘@’localhost’:

插件内部使用来访问服务器。该用户已被锁定,客户端无法连接。

3.1.7.5  非管理员账号Create_user_priv不应该设置成Y

名称

非管理员账号Create_user_priv不应该设置成Y

说明

Create_user_priv权限允许委托账号创建任意用户,会造成一定安全隐患。

问题影响

使用超越当前用户权限的权利。可以被攻击者所利用。

检查方法

mysql> select user, host from mysql.user where Create_user_priv = ‘Y’;

如果返回的都是管理员账号说明安全,否则需要对用户清除权限

参考值

返回的都是管理员账号

实施步骤

mysql> REVOKE CREATE USER ON *.* FROM ‘<user>’; //<user>为需要撤销权限的用户

回退步骤

mysql> GRANT CREATE USER ON *.* TO user@localhost; //user为需要增加权限的用户

3.1.7.6  非管理员账号Grant_priv不应该设置成Y

名称

非管理员账号Grant_priv不应该设置成Y

说明

Grant_priv权限允许委托账号对其他用户赋权,可能会被黑客利用造成一定安全隐患。

问题影响

使用超越当前用户权限的权利。可以被攻击者所利用。

检查方法

mysql> select user, host from mysql.user where Grant_priv= ‘Y’;

如果返回的都是管理员账号说明安全,否则需要对用户清除权限

参考值

返回的都是管理员账号

实施步骤

mysql> REVOKE GRANT ON *.* FROM ‘<user>’; //<user>为需要撤销权限的用户

回退步骤

mysql> GRANT GRANT ON *.* TO user@localhost; //user为需要增加权限的用户

3.1.7.7  非管理员账号Reload_priv不应该设置成Y

名称

非管理员账号Reload_priv不应该设置成Y

说明

Reload_priv权限可以对本地文件进行操作,可能会被黑客利用造成一定安全隐患

问题影响

使用超越当前用户权限的权利。可以被攻击者所利用。

检查方法

mysql> select user, host from mysql.user where Reload_priv= ‘Y’;

如果返回的都是管理员账号说明安全,否则需要对用户清除权限

参考值

返回的都是管理员账号

实施步骤

mysql> REVOKE RELOAD ON *.* FROM ‘<user>’; //<user>为需要撤销权限的用户

回退步骤

mysql> GRANT RELOAD ON *.* TO user@localhost; //user为需要增加权限的用户

3.1.7  口令策略

3.1.8.1  口令复杂度

名称

口令复杂度设置

说明

口令应符合口令策略,要求包含数字、字符、大小写和特殊字符,且长度大于等于8位

问题影响

弱口令容易被恶意攻击者爆破,导致口令被猜解

检查方法

通过msyql环境变量可以查看密码策略的相关参数

mysql> show variables like ‘%password%’;

参考值

validate_password.policy=MEDIUM //密码策略,默认为MEDIUM策略

validate_password.length=8 //密码最少长度为8位

validate_password.mixed_case_count=1 //大小写字符长度,至少1个

validate_password.number_count=1 //数字至少1个

validate_password.pecial_char_count=1 //特殊字符至少1个

实施步骤

1. 修改配置文件vi /etc/my.cnf,添加安全参数

[mysqld]

plugin-load=validate_password.so

validate_password.policy=1 //密码强度检查级别为MEDIUM

validate-password=FORCE_PLUS_PERMANENT //永久强制使用插件,为阻止该插件在运行时被删除

2. 重启mysql服务

systemctl restart mysqld

回退方案

修改配置前使用以下命令备份配置文件

cp /etc/my.cnf /etc/my.cnf.bak

回退操作:

cp /etc/my.cnf.bak /etc/my.cnf

或 validate_password = off

备注

mysql5.7默认安装了密码安全检查插件(validate_password),默认密码检查策略要求密码必须包含:大小写字母、数字和特殊符号,并且长度不能少于8位。否则会提示ERROR 1819 (HY000): Your password does not satisfy the current policy requirements错误

3.1.8.2  口令生存周期

名称

口令生存周期设置(因数据库可用性要求高,不强制启用)

描述

推荐口令最长不超过3个月更改一次口令

问题影响

密码永不过期,无法保证口令的安全性

检查方法

1. 查看全局密码过期的参数设定

mysql> show variables like ‘default_password_lifetime’;

在5.7.11版本后都已经把默认值从360变成了0也就是永不过期了;

2. 查看未设定密码过期策略的用户

select user,host,password_lifetime,password_last_changed,password_expired from mysql.user;

参考值

default_password_lifetime=90 //密码90天过期

实施步骤

l 全局参数设定(因数据库可用性要求高,不强制启用):

1. 修改配置文件vi /etc/my.cnf,添加安全参数

[mysqld]

default_password_lifetime=90

2. 重启mysql服务

systemctl restart mysqld

l 特定用户口令过期设定

mysql> ALTER USER ‘XXXX’@’localhost’ PASSWORD EXPIRE INTERVAL 90 DAY;

回退方案

l 全局设定:

修改配置前使用以下命令备份配置文件

cp /etc/my.cnf /etc/my.cnf.bak

回退操作:

cp /etc/my.cnf.bak /etc/my.cnf

l 特定用户口令过期设定

mysql> ALTER USER ‘XXXX’@’localhost’ PASSWORD EXPIRE DEFAULT;

3.1.8.3  确保无空口令用户

名称

确认无空口令用户

问题影响

如果密码被设置成空密码,入侵者只要知道密码和主机允许列表,就可以绕过身份验证随意登录数据库,进行违规操作。

检查方法

mysql> SELECT User,host FROM mysql.user WHERE authentication_string=”;

没有行数返回说明安全,否则需要配置

参考值

实施步骤

mysql> SET PASSWORD FOR ‘user’@’host’ = PASSWORD(“XXXXXXX”);

3.1.8.4  确保无匿名账户

名称

确认无匿名账户

问题影响

匿名用户是空的,也没有密码。安全性很差,任意人员都可以利用匿名用户访问数据库。

检查方法

mysql> SELECT user,host FROM mysql.user WHERE user = ”;

没有行数返回说明安全,否则需要修复

参考值

Empty set (0.00 sec)

实施步骤

删除匿名用户

3.1.8.5  确保用户不允许所有ip访问

名称

确保用户不允许所有ip访问

问题影响

某一数据库用户支持所有ip访问,一旦账号密码泄露,数据库就变得很不安全

检查方法

mysql> SELECT user, host FROM mysql.user WHERE host = ‘%’;

结果集为空说明不存在问题,否则需要修复

参考值

实施步骤

删除匿名用户