在开展数据库安全加固或等级保护工作时,我们常会面对来自安全厂商的一长串整改建议。这些建议虽旨在提升安全性,但有时过于强调形式化合规,可能在实际运维中引入不必要的复杂度和潜在风险。特别是对于部署在内网、并已有网络隔离与基础权限管控的数据库,其实际风险往往低于评估报告所描述的严重程度。
本文基于一次实际的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 |
密码强度策略等级 |
MEDIUM |
STRONG |
validate_password_length |
密码最小长度 |
8 |
12 |
validate_password_mixed_case_count |
至少需要的大写+小写字母数 |
1 |
2 |
validate_password_number_count |
至少需要的数字个数 |
1 |
1 |
validate_password_special_char_count |
至少需要的特殊字符个数 |
1 |
1 |
密码有效期
长期使用固定密码会增加被暴力破解或泄露的风险。定期更换密码是纵深防御中的重要环节。MySQL支持全局配置密码时效,也可以为特定用户单独设置。不过,此配置需与应用程序更新周期相匹配,防止因密码过期导致应用无法连接。通常更建议在应用版本迭代时手动更新数据库密码。
-
设置全局密码过期策略
例如,设置所有用户的密码每90天必须更换:
SET GLOBAL default_password_lifetime = 90;
-
为特定用户设置独立的过期策略
对于root等高权限账户,可以设置更严格的策略。
-
验证设置
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 mysql.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_max_connection_delay = 90000;
注意:不当配置此插件可能导致连接池耗尽,出现“Waiting in connection_control plugin”的等待状态,带来可用性风险,需在测试环境充分验证。
账户策略
默认的root用户
MySQL安装后默认的root账户是攻击的首要目标。必须强化其安全:
- 设置强密码:确保密码足够复杂和冗长。
- 禁止远程登录:确保不存在名为
‘root’@‘%’ 的用户。root账户应只允许从数据库服务器本机(‘root’@‘localhost’)登录。
权限分离(三权分立)
所有管理任务都由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 SELECT ON mysql.* TO 'secadmin'@'192.168.1.100';
注意:secadmin修改用户密码可能需要SUPER权限或由root执行,直接授予GRANT OPTION权限过大,需评估风险。
-
审计管理员 (auditadmin):负责查看日志与监控活动。
-- 创建审计员用户
CREATE USER 'auditadmin'@'192.168.1.200' IDENTIFIED BY 'AuditPassword!789';
-- 授予只读权限
GRANT SELECT ON *.* TO 'auditadmin'@'192.168.1.200';
-- 授予查看进程权限
GRANT PROCESS ON *.* TO 'auditadmin'@'192.168.1.200';
注意:MySQL社区版无内置审计功能,如需详细审计日志,需使用企业版审计插件或第三方插件(如MariaDB Audit Plugin)。
为应用程序创建专属账户
永远不要使用root或任何管理账户连接应用程序。应为每个应用或服务创建独立的、权限最小化的专属账户(例如区分只读和读写账户)。
定期使用以下命令审查账户权限,防止权限蔓延:
SHOW GRANTS FOR 'user'@'host';
重要提醒:所有安全配置变更都必须在测试环境中充分验证后,再在生产环境实施。在云栈社区,你可以找到更多关于数据库安全与运维的深度讨论和实战案例。
|