赞
踩
在linux系统中,数据库文件不宜存放在 /,/var,/usr目录内,执行以下命令进行检查
- mysql> select @@datadir;
- # 或者
- mysql> show variables where variable_name='datadir';
加固方法
- # 设置指定安全的路径
- mysql> set global datadir='路径' ;
- # 或者修改配置文件my.cnf(linux)或my.init(windows)中的datadir值
- datadir='路径'
- # ps命令查看进程, grep命令过滤结果
- ps -ef | grep mysql
加固方法
- # 1. 创建低权限账号和组
- groupadd mysql
- useradd -r -g mysql mysql
- # 2. 给新建账号添加密码
- passwd mysql
- # 3. 修改MYSQL安装目录的权限(提前关闭mysql服务)
- chown -R mysl.mysql mysql安装路径
- # 4. 读写执行权限最小化755
- chmod 755 mysql安装根路径
- chmod 755 mysql安装后执行目录(bin)
- chmod 755 mysql安装后lib库(libexec)
- chmod -R go-rwx mysql数据存储目录(data)
- # 5.重启mysql服务即可
- service mysqld start
使用其它Linux用户启动mysqld,增加user选项指定/etc/my.cnf选项文件或服务器数据目录的my.cnf选项文件中的[mysqld]组的用户名。
- vim /etc/my.cnf
- [mysqld]
- user=mysql
查看系统中是存在.mysql_history文件,若存在则需要加固
find / -name ".mysql_history"
加固方法
- echo "export MYSQL_HISTORY=dev/null" >> /etc/profile
- ln -s /dev/null .mysql_history文件路径
- rm -r .mysql_history文件路径
使用如下命令,查看MYSQL_PWD环境变量是否设置了敏感信息
grep MYSQL_PWD /proc/*/environ
- # 检查是否存在密码长度为0的用户
- mysql> select user,host from mysql.user where length(authentication_string) = 0;
- # 通过mysql.user系统表查看全部数据库用户状态
- mysql> select user,host,authentication_string,password_lifetime,account_locked from mysql.user;
MySQL 系统自带有 validate_password 插件,此插件可以验证密码强度,未达到规定强度的密码不允许被设置。MySQL 5.7 及 8.0 版本默认情况下均不启用该插件。
(1)插件安装检查
进入 MySQL 命令行,通过 show plugins 或者查看 validate_password 相关参数可以判断是否已安装此插件
- # 插件安装检查,返回为空表示未安装
- mysql> show variables like 'validate%';
(2)validate_password 插件安装
- # 安装插件
- mysql> INSTALL PLUGIN validate_password SONAME 'validate_password.so';
-
- # 查看 validate_password 相关参数
- mysql> 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 |
- +--------------------------------------+--------+
- 7 rows in set (0.00 sec)
(3)参数释意
- 1、validate_password_policy
- 代表密码策略,默认是MEDIUM 可配置的值有以下:
- 0 or LOW 仅需需符合密码长度(由参数validate_password_length指定)
- 1 or MEDIUM 满足LOW策略,同时还需满足至少有1个数字,小写字母,大写字母和特殊字符
- 2 or STRONG 满足MEDIUM策略,同时密码不能存在字典文件(dictionary file)中
-
- 2、validate_password_dictionary_file
- 用于配置密码的字典文件,当validate_password_policy设置为STRONG时可以配置密码字典文件,字典文件中存在的密码不得使用。
-
- 3、validate_password_length
- 用来设置密码的最小长度,默认值是8
-
- 4、validate_password_mixed_case_count
- 当validate_password_policy设置为MEDIUM或者STRONG时,密码中至少同时拥有的小写和大写字母的数量,默认是1最小是0;默认是至少拥有一个小写和一个大写字母。
-
- 5、validate_password_number_count
- 当validate_password_policy设置为MEDIUM或者STRONG时,密码中至少拥有的数字的个数,默认1最小是0
-
- 6、validate_password_special_char_count
- 当validate_password_policy设置为MEDIUM或者STRONG时,密码中至少拥有的特殊字符的个数,默认1最小是0
(4)密码复杂度策略设置
- # 设置密码长度至少10位
- mysql> set global validate_password_length = 10;
- Query OK, 0 rows affected (0.00 sec)
(5)配置文件写入
如果想让密码复杂度策略永久生效,可以在 /etc/mysql/mysql.conf.d/mysqld.cnf 文件中写入如下配置
- [mysqld]
- plugin-load = "validate_password.so"
- validate-password = FORCE_PLUS_PERMANENT
- validate_password_length = 8
- validate_password_policy = 1
- validate_password_mixed_case_count = 1
- validate_password_number_count = 1
- validate_password_special_char_count = 1
(1)设置全局过期策略
- # 运行中临时生效
- mysql> SET GLOBAL default_password_lifetime = 90;
- Query OK, 0 rows affected (0.01 sec)
-
- # 修改配置文件使得永久生效
- [mysqld]
- default_password_lifetime = 90
-
- # 查询全局密码过期时间
- mysql> show global variables like 'default_password_lifetime';
(2)设置单个用户密码过期策略
- # 通过mysql.user系统表查看全部数据库用户状态
- mysql> select user,host,password_expired,password_lifetime,password_last_changed,account_locked from mysql.user;
-
- # 设置user1用户密码立即过期
- mysql> ALTER USER 'user1'@'%' PASSWORD EXPIRE;
-
- # 设置user1用户密码永不过期
- mysql> ALTER USER 'user1'@'%' PASSWORD EXPIRE NEVER;
-
- # 设置user1用户密码90天过期
- mysql> ALTER USER 'user1'@'%' PASSWORD EXPIRE INTERVAL 90 DAY;
-
- # 设置user1用户密码使用全局密码过期策略
- mysql> ALTER USER 'user1'@'%' PASSWORD EXPIRE DEFAULT;
(1)原则上,应当禁止远程登录(至少要禁止root直接远程登录数据库)
执行以下SQL语句检查 host 字段是否仅为 127.0.0.1 或 localhost 或 ::1
mysql> select user,host from mysql.user where user='root';
(2)其它用户如需远程连接,应做访问范围限制
执行以下SQL语句检查是否存在任意IP登录的用户
mysql> select user,host from mysql.user where host = '%';
(3)远程管理用户配置方法
<password> 指定远程连接时使用的密码,与本地密码可不同(但需符合密码复杂度要求)
- mysql> GRANT ALL PRIVILEGES ON <databases-name>.* TO 'user'@'<ip>' IDENTIFIED BY '<password>' WITH GRANT OPTION;
- mysql> FLUSH PRIVILEGES;
-
- # 例如:给teacher用户分配student数据库,只允许192.168.56.%网段远程连接并设置口令为Admin123
- mysql> GRANT ALL PRIVILEGES ON student.* TO 'teacher'@'192.168.56.%' IDENTIFIED BY 'Admin123' WITH GRANT OPTION;
- mysql> FLUSH PRIVILEGES;
- mysql> show databases;
- mysql> drop database test; #删除数据库test
- mysql> use mysql;
- mysql> delete from db; #删除存放数据库的表信息,因为还没有数据库信息。
- mysql> delete from user where not (user='root'); #删除初始非root的用户
- mysql> delete from user where user='root' and password=''; #删除空密码的root尽量重复操作
- mysql> flush privileges; #强制刷新内存授权表。
user表和db表中存放着可以授予数据库用户的权限,确保只有管理员账号才能访问所有数据库
执行如下SQL语句, 确保返回结果只能是数据库管理员账号
- 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');
- mysql> 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'));
user表中的权限列有:
- file_priv:表示是否允许用户读取数据库所在主机的本地文件;
- Process:表示是否允许用户查询所有用户的命令执行信息;
- Super_priv:表示用户是否有设置全局变量、管理员调试等高级别权限;
- Shutdown_priv:表示用户是否可以关闭数据库;
- Create_user_priv:表示用户是否可以创建或删除其他用户;
- Grant_priv:表示用户是否可以修改其他用户的权限;
应确保只有数据库管理员才有上述权限,使用如下sql语句查看拥有各个权限的数据库账号,确保查询结果中不存在非管理员用户
- mysql> select user, host from mysql.user where File_priv = 'Y';
-
- mysql> select user, host from mysql.user where Process_priv = 'Y';
-
- mysql> select user, host from mysql.user where Process_priv = 'Y';
-
- mysql> SELECT user, host FROM mysql.user WHERE Shutdown_priv = 'Y';
-
- mysql> SELECT user, host FROM mysql.user WHERE Create_user_priv = 'Y';
-
- mysql> SELECT user, host FROM mysql.user WHERE Grant_priv = 'Y';
-
- mysql> SELECT user, host FROM mysql.db WHERE Grant_priv = 'Y';
如果存在非管理员用户,可以使用如下命令进行权限回收,其中<user>为上述查询到的非管理员用户
- mysql> REVOKE FILE ON *.* FROM '<user>';
-
- mysql> REVOKE PROCESS ON *.* FROM '<user>';
-
- mysql> REVOKE SUPER ON *.* FROM '<user>';
-
- mysql> REVOKE SHUTDOWN ON *.* FROM '<user>';
-
- mysql> REVOKE CREATE USER ON *.* FROM '<user>';
-
- mysql> REVOKE GRANT OPTION ON *.* FROM <user>;
DML/DDL语句包括创建或修改数据库结构的权限,例如insert、update、delete、create、drop和alter语句,在任何数据库中都要控制用户的此类权限,确保只授权给有业务需求的非管理员用户。
在MySQL命令行下执行如下命令进行检查
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';
在上述查询结果中,应该具有针对性地为每个用户设置相关数据库权限,使用如下命令进行相关权限的回收,其中<user>为查询到的未授权的用户,host为相关主机,database为相关数据库
- mysql> REVOKE SELECT ON <host>.<database> FROM <user>;
-
- mysql> REVOKE INSERT ON <host>.<database> FROM <user>;
-
- mysql> REVOKE UPDATE ON <host>.<database> FROM <user>;
-
- mysql> REVOKE DELETE ON <host>.<database> FROM <user>;
-
- mysql> REVOKE CREATE ON <host>.<database> FROM <user>;
-
- mysql> REVOKE DROP ON <host>.<database> FROM <user>;
-
- mysql> REVOKE ALTER ON <host>.<database> FROM <user>;
数据目录是mysql数据库存放的位置,在MySQL命令行界面下执行如下命令:
mysql> show variables where variable_name = 'datadir';
在终端命令行下执行如下命令:
- # <datadir>是上述命令的执行结果
- ls -l <datadir>/.. | egrep "^d[r|w|x]{3}------\s*.\s*mysql\s*mysql\s*\d*.*mysql"
若存在问题,执行如下命令进行加固
- chmod 700 <datadir>
- chown mysql:mysql <datadir>
mysql的运行会产生很多日志,例如二进制日志、错误日志、慢查询日志等等,MySQL命令行下执行如下命令:
mysql> show variables like 'log_bin_basename';
在终端命令行执行如下命令:
ls <log_bin_basename>.*
对于发现的每一个文件,执行如下命令,根据输出确认日志文件的权限设置是否存在问题。
ls -l <log_bin_basename.nnnnn> | egrep "^-[r|w]{2}-[r|w]{2}----\s*.*$"
若存在问题,对于每个日志文件,修改其权限和属组如下:
- chmod 660 <log file>
- chown mysql:mysql <log file>
在MySQL命令行下执行如下命令:
mysql> show variables like 'log_error';
在终端命令行执行如下命令:
ls <log_error>.*
对于发现的每一个文件,执行如下命令,根据输出确认日志文件的权限设置是否存在问题。
ls -l <log_error> | egrep "^-[r|w]{2}-[r|w]{2}----\s*.*$"
若存在问题,对于每个日志文件,修改其权限和属组如下:
- chmod 660 <log file>
- chown mysql:mysql <log file>
在MySQL命令行下执行如下命令:
mysql> show variables like 'slow_query_log_file';
在终端命令行执行如下命令:
ls <slow_query_log_file>.*
对于发现的每一个文件,执行如下命令,根据输出确认日志文件的权限设置是否存在问题。
ls -l <slow_query_log_file> | egrep "^-[r|w]{2}-[r|w]{2}----\s*.*$"
若存在问题,对于每个日志文件,修改其权限和属组如下:
- chmod 660 <log file>
- chown mysql:mysql <log file>
在MySQL命令行下执行如下命令:
mysql> show variables like 'general_log_file';
在终端命令行执行如下命令:
ls <general_log_file>.*
对于发现的每一个文件,执行如下命令,根据输出确认日志文件的权限设置是否存在问题。
ls -l <general_log_file> | egrep "^-[r|w]{2}-[r|w]{2}----\s*.*$"
若存在问题,对于每个日志文件,修改其权限和属组如下:
- chmod 660 <log file>
- chown mysql:mysql <log file>
在MySQL命令行下执行如下命令:
mysql> show global variables where variable_name = 'audit_log_file';
在终端命令行执行如下命令,根据输出确认日志文件的权限设置是否存在问题。
ls -l <audit_log_file> | egrep "^-rw[-x]rw[-x][-r][-w][-x][ \t]*[0-9][ \t]*mysql[\t]*mysql.*$"
若存在问题,对于每个日志文件,修改其权限和属组如下:
- chmod 660 <audit_log_file>
- chown mysql:mysql <audit_log_file>
- # 查看空闲连接超时时间
- mysql> SHOW GLOBAL VARIABLES LIKE '%timeout%'
- # 修改空闲连接超时时间
- mysql> SET GLOBAL wait_timeout=1800
错误日志包括数据库运行和停止过程中的一系列活动信息,有助于分析数据库运行过程中的一些异常活动,一般情况下需要开启错误日志记录功能,使用如下命令查询:
mysql> SHOW variables LIKE 'log_error';
确保返回结果为非空,如果为空,需要在mysql数据库配置文件中增加如下配置
- # 在/etc/my.cnf加入配置
- [mysqld_safe]
- log-error=log文件路径
使用如下命令进行查询:
mysql> SELECT @@global.log_bin_basename;
确保返回结果不是如下路径:/、/var、/usr
原始日志选项会决定一些敏感信息是否会被明文写进日志中,例如查询日志、慢查询日志、二进制日志,确保数据库配置文件中存在如下配置项:
- [mysqld_safe]
- Log-raw = OFF
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。