等保三级:mysql数据库加固思路
本文采用Mysql8.0.31进行加固,具体命令与Mysql5.x版本命令存在差异,但思路无差,可进行参考。
文章目录
常规操作
create user 'root'@'%' identified by '********'; //创建用户
alter user 'root'@'%' identified with mysql_native_password by '********'; //修改密码
rename user 'root'@'%' to 'root'@'192.168.1.1'; //重命名
flush privileges; //刷新权限
grant all privileges on *.* to 'root'@'192.168.1.%'; //赋予权限
revoke all privileges on *.* to 'root'@'%'; //收回权限
select current_user(); //查看当前登录的用户
select current_role(); //查看当前登录的角色
mysqldump -uroot -p mysql>mysql.sql //导出mysql数据库
create database xiaozhou_db; //创建xiaozhou数据库
show databases; //展示所有数据库
drop database xiaohzou_db; //删除数据库
alter user 'root'@'localhost' identified with mysql_native_password by 'xlpszqdbb'; //修改密码
show variables like 'port'; //查看端口
一、身份鉴别
a) 测评内容
应对登录的用户进行身份标识和鉴别,身份标识具有唯一性,身份鉴别信息具有复杂度要求并定期更换
要求:建议身份密码登录,身份标识具有唯一性,身份鉴别信息具有复杂度要求,密码长度最少为8位,密码由数字、字母大小写、特殊符号组成、并设置定期更换,更换时间最长位90天。
1.查看所有用户:
select user,host from mysql.user;
示例如下:
2.查看密码复杂度插件:
select * from mysql.`plugin`;
示例如下:
查看mysql的插件,发现mysql8.0 并没有校验插件,然后查看插件包,发现有这个插件,则对该插件进行安装。
命令如下:
install plugin validate_password soname 'validate_password.so';
3.卸载默认密码复杂度插件
auth_socket.so插件为测试环境,顾我们将其卸载
命令如下:
uninstall plugin auth_socket.so;
4.密码复杂度插件配置
show variables like 'validate%';
+--------------------------------------+--------+
| Variable_name | Value |
+--------------------------------------+--------+
| validate_password_check_user_name | ON |
| validate_password_dictionary_file | |
| validate_password_length | 8 |
| validate_password_mixed_case_count | 1 |
| validate_password_number_count | 1 |
| validate_password_policy | MEDIUM |
| validate_password_special_char_count | 1 |
+--------------------------------------+--------+
- validate_password_check_user_name,ON为打开
- validate_password_dictionary_file用于配置密码的字典文件,当validate_password_policy设置为STRONG时可以配置密码字典文件,字典文件中存在的密码不得使用
- validate_password_length用来设置密码的最小长度,默认值是8最小是0
- validate_password_mixed_case_count当validate_password_policy设置为MEDIUM或者STRONG时,密码中至少同时拥有的小写和大写字母的数量,默认是1最小是0;默认是至少拥有一个小写和一个大写字母。
- validate_password_number_count当validate_password_policy设置为MEDIUM或者STRONG时,密码中至少拥有的数字的个数,默认1最小是0
- validate_password_special_char_count当validate_password_policy设置为MEDIUM或者STRONG时,密码中至少拥有的特殊字符的个数,默认1最小是0
5.密码有效期配置
show global variables like 'default_password_lifetime';
修改命令为:
set global default_password_lifetime = 90;
查看user表的几个关键字段:它们的单位都是天,当password_lifetime 为null时,则代表该用户当前口令的有效期是使用的全局变量,而default_password_lifetime 为0代表有效期永远。
查看密码有效期状态:
select user,host,password_lifetime,password_last_changed from mysql.user;
b) 测评内容
应具有登录失败处理功能,应配置并启用结束会话、限制非法登录次数和当登录连接超时自动退出等相关措施
要求:建议数据库配置登录失败处理功能,应配置并启用结束会话、限制非法登录次数和当登录连接超时自动退出等相关措施,可采取登录失败五次锁定三十分钟;登陆超时设置为30分钟自动退出。
1.查看失败锁定策略:
show variables like "%connection_control%";
空表表示未安装插件,故我们进行插件安装
install plugin connection_control soname "connection_control.so";
install plugin connection_control_failed_login_attempts soname 'connection_control.so';
查看插件状态:
select plugin_name,plugin_status from INFORMATION_SCHEMA.PLUGINS where PLUGIN_NAME LIKE 'connection%';
再次对策略进行查询,发现以下情况
mysql> show variables like "%connection_control%";
+-------------------------------------------------+------------+
| Variable_name | Value |
+-------------------------------------------------+------------+
| connection_control_failed_connections_threshold | 3 |
| connection_control_max_connection_delay | 2147483647 |
| connection_control_min_connection_delay | 1000 |
+-------------------------------------------------+------------+
3 rows in set (0.00 sec)
加固命令:
set global connection_control_failed_connections_threshold = 5;
set global connection_control_max_connection_delay = 1800000;
set global connection_control_min_connection_delay = 1800000;
connection_control_failed_connections_threshold:在服务器增加后续连接尝试的延迟之前,允许客户端进行的连续失败连接尝试的次数。
connection_control_min_connection_delay:对于超出阈值的每个连续连接失败,要添加的延迟量。
connection_control_max_connection_delay:要添加的最大延迟。
2.查看连接超时退出策略
命令如下:
show global variables like '%timeout';
匹配如下:
mysql> show global variables like '%timeout';
+-----------------------------------+----------+
| Variable_name | Value |
+-----------------------------------+----------+
| connect_timeout | 10 |
| delayed_insert_timeout | 300 |
| have_statement_timeout | YES |
| innodb_flush_log_at_timeout | 1 |
| innodb_lock_wait_timeout | 50 |
| innodb_rollback_on_timeout | OFF |
| interactive_timeout | 28800 |
| lock_wait_timeout | 31536000 |
| mysqlx_connect_timeout | 30 |
| mysqlx_idle_worker_thread_timeout | 60 |
| mysqlx_interactive_timeout | 28800 |
| mysqlx_port_open_timeout | 0 |
| mysqlx_read_timeout | 30 |
| mysqlx_wait_timeout | 28800 |
| mysqlx_write_timeout | 60 |
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| replica_net_timeout | 60 |
| rpl_stop_replica_timeout | 31536000 |
| rpl_stop_slave_timeout | 31536000 |
| slave_net_timeout | 60 |
| ssl_session_cache_timeout | 300 |
| wait_timeout | 28800 |
+-----------------------------------+----------+
23 rows in set (0.00 sec)
我们查看的参数是这三个:
- wait_timeout
- interactive_timeout
- connect_timeout
加固命令如下:
set global wait_timeout=1800;
set global interactive_timeout=1800;
set global connect_timeout=10;
c) 测评内容
当进行远程管理时,应采取必要措施防止鉴别信息在网络传输过程中被窃听;
要求:建议远程管理数据库时建议使用堡垒机+ssh防止鉴别信息在网络传输过程中被窃听
1.查询ssl是否开启
show variables like "%ssl%";
yes是开启了ssl,disable则表示没有
2.开启ssl加密传输
set global have_openssl=yes;
set global have_ssl=yes;
会发现报以下错误:
mysql> set global have_openssl=yes;
ERROR 1238 (HY000): Variable 'have_openssl' is a read only variable
mysql> set global have_ssl=yes;
ERROR 1238 (HY000): Variable 'have_ssl' is a read only variable
大概意思就是ssl你改不了,只有读的权限。因为在MySQL8.0中ssl是默认开启的。如果没开启的也不要惊慌,我们往下看。
3.查询是否使用ssl
这里先和大家普及一下,ssl中,并不是开启了ssl加密传输就一定使用了加密传输,绝大多数情况下是要进行配置,所以我们还需要看ssl证书是否使用
status
这里可以看到,ssl证书是没有使用的,或者是根本就没有ssl证书。
4.生成ssl证书
我们退出数据库,我用的是Linux,所以到Linux命令行界面进行操作
mysql_ssl_rsa_setup
或者是
mysqld_ssl_rsa_setup
#具体要看Linux版本
因为我不清楚数据库安装位置,故我用命令找数据库在哪
find ./ -name "mysql_ssl_rsa_setup"
find ./ -name "mysqld_ssl_rsa_setup"
使用命令执行该文件,因为我的数据库是默认有证书文件,所以执行时没有返回值
接再来还要找证书位置,同样的,用命令找
find ./ -name "*.pem"
./var/lib/mysql/private_key.pem #私钥/公钥对的私有成员
./var/lib/mysql/ca.pem #自签的CA证书,客户端连接也需要提供
./var/lib/mysql/server-cert.pem #服务器端证书文件
./var/lib/mysql/client-cert.pem #客户端连接服务器端需要提供的证书文件
./var/lib/mysql/client-key.pem #客户端连接服务器端需要提供的私钥文件
./var/lib/mysql/public_key.pem #私钥/公钥对的共有成员
./var/lib/mysql/server-key.pem #服务器端私钥文件
./var/lib/mysql/ca-key.pem #CA私钥
5.配置ssl证书
修改mysql配置文件,找到my.cnf
添加以下配置
[mysqld]
ssl-ca=/var/lib/mysql/ca.pem
ssl-cert=/var/lib/mysql/server-cert.pem
ssl-key=/var/lib/mysql/server-key.pem
[mysql]
ssl-ca=/var/lib/mysql/ca.pem
ssl-cert=/var/lib/mysql/client-cert.pem
ssl-key=/var/lib/mysql/client-key.pem
然后重启数据库,然后再登录数据库查看
d) 测评内容
应采用口令、密码技术、生物技术等两种或两种以上组合的鉴别技术对用户进行身份鉴别,且其中一种鉴别技术至少应使用密码技术来实现
要求:建议远程管理数据库时建议使用堡垒机+ssh防止鉴别信息在网络传输过程中被窃听
1.通过加入堡垒机进行统一管控
(1)创建两个测试用户
一个测试用户为密码登录,一个为密码+ssl证书登录
create user 'test'@'%' identified by 'Test@123';
create user 'testssl'@'%' identified by 'Test@123' require ssl;
(2)分别用两个测试用户进行登录
因为我们上面在服务器中加入了以下参数,故用服务器登录ssl账户进行测试是可以输密码直接进入的,所以我们用远程工具进行连接
可以看出,密码是输入对了,但是mysql服务端拒绝连接,这时候我们需要把密钥加到客户端中
测试账户记得删掉哦,这样子做也是有弊端的,就是创建的每一个用户都要用ssl创建,基本上是很难做到的,所以我还是建议使用堡垒机进行登录
二、访问控制
a) 测评内容
应对登录的用户分配账户和权限;
要求:建议对登录用户由管理员分配账户和权限。 也就是必须要分成几个角色,这个放后面一起测评项d一起来做。
b) 测评内容
应重命名或删除默认账户,修改默认账户的默认口令
要求:应重命名或删除默认账户,修改默认账户的默认口令
c) 测评内容
应及时删除或停用多余的、过期的账户,避免共享账户的存在;
要求:建议删除或停用多余的、过期的账户,避免共享账户的存在;根据需要创建每个人员对应的账户。
d) 测评内容
应授予管理用户所需的最小权限,实现管理用户的权限分离;
要求:建议建立、操作员、审计员、安全管理员等角色,安全管理为制定安全策略人员、操作员为日常操作用户、审计员只需具有审计日志查看权限;实现用户所需权限最小化,和管理用户权限分离。
1.创建3个角色:
- 操作员:负责业务层面开发,对应我们开发人员。
- 审计员:只需对日志具有审查权限
- 管理员:拥有所有的权限,制定安全策略。
create role 'System_db','Security_db','Audit_db';
2.给3个角色分配权限:
grant all privileges on *.* to 'System_db'@'%' with grant option;
grant reload,process,Alter,Create User,Create View,select,show databases,show view,update,file on *.* to 'Security_db'
@'%';
grant reload,process,insert,select,show,create view,alter,insert,show database,show view, on *.* to 'Audit_db'@'%';
mysql> GRANT ALL privileges on *.* to 'System_db'@'%' with grant option;
Query OK, 0 rows affected (0.01 sec)
mysql> grant reload,process,Alter,Create User,Create View,select,show databases,show view,update,file on *.* to 'Securit
y_db'@'%';
Query OK, 0 rows affected (0.01 sec)
mysql> grant reload,process,Alter,Create User,Create View,select,show databases,show view,update,file on *.* to 'Audit_d
b'@'%';
Query OK, 0 rows affected (0.00 sec)
3.创建管理员用户
create user 'System'@'%' identified by 'System@123';
create user 'Security'@'%' identified by 'Security@123';
create user 'Audit'@'%' identified by 'Audit@123';
4.将用户加入到角色中
grant 'System_db' to 'System'@'%';
grant 'Security_db' to 'Security'@'%';
grant 'Audit_db' to 'Audit'@'%';
5.激活各个角色
set global activate_all_roles_on_login=on;
- 需要注意的是,角色创建后,并不会直接激活,激活的方式有几种,但推荐的一种就是去配置文件配置参数。
- 当用户登录后,可以查看该角色是否存在。查看参数是off状态。更改位on,该角色在登录后就会被自动激活。
三、安全审计
a) 测评内容
应启用安全审计功能,审计覆盖到每个用户,对重要的用户行为和重要安全事件进行审计
要求:建议数据库开启安全审计功能,审计覆盖到每个用户,对重要的用户行为和重要安全事件进行审计;
方法一:
1.查看审计开启情况
show global variables like 'log_timestamps';
show global variables like '%general%';
show global variables like '%log_bin%';
show global variables like '%log_error%';
show global variables like '%slow_query_log%';
- log_timestamps表示记录审计日志的时间是从哪里获取。UTC是全球时间,system是系统当前时间,一般我们用当前时间
- general_log表示审计功能是否开启
- general_log_file表示审计信息的日志文件
- log_bin表示二进制日志
- log_bin_basename二进制日志的日志文件
- log_error表示错误日志
- slow_query_log表示慢日志
- slow_query_log_file表示慢日志的日志文件
2.开启审计功能
set global log_timestamps = SYSTEM;
set global general_log = ON;
set global general_log_file = /var/lib/mysql/general.log;
set global slow_query_log = ON;
set global slow_query_log_file = /var/lib/mysql/slow_query.log;
我这因为服务器权限问题,不能命令直接改审计文件,需要到配置文件中改。
同样的,上述命令只能进行临时更改,当重启数据库后将会恢复默认,所以我们采用直接改配置文件的方式,但是直接改配置文件需要重启数据库
3.查看审计文件
cat /var/lib/mysql/general.log
cat /var/lib/mysql/binlog
cat /var/lib/mysql/error.log
cat /var/lib/mysql/slow_query.log
方法二:
BinLog+Init_connect
BinLog是MySQL操作时留下的日志,BinLog一方面可以用在数据库的恢复与主从复制上,另外一方面可以用来做数据库的审计。
由于BinLog日志里面无法查询是谁在哪个时间段登录的等信息,缺少审计必要的信息。在MySQL中,每个连接都会先执行init_connect进行连接的初始化,我们可以在这里获取用户的登录名称和thread ID值。然后配合BinLog,就可以追踪到每个操作语句的操作时间,操作人等信息,再加上BinLog的日志信息实现审计。
1.创建审计用的数据库和表
我们可以单独创建审计的表和库,同时也可对表和库进行加密,具体算法看个人喜好,一般MD5和Base64不推荐。
create database auditdb;
use auditdb;
create table accesslog(
id int primary key auto_increment,
connectionid int,
connectionuser varchar(30),
logintime datetime
);
2.给用户添加这个库的权限
grant all privileges on auditdb.* to '用户' identified by '密码';
insert into mysql.db (Host,Db,user,insert_priv) values ('%','auditdb','','Y') ;
flush privileges;
3.把这一方式加入到配置文件中
log-bin=mysql-bin
#开启Binlog
init_connect='insert into auditdb.accesslog(connectionid, connectionuser,logintime) values(connection_id(),user(),now());'
#设置初始化连接参数
4.查看二进制日志
show master status;
show master logs;
方法三:
1.下载MariaDB Audit Plugin插件
(下载地址:https://mariadb.org/download/)
可以通过下载安装包,到安装包里面找到server_audit.so插件
也可以通过这个链接直接下载
https://raw.githubusercontent.com/ZQ123666/tupian/main/server_audit.so
我建议到GitHub上下载
https://github.com/mcafee-enterprise/mysql-audit/releases
2.安装libaudit_plugin.so插件
把libaudit_plugin.so插件放进MySQL的plugin文件夹中
修改文件权限
chmod 644 libaudit_plugin.so
ll
到MySQL进行安装
INSTALL PLUGIN libaudit_plugin SONAME 'libaudit_plugin.so';
b) 测评内容
审计记录应包括事件的日期、用户、事件类型、事件是否成功及其他与审计相关的信息。
要求:只要启用了审计功能,无论是自带的审计还是插件,在记录的信息上都能满足这个要求。
c) 测评内容
应对审计记录进行保护,定期备份,避免受到未预期的删除、修改或覆盖
要求:如果审计记录存储在文件中,那么在操作系统上需要对这些日志文件的权限进行限定,仅允许数据库管理员可对文件进行访问、修改等。同时也要限制MYSQL中的file_priv权限。
如果审核记录存储在数据库表中,那么也应该对数据库的表进行权限设置,仅数据库管理员可对审核记录进行访问、修改等。
d) 测评内容
应对审计进程进行保护,防止未经授权的中断
要求:需要对审计过程进行配置,一个是my.cnf ,这里就需要操作系统对配置文件的权限进行限制,只允许数据库管理有权限进行修改。(同时也要限制mysql的file_priv 权限)。
另外一个就说那些变量了,似乎是需要super权限才可以设置全局变量,那么就需要查看super权限给了哪些账户。
四、入侵防范
a) 测评内容
应通过设定终端接入方式或网络地址范围对通过网络进行管理的管理终端进行限制;
要求:建议设定终端接入方式或设置网络地址范围,只允许特定IP或地址段进行登录。只允许公司内网通过ssh远程登录。
应该查看用户登录的地址是否给所有用户加上了IP限制。 如果在防火墙上限定了特定的终端IP进行访问这个数据库,那么是符合要求的。
五、可信验证
a) 测评内容
可基于可信根对计算设备的系统引导程序、系统程序、重要配置参数和应用程序等进行可信验证,并在应用程序的关键执行环节进行动态可信验证,在检测到其可信性受到破坏后进行报警,并将验证结果形成审计记录送至安全管理中心
要求:将来可考虑采用可信技术基于可信根对边界设备的系统引导程序、系统程序、重要配置参数和边界防护应用程序等进行可信验证,并在应用程序的关键执行环节进行动态可信验证,在检测到其可信性受到破坏后进行报警,并将验证结果形成审计记录送至安全管理中心。
六、数据完整性
a) 测评内容
应采用校验技术或密码技术保证重要数据在传输过程中的完整性,包括但不限于鉴别数据、重要业务数据、重要审计数据、重要配置数据、重要视频数据和重要个人信息等
要求:建议采用堡垒机+ssh技术保证重要数据在传输过程中的完整性,包括但不限于鉴别数据、重要业务数据、重要审计数据、重要配置数据、重要视频数据和重要个人信息等
b) 测评内容
应采用校验技术或密码技术保证重要数据在存储过程中的完整性,包括但不限于鉴别数据、重要业务数据、重要审计数据、重要配置数据、重要视频数据和重要个人信息等
要求:建议采用MD5或者其他相同功能的技术保证重要数据在存储过程中的完整性,包括但不限于鉴别数据、重要业务数据、重要审计数据、重要配置数据、重要视频数据和重要个人信息等。建议对个人信息加密储存,实现部分整改。
个人信息
建议采取AES、DES进行加密存储,MD5易被破解
七、数据保密性
a) 测评内容
应采用密码技术保证重要数据在传输过程中的保密性,包括但不限于鉴别数据、重要业务数据和重要个人信息等
要求:建议采用堡垒机+ssh技术保证重要数据在传输过程中的保密性,包括但不限于鉴别数据、重要业务数据、重要审计数据、重要配置数据、重要视频数据和重要个人信息等
b) 测评内容
应采用密码技术保证重要数据在存储过程中的保密性,包括但不限于鉴别数据、重要业务数据和重要个人信息等。
要求:建议采用哈希算法、加盐等加密方式对文件加密保证重要数据在存储过程中的保密性,包括但不限于鉴别数据、重要业务数据和重要个人信息等。建议对个人信息加密储存,实现部分整改,同数据完整性。
业务数据、鉴别数据、个人信息
建议采取AES、DES进行加密存储,MD5易被破解
八、数据备份恢复
a) 测评内容
应提供重要数据的本地数据备份与恢复功能
要求:建议供重要数据的本地数据备份与恢复功能
b) 测评内容
应提供异地实时备份功能,利用通信网络将重要数据实时备份至备份场地
要求:建议供异地实时备份功能,利用通信网络将重要数据实时备份至备份场地;实现异地灾备。建议在其他区域进行异地备份
1.数据库备份参数
mysqldump -h 服务器 -u 用户名 -p 密码 数据库名 > 备份文件.sql
//常用参数
-A, --all-databases #备份所有库
-B, --databases #备份多个库多个数据库
--single-transaction#InnoDB 一致性 服务可用性
--master-data=1|2 #记录 binlog日志位置与文件名,追加至备份文件中
--triggers #备份触发器
-F, --flush-logs #备份之前刷新日志
-E, --events #备份事件调度器代码
-R, --routines #备份存储过程和存储函数
注意: 不管物理备份还是逻辑备份, 必须开启binlog日志
2.使用mysqldump完整备份
mysqldump -uSystem -p'System@123' \
--all-databases \
--single-transaction \
--source-data=1 > /root/`date +%F%H`-mysql-all.sql
3.使用备份文件进行备份恢复
mysql -uSystem -p'System@123' < /root/2022-12-1314-mysql-all.sql
c) 测评内容
应提供重要数据处理系统的热冗余,保证系统的高可用性。
要求:建议数据库使用热冗余或者使用高可用版数据库,保证系统的高可用性。
九、剩余信息保护
a) 测评内容
应保证鉴别信息所在的存储空间被释放或重新分配前得到完全清除
mysql数据库自身能够保证鉴别信息所在的存储空间被释放或重新分配前得到完全清除
b) 测评内容
应保证存有敏感数据的存储空间被释放或重新分配前得到完全清除
mysql数据库自身能够保证存有敏感数据的存储空间被释放或重新分配前得到完全清除
十、个人信息保护
a) 测评内容
应仅采集和保存业务必需的用户个人信息
数据库不涉及对个人信息的采集,此项在应用层面进行判定
b) 测评内容
应禁止未授权访问和非法使用用户个人信息
数据库不涉及对个人信息的采集,此项在应用层面进行判定