MySQL数据库安全加固方法
基本安全原则
- 选择稳定版本并及时更新、打补丁
- 严禁使用弱口令,定期更新口令
- 严格的权限分配和访问控制
具体安全配置
系统层面配置
-
系统安装时,需要确认没有其他⽤户登录在服务器上。
-
选择稳定的版本,并及时更新到最新版本、打补丁
-
查看系统防火墙或网络安全设备,是否有限制对MySQL数据库的访问
-
不设置环境变量或确保MYSQL_PWD环境变量未设置敏感信息
-
禁用MySQL命令历史记录
删除现在的.mysql_history文件 rm ~/.mysql_history 创建它的软连接 ln -s /dev/null ~/.mysql_history 如果有特殊情况需要打开,重新设置MYSQL_HISTFILE即可: 比如export MYSQL_HISTFILE=~/.mysql_history
-
系统安装时运行mysql_secure_installation执行相关安全设置
运行mysql_secure_installation会执行几个设置: a)为root用户设置密码 b)删除匿名账号 c)取消root用户远程登录 d)删除test库和对test库的访问权限 e)刷新授权表使修改生效
服务器配置
- 3306端口及服务不允许暴露到公网。如有特殊业务需求需对外网开放,必须经云安全部审核通讨后,才允许对外网开放。
- 服务器不应该具备访问外⽹的能⼒(如有必要,可单向访问)。
- 新的服务器正式投⼊使⽤前,必须经过安全加固。
⽤户和密码配置
-
使用专用的最小权限账号运行Mysql数据库进程
-
严禁使用弱口令,严禁共享账号
-
强密码的设定,需要符合以下标准:
每个账号必须要设密码且密码不能和用户名相同;(必选) 不得出现用户名、真实姓名为公司名称;(必选) 用户密码长度不能低于8位;(必选) 不能使用常用单词;(必选) 不能使用用户相关信息:例如生日、电话号码等等;(可选) 至少由3种字符组成,包含字母、数字、特殊符号在内。(可选)
-
使用validate_password.so插件,进行安全加固
安装插件:(默认安装了插件后,强度插件就启用了,关闭,需要在配置文件假如相关关闭参数) mysql>INSTALL PLUGIN validate_password SONAME 'validate_password.so'; 配置文件添加部分参数: [mysqld] plugin-load=validate_password.so validate_password_policy=2 validate-password=FORCE_PLUS_PERMANENT 3.以上处理后,就可以测试了: mysql> SET PASSWORD = PASSWORD('abc'); ERROR 1819 (HY000): Your password does not satisfy the current policy requirements mysql> SET PASSWORD = '*0D3CED9BEC10A777AEC23CCC353A8C08A633045E'; Query OK, 0 rows affected (0.01 sec) 相关选项说明: validate-password=ON/OFF/FORCE/FORCE_PLUS_PERMANENT: 决定是否使用该插件(及强制/永久强制使用)。 validate_password_dictionary_file:插件用于验证密码强度的字典文件路径。 validate_password_length:密码最小长度。 validate_password_mixed_case_count:密码至少要包含的小写字母个数和大写字母个数。 validate_password_number_count:密码至少要包含的数字个数。 validate_password_policy:密码强度检查等级,0/LOW、1/MEDIUM、2/STRONG。 validate_password_special_char_count:密码至少要包含的特殊字符数。 其中,关于validate_password_policy-密码强度检查等级: 0/LOW:只检查长度。 1/MEDIUM:检查长度、数字、大小写、特殊字符。 2/STRONG:检查长度、数字、大小写、特殊字符字典文件。
-
-
用户密码过期时间小于等于90天
配置文件中设置 [mysqld] default_password_lifetime=90
-
重命名root账号
use mysql update user set user="新的用户名" where user="root"; select user,host,password from mysql.user; #查看结果
-
控制最高权限只有管理员
使用如下sql语句: 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'); SELECT user, host FROM mysql.db WHERE db = 'mysql' AND ((Select_priv = 'Y') OR (Insert_priv = 'Y') OR (Update_priv = 'Y')OR (Delete_priv = 'Y') OR (Create_priv = 'Y') OR (Drop_priv = 'Y')); 确保返回结果只能是数据库管理员账号。
-
合理控制DML/DDL操作授权
DML/DDL语句包括创建或修改数据库结构的权限,例如insert、update、delete、create、drop和alter语句,在任何数据库中都要控制用户的此类权限,确保只授权给有业务需求的非管理员用户。Mysql命令行下执行如下命令: SELECT User,Host,Db FROM mysql.db WHERE Select_priv='Y' OR Insert_priv='Y' OR Update_priv='Y' OR Delete_priv='Y' OR Create_priv='Y' OR Drop_priv='Y' OR Alter_priv='Y'; 上述查询到的用户只能对特定的数据库才有相关的权限,使用如下命令进行相关权限的回收: REVOKE SELECT ON <host>.<database> FROM <user>; REVOKE INSERT ON <host>.<database> FROM <user>; REVOKE UPDATE ON <host>.<database> FROM <user>; REVOKE DELETE ON <host>.<database> FROM <user>; REVOKE CREATE ON <host>.<database> FROM <user>; REVOKE DROP ON <host>.<database> FROM <user>; REVOKE ALTER ON <host>.<database> FROM <user>; 其中<user>为查询到的未授权的用户,host为相关主机,database为相关数据库。 权限说明: file_priv:表示是否允许用户读取数据库所在主机的本地文件; Process:表示是否允许用户查询所有用户的命令执行信息; Super_priv:表示用户是否有设置全局变量、管理员调试等高级别权限; Shutdown_priv:表示用户是否可以关闭数据库; Create_user_priv:表示用户是否可以创建或删除其他用户; Grant_priv:表示用户是否可以修改其他用户的权限;
-
历史命令行密码设置为不可见
(1)先输入mysql -u admin -p (2)根据命令行提示输入密码; 而不要在一整条命令中输入密码。 另外要控制mysql配置文件访问权限
-
删除默认test数据库,测试帐号,空密码、匿名帐号
bash drop database if exists ${dbname}; #删除冗余数据库, 如test bash drop user '' #清除无用用户(没有用户名的用户) select user,host from mysql.user #使用该命令查询是否存在空账号
-
禁止root远程登录
use mysql; # 切换到mysql数据库(这是MySQL自带的一个数据库,里面存放着一些root的配置信息); update user set host = "localhost" where user = "root" and host = "%"; # 修改root用户的host属性,确保其为localhost,这表示只能本地访问(%表示可以远程访问); flush privileges; #刷新
-
关闭Old_Passwords
mysql> show variables like ‘%password%’; +—————+——-+ | Variable_name | Value | +—————+——-+ | old_passwords | OFF | ####这里表明已经关闭了旧密码选项 +—————+——-+ 1 row in set (0.00 sec)
-
secure_auth选项设置
如果客户端采用Old_passwords发起连接请求,如果服务器端设置了secure_auth,则客户端会拒绝连接请求,可以根据安全需求在配置文件中做相应配置。
-
确保所有用户都要求使用非空密码登录
行如下语句查询是否有用户不需要密码即可登录: SELECT User,host FROM mysql.user WHERE (plugin IN('mysql_native_password', 'mysql_old_password') AND (LENGTH(Password) = 0 OR Password IS NULL)) OR (plugin='sha256_password' AND LENGTH(authentication_string) = 0);
文件权限配置
- 禁止MySQL对本地文件存取
在MySQL中,提供对本地文件的读取,使用的是load data local infile命令,默认在5.0版本中,该选项是默认打开的,该操作令会利用MySQL把本地文件读到数据库中,然后用户就可以非法获取敏感信息了,如不需要读取本地文件,请关闭。
检查方法
Less /etc/my.cnf
检查[mysqld]部分是否存在local-infile=0。
或者ps –aux查看启动mysql进程是有local-infile=0
-
控制二进制日志文件的权限
mysql的运行会产生很多日志,例如二进制日志、错误日志、慢查询日志等等,Mysql命令行下执行如下命令: show variables like 'log_bin_basename'; Linux在终端命令行执行如下命令: ls <log_bin_basename>.* 对于发现的每一个文件,执行如下命令: ls -l <log_bin_basename> # 根据输出确认日志文件的权限设置是否存在问题。 对于每个日志文件,修改其权限和属组如下: chmod 660 <log file> chown mysql:mysql <log file>
-
控制datadir、basedir的访问权限
数据目录是mysql数据库存放的位置,在mysql命令行界面下执行如下命令: show variables where variable_name = 'datadir'; 在终端命令行下执行如下命令: ls -l <datadir> 如果存在问题,linux环境下在终端执行如下命令进行加固: chmod 700 <datadir> #仅MySQL数据库用户有读写权限 chown mysql:mysql <datadir> 同理控制basedir权限,仅DBA和数据库用户可访问
-
控制错误日志文件的权限
Mysql命令行下执行如下命令: show variables like 'log_error'; 在终端命令行执行如下命令: ls <log_error>.* 对于发现的每一个文件,执行如下命令: ls -l <log_error> # 根据输出确认日志文件的权限设置是否存在问题。 对于每个日志文件,修改其权限和属组如下: chmod 660 <log file> chown mysql:mysql <log file>
-
控制慢查询日志文件的权限
Mysql命令行下执行如下命令: show variables like 'slow_query_log_file'; 在终端命令行执行如下命令: ls <slow_query_log_file>.* 对于发现的每一个文件,执行如下命令: ls -l <slow_query_log_file> 根据输出确认日志文件的权限设置是否存在问题。 对于每个日志文件,修改其权限和属组如下: chmod 660 <log file> chown mysql:mysql <log file>
-
控制通用日志文件的权限
Mysql命令行下执行如下命令: show variables like 'general_log_file'; 在终端命令行执行如下命令: ls <general_log_file>.* 对于发现的每一个文件,执行如下命令: ls -l <general_log_file> # 根据输出确认日志文件的权限设置是否存在问题。 对于每个日志文件,修改其权限和属组如下: chmod 660 <log file> chown mysql:mysql <log file>
-
控制审计日志文件的权限
Mysql命令行下执行如下命令: show global variables where variable_name = 'audit_log_file'; 在终端执行如下命令: ls -l <audit_log_file> # 根据输出确认日志文件的权限设置是否存在问题。 对于每个日志文件,修改其权限和属组如下: chmod 660 <audit_log_file> chown mysql:mysql <audit_log_file>
审计和日志
-
开启审计功能
show variables like '%plugin%'; #查看插件存放位置 +-----------------+--------------------------+ | Variable_name | Value | +-----------------+--------------------------+ | plugin_dir | /usr/lib64/mysql/plugin/ | | plugin_maturity | unknown | +-----------------+--------------------------+ 注意:mysql上的审计插件libaudit_plugin.so需要单独下载后安装,mariadb自带审计插件server_audit.so 执行安装命令: install plugin server_audit SONAME 'server_audit.so'; flush privileges; 修改配置文件: vim /etc/my.cnf 在[mysqld]下面添加 server_audit=FORCE_PLUS_PERMANENT --防止审计插件被卸载 server_audit_logging=ON --开启审计日志 server_audit_excl_users='z' --不在审计内的用户 server_audit_file_rotate_size=2000000 --审计日志文件轮替限制大小 server_audit_file_rotations=200 --审计轮替日志限制数 server_audit_excl_users='root' --审计在内的用户 server_audit_events='query_ddl,query_dml'; --审计日志事件的操作指令内容 重启数据库使配置生效 错误日志包括数据库运行和停止过程中的一系列活动信息,有助于分析数据库运行过程中的一些异常活动,一般情况下需要开启错误日志记录功能,使用如下命令查询: SHOW variables LIKE 'log_error'; 确保返回结果为非空,如果为空,需要在mysql数据库配置文件中增加相关配置
-
确保数据存放在非系统区域
随着数据库的运行产生的数据会不断增加,如果存放在系统区域,则会影响系统的正常运行,所以配置datadir时应避开:root('/'),"/var","/usr"
-
关闭原始日志功能
原始日志选项会决定一些敏感信息是否会被明文写进日志中,例如查询日志、慢查询日志、二进制日志,确保数据库配置文件中存在如下配置项: Log-raw = OFF
备份与恢复
-
数据库定期备份,并保证至少每周1次的完全备份
-
定期进行备份和恢复有效性的测试