MySQL安全等保的一些安全项

在开展安全加固或等级保护相关工作的过程中,我个人倾向于保持一种务实的态度。这并非是对安全本身有任何异议,而是注意到部分安全厂商所提供的整改建议,有时过于注重形式化要求,可能在实际运维中引入“无效”成本,甚至影响系统稳定性。例如,在某些场景下,安全扫描工具本身就可能引发服务异常,这类情况在实际运维中并不少见。

就数据库而言,若其部署于内网环境,并已实施了适当的网络隔离与权限管控,实际风险通常远低于安全评估报告中所描述的严重程度。近期,我们在某客户的MySQL数据库中识别出若干待整改项,借此机会做了简要记录与整理。

像MySQL、redis这种开源数据库,通常仅提供基本功能,本身不直接提供内置的、完善的密码策略管理功能。比如像密码复杂度限制,包含大小写;密码有效期,错误密码深度次数,锁定多久,登录记录、审计操作。 这些功能在Oracle 这种商业化软件较为常见。

密码策略

MySQL 从 5.7 版本开始,引入了一个名为 validate_password 的插件,专门用于检查和强制执行密码策略。

SELECT PLUGIN_NAME, PLUGIN_STATUS
FROM INFORMATION_SCHEMA.PLUGINS
WHERE PLUGIN_NAME LIKE 'validate%';

常见的可配置策略项:

变量名含义默认值(可能因版本而异)设置示例
validate_password_policy密码强度策略等级MEDIUMSTRONG
validate_password_length密码最小长度812
validate_password_mixed_case_count至少需要的大写+小写字母数12
validate_password_number_count至少需要的数字个数11
validate_password_special_char_count至少需要的特殊字符个数11

密码有效期

长期使用同一个密码会增加密码被暴力破解或泄露的风险。定期更换密码是纵深防御策略中的重要一环,可以有效降低此类风险。MySQL中可以通过变量全局的配置密码时效,或指定用户限制。但该配置同常于应用程序相匹配,防止密码过期应用无法连接,建议应用手动定期在应用版本时更改密码。

设置全局密码过期策略
您可以为所有用户设置一个全局的密码过期时间。例如,设置所有用户的密码每90天必须更换:

SET GLOBAL default_password_lifetime = 90;

为特定用户设置独立的过期策略

对于某些特定账户(如root),您可能希望设置更短的过期时间。可以使用 ALTER USER 语句。

-- 将用户'root'@'localhost'的密码设置为30天过期
ALTER USER 'root'@'localhost' PASSWORD EXPIRE INTERVAL 30 DAY;

-- 让某个用户的密码立即过期,下次登录时必须修改
ALTER USER 'some_user'@'%' PASSWORD EXPIRE;

验证设置

mysql> SHOW VARIABLES LIKE 'default_password_lifetime';
+---------------------------+-------+
| Variable_name             | Value |
+---------------------------+-------+
| default_password_lifetime | 0     |
+---------------------------+-------+
1 row in set (0.00 sec)

mysql> select host,user,password_last_changed,password_lifetime,password_expired,account_locked from user;
+-----------+-----------------+-----------------------+-------------------+------------------+----------------+
| host      | user            | password_last_changed | password_lifetime | password_expired | account_locked |
+-----------+-----------------+-----------------------+-------------------+------------------+----------------+
| localhost | root            | 2023-07-29 12:05:56   |              NULL | N                | N              |
| localhost | mysql.session   | 2023-07-29 12:05:29   |              NULL | N                | Y              |

登录失败限制

Connection_control插件库允许管理员在连续指定次数的不成功登录尝试后,增加服务器对连接的响应延迟。

SET GLOBAL connection_control_failed_connections_threshold = 3;
SET GLOBAL connection_control_min_connection_delay = 1000;  
SET GLOBAL connection_control_min_connection_delay = 90000;

注意可能会带个《MySQL安全插件connection_control及导致链接耗尽”Waiting in connection_control plugin”》之前写到的可用性风险。

帐号策略

默认的root用户

MySQL安装后默认创建的root账户拥有最高权限,是攻击者的首要目标。如果其密码被破解,整个数据库将完全沦陷。可以强化root登录.为root设置强密码:确保root密码是足够复杂和冗长的。

禁止远程root登录:确保没有名为 'root'@'%' 的用户。root账户应只允许从数据库服务器本机('root'@'localhost')登录。

-- 查看所有root用户
SELECT user, host FROM mysql.user WHERE user = 'root';

-- 删除允许从任何主机登录的root账户(谨慎操作!请先确认)
DROP USER 'root'@'%';

权限未分离

所有管理任务都由root账户完成,不符合“三权分立”(通常指系统管理员、安全管理员、审计管理员)的安全原则。一旦一个账号泄露,所有功能权限都会丢失,且无法进行有效的操作审计和追溯。

根据您的业务需求,至少应创建以下三类账户:

系统管理员(sysadmin):负责数据库的日常运维,如创建/删除数据库、表、用户,数据备份/恢复等。

-- 创建管理员用户,限制其登录IP为运维网络段
CREATE USER 'sysadmin'@'192.168.1.%' IDENTIFIED BY 'StrongPassword!123';

-- 授予其广泛的权限,但不包括敏感的管理权限
GRANT RELOAD, PROCESS, CREATE, ALTER, DROP, INSERT, SELECT, UPDATE, DELETE, INDEX, CREATE VIEW, SHOW VIEW, EVENT, TRIGGER ON *.* TO 'sysadmin'@'192.168.1.%';
-- 注意:谨慎授予 FILE, SUPER, GRANT OPTION 等高级权限。

安全管理员(secadmin):负责账户管理和安全策略,如创建/删除用户、授权、设置密码策略等。

-- 创建安全管理员用户,限制其只能从特定管理主机登录
CREATE USER 'secadmin'@'192.168.1.100' IDENTIFIED BY 'AnotherStrongPassword!456';

-- 授予其账户管理权限
GRANT CREATE USER, ALTER USER, DROP USER ON *.* TO 'secadmin'@'192.168.1.100';
-- 注意:为了使其能设置密码,通常也需要 GRANT OPTION 权限,但这权限过大,需谨慎。
-- 更安全的做法是,secadmin通过具有SUPER权限的会话执行ALTER USER,或者由root执行。

-- 授予其在mysql系统数据库上的SELECT权限,以便查看用户信息
GRANT SELECT ON mysql.* TO 'secadmin'@'192.168.1.100';

审计管理员(auditadmin):负责查看日志,监控数据库活动,但不能修改数据。当然mysql并没有审计功能,需要MySQL官方企业版( MySQL Enterprise Audit插件 )或相应的插件(MariaDB Audit Plugin )。

-- 创建审计员用户
CREATE USER 'auditadmin'@'192.168.1.200' IDENTIFIED BY 'AuditPassword!789';

-- 授予其只读权限和日志查看权限
GRANT SELECT ON *.* TO 'auditadmin'@'192.168.1.200';

-- 授予 PROCESS 权限,可以查看所有正在执行的语句(SHOW PROCESSLIST)
GRANT PROCESS ON *.* TO 'auditadmin'@'192.168.1.200';

-- 如果使用了MySQL企业版的审计插件,还需要授予相关的审计权限。

为应用程序创建专属账户

永远不要使用上述任何管理账户或root账户来连接应用程序。应为每个应用或服务创建独立的、权限最小的账户。如可以只读用户和读写用户。

定期使用 SHOW GRANTS FOR 'user'@'host'; 命令审查各账户的权限,确保没有权限蔓延。

注:安全配置需要在测试环境验证后,再实施数据库。

Leave a Comment