12、MySQL数据库加固
Categories:
8 分钟阅读
定位:MySQL 5.7 / 8.0 等保三级安全加固手册:按 00~13 编号分节覆盖账户治理、口令复杂度、登录失败处理与超时、远程管理与主机限制、连接数、日志与审计、文件读写防护、权限最小化与三权分立,每节附验证命令与测评项对照表。
适用版本:MySQL 5.7 / 8.0(5.6 大体兼容;版本差异见文末速查表)。 配套测评:MySQL 测评命令。
使用说明:
- 本文为加固操作手册:所有命令都会修改配置,可能中断服务、断开当前会话或需要重启。实施前必须完成变更审批、确认业务窗口、备份原配置(设备
save与copy running-config/backup startup-configuration,主机备份/etc、注册表与关键业务数据),并准备可执行的回滚预案。- 先在测试环境或单台设备灰度验证,确认无业务影响后再批量推广;每完成一项立即用文中「验证」命令核验生效——配置已下发不等于策略已生效(如 H3C 未
password-control enable、Linux 未对存量账户chage、Windows 未gpupdate /force)。- 示例中的地址、账户名、口令、路径均为演示值(如
PleaseChange@123、192.168.10.20、admin123),现场须替换为符合本单位口令策略与网络规划的真实值,严禁直接沿用文中示例口令;对外发布或归档时须对个人信息与内网管理地址脱敏。- 命令不存在、视图名或参数与本文不一致时,先用
display version/show version/winver确认版本与部署形态,再查阅对应版本官方文档换用等效命令;版本差异不得直接作为「无法整改」的结论,须给出替代措施并评估其实际效果。- 涉及账户、锁定、超时、防火墙与端口收敛的变更存在锁死自身风险:务必保留一条已验证的恢复通道(Console 口、带外管理口、堡垒机会话或另一管理员账户)后再实施。
- 加固完成后按「16、安全评估加固记录表3.0」逐项留痕(整改前后回显、操作人、时间、验证结论、回退情况),并纳入复测;测评判定口径以 GB/T 28448-2019 与《高风险判定指引》为准,本文的「加固要点」不构成最终测评结论。
不适用标识说明:
- 使用
【不适用】明确标记现场可判定为不适用的控制点,并写明判定依据与承载该能力的上位组件。- 依据 GB/T 28448-2019「按测评对象实际承载功能与数据处理范围判定」原则:控制能力由统一认证平台、堡垒机、日志审计系统、终端管理系统、虚拟化平台或云托管平台承载时,应注明测评单元边界后判定不适用或转由上位组件核查,不得机械按缺失判不符合。
- 产品版本确实不提供该能力(如老旧设备无 SNMPv3、无可信根、社区版无审计模块、已停止官方支持的操作系统)时,须核查替代措施并按替代措施的实际效果定档,不得直接判不适用;已停止支持的版本应同时提出升级或补偿控制建议。
测评项对照表
| 控制点(GB/T 22239-2019 安全计算环境-数据库) | 对应章节 |
|---|---|
| 身份鉴别:口令复杂度/有效期 | 01、03 |
| 身份鉴别:登录失败处理与超时 | 04 |
| 身份鉴别:远程管理防窃听 | 05 |
| 访问控制:账户最小化、默认账户治理 | 01、06、11 |
| 安全审计:日志与留存 | 08 |
| 入侵防范:文件读写防护、端口与服务收敛 | 09、10 |
| 数据备份恢复 | 12 |
00 关注官方安全更新公告
对应控制点:GB/T 22239-2019 8.1.4.4 入侵防范 a)~f)(最小安装与组件收敛、监听与端口限制、危险能力关闭、漏洞与补丁管理)
加固要点:按最小化原则收敛数据库暴露面:仅安装业务所需组件(去掉示例库、示例脚本、可选的 Web 管理台与客户端工具),关闭不需要的服务与端口;监听地址限定到业务网段(禁止
0.0.0.0或bindIp: 0.0.0.0直连公网),端口经主机防火墙与边界策略双重限制到应用服务器与运维堡垒机;关闭高危能力(MySQLlocal_infile=OFF并设置secure_file_priv、启用skip_symbolic_links;PostgreSQL 限制COPY ... PROGRAM、lo_import/lo_export、file_fdw;MongoDBsecurity.javascriptEnabled: false并确认未启用旧版 HTTP 接口);建立版本与漏洞台账,跟踪官方安全公告并按变更窗口修补,已停止官方支持的版本须提出升级或补偿控制建议。验证方法:已安装组件与版本清单、监听地址与端口回显(
ss -tlnp或netstat -ano、MySQLSHOW VARIABLES LIKE 'bind_address';、PostgreSQLSHOW listen_addresses; SHOW port;、MongoDBnet.bindIp配置)、主机防火墙与边界策略截图、高危参数当前值回显、漏洞台账与补丁记录、官方安全公告订阅证据(MySQL Release Notes、PostgreSQL 官方邮件列表与 Release Notes、MongoDB Release Notes、达梦与金仓官网公告)。
数据库监听地址为 0.0.0.0 且端口经边界策略直接对互联网或办公终端区开放,同时存在弱口令或默认口令时,按《高风险判定指引》可直接判高风险;MySQL local_infile=ON 且 secure_file_priv 为空,攻击者可借恶意服务端读取客户端任意文件,同样按高风险处理。
判定口径详见 22、高风险判定指引与加固对照表。
在不影响业务的前提下及时更新小版本与补丁。官方安全公告:https://www.oracle.com/security-alerts/
核查版本与已知漏洞:select version();
01 禁止空口令并治理默认/多余账户
对应控制点:GB/T 22239-2019 8.1.4.1 身份鉴别 a)~d)(数据库管理系统自身账户标识与鉴别)
加固要点:数据库账户须唯一实名、禁止共用与空口令:删除或锁定安装时产生的多余账户与测试对象(MySQL 的匿名账户与
test库、PostgreSQL 与操作系统同名的默认账户、MongoDB 创建首个用户前的localhost exception、达梦与金仓的默认示例账户),管理账户按「系统管理员 / 安全保密管理员 / 安全审计员」三权分立建账(DM 的 SYSDBA/SYSSSO/SYSAUDITOR、KingbaseES 的 SYSTEM/SSEO/SYSSAO、PostgreSQL 用三个独立 ROLE 分持权限、MySQL 用独立管理账户并按权限分离),应用连接账户与 DBA 账户严格分离且只授予业务库的对象权限。鉴别信息复杂度与有效期按 8.1.4.1 a) 配置并逐账户下发生效;三级系统须核查最高权限账户是否同受约束。验证方法:账户清单与权限矩阵(MySQL
SELECT user,host,account_locked,password_expired,plugin FROM mysql.user;、PostgreSQL\du+与SELECT rolname,rolsuper,rolcreatedb,rolcreaterole,rolcanlogin,rolvaliduntil FROM pg_roles;、MongoDBdb.getUsers()与db.getUser("<u>")、达梦SELECT USERNAME,ACCOUNT_STATUS,LOCK_DATE FROM DBA_USERS;、金仓SYS_USERS视图或\du)+ 口令策略参数回显 + 三权分立的分权实测(用安全审计员账户执行 DBA 操作应被拒)+ 一次真实登录记录。
数据库存在空口令账户、匿名账户或沿用安装默认口令的管理账户(MySQL 的匿名 ''@'localhost'、MongoDB 未创建首个用户前的 localhost exception、达梦与金仓默认账户未改口令),或管理账户对全网乃至互联网开放且无来源限制,按《高风险判定指引》可直接判高风险;三权分立未落实、安全审计员与系统管理员由同一账户担任时,按高风险线索记录。
判定口径详见 22、高风险判定指引与加固对照表。
核查方法
select user,host,authentication_string,password_lifetime,account_locked from mysql.user;
select user,host from mysql.user where length(authentication_string) = 0; -- 空口令账户
示例输出(节选)
mysql> select user,host,authentication_string,password_lifetime,account_locked from mysql.user;
+------------------+-----------+-------------------------------------------+-------------------+----------------+
| user | host | authentication_string | password_lifetime| account_locked |
+------------------+-----------+-------------------------------------------+-------------------+----------------+
| root | localhost | $A$005$...hashed... | NULL | N |
| appuser | 192.168.% | $A$005$...hashed... | 90 | N |
| mysql.infoschema | localhost | $A$005$...hashed... | NULL | Y |
+------------------+-----------+-------------------------------------------+-------------------+----------------+
mysql> select user,host from mysql.user where length(authentication_string) = 0;
Empty set (0.00 sec) -- 空口令账户应为 0 行
加固操作
-- 设置强口令(需满足 03 节复杂度策略)
set password for 'user'@'host' = password('YourStrong@Passw0rd');
-- 锁定(停用)多余账户
ALTER USER 'user'@'host' ACCOUNT LOCK;
-- 删除匿名账户与 test 库(旧版本默认存在)
delete from mysql.user where user='';
drop database if exists test;
- 预期现象:无空口令账户;默认账户口令已修改;无匿名账户;test 库已删除(旧版本)。
02 弱口令核查
对应控制点:GB/T 22239-2019 8.1.4.1 身份鉴别 a)(身份鉴别信息具有复杂度要求并定期更换)
加固要点:按「复杂度 + 长度 + 老化 + 历史」四要素配置并对全部账户生效:最小长度不低于 8 位(管理账户建议 12~16 位)、至少包含大写字母/小写字母/数字/特殊字符中三类、老化不超过 90 天、历史防重复不少于 5 次。落地方式因产品而异——MySQL 8.0 用
validate_password组件(5.7 为插件,参数名validate_password_policy/validate_password_length与 8.0 的validate_password.policy/.length写法不同);PostgreSQL 用 contrib 的passwordcheck扩展(须写入shared_preload_libraries后重启,能力较弱,长度与字符类组合须辅以应用侧或制度约束);MongoDB 无内置口令复杂度校验,须在账户创建流程与配置管理中约束并说明;达梦用PWD_POLICY/PASSWORD_POLICY位掩码与PWD_MIN_LEN;金仓用 PROFILE 机制。无论采用哪种方式,都须核查最高权限账户是否同受约束,并对存量账户逐个下发有效期。验证方法:口令策略参数回显(
SHOW VARIABLES LIKE 'validate_password%';、SHOW shared_preload_libraries;与CREATE EXTENSION passwordcheck结果、达梦SELECT * FROM V$PARAMETER WHERE NAME LIKE 'PWD%';、金仓 PROFILE 定义)+ 存量账户有效期抽查(MySQLSELECT user,host,password_expired,password_lifetime FROM mysql.user;、PostgreSQLrolvaliduntil、达梦DBA_USERS.EXPIRY_DATE)+ 一次弱口令设置被拒的实测记录。
数据库管理账户存在弱口令或口令永不过期,且管理端口对非运维网段开放、可被在线口令猜测时,按《高风险判定指引》可直接判高风险;仅在参数模板中配置复杂度而未对存量账户重设口令,属高频「已整改但无效」情形,复测必须重新实测而非只看配置。
判定口径详见 22、高风险判定指引与加固对照表。
将 authentication_string 密文放到解密平台验证能否反推出明文(仅限自有口令强度自检,如 https://www.cmd5.com/ 、https://www.somd5.com/ ):能秒解说明口令强度不足或使用了旧弱哈希算法,应改强口令并确认 default_authentication_plugin(8.0 默认 caching_sha2_password)。
03 密码复杂度(validate_password)
对应控制点:GB/T 22239-2019 8.1.4.1 身份鉴别 a)(身份鉴别信息具有复杂度要求并定期更换)
核查方法
show variables like '%validate_password%';
示例输出(节选)
mysql> show variables like '%validate_password%';
+-------------------------------------------------+--------+
| Variable_name | Value |
+-------------------------------------------------+--------+
| 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 |
+-------------------------------------------------+--------+
加固操作:编辑 /etc/mysql/mysql.conf.d/mysqld.cnf(或 /etc/my.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
策略取值:
| 值 | 密码策略 |
|---|---|
| 0 / LOW | 仅校验长度 |
| 1 / MEDIUM | 校验长度 + 数字/大小写/特殊字符 |
| 2 / STRONG | 在 MEDIUM 基础上增加字典文件校验 |
FORCE_PLUS_PERMANENT 表示强制启用且不可在运行期卸载。重启后 show variables like '%validate_password%' 核验(预期 policy=MEDIUM、length=8)。运行期安装可用 INSTALL PLUGIN validate_password SONAME 'validate_password.so';。
04 登录失败处理与连接超时
对应控制点:GB/T 22239-2019 8.1.4.1 身份鉴别 b)(提供登录失败处理功能,限制非法登录次数)
加固要点:提供并启用登录失败处理功能:MySQL 8.0 用
connection_control插件(connection_control_failed_connections_threshold建议 3~5,min_connection_delay/max_connection_delay递增延时);PostgreSQL 无内置失败锁定,须以 fail2ban、pgbouncer 或数据库审计系统联动实现,并如实说明替代措施与其实际效果;MongoDB 无内置失败锁定,以net.bindIp配合防火墙限制来源、审计与告警联动实现;达梦用FAILED_LOGIN_ATTEMPS(注意官方关键字拼写少一个 T)与PASSWORD_LOCK_TIME;金仓用 PROFILE 的失败次数与锁定时长。策略须覆盖最高权限账户,并保留一条已验证的恢复通道(本地 socket 登录、单用户维护模式或另一管理员账户),避免锁定即失联。验证方法:失败处理参数回显(
SHOW VARIABLES LIKE 'connection_control%';、\dx确认插件已安装、达梦与金仓的 LIMIT 与 PROFILE 定义)+ 一次真实失败登录实测:连续输错至阈值后确认账户被拒或延时递增,并记录解锁方式与解锁后登录成功;采用替代措施时须附 fail2ban 规则与触发日志(fail2ban-client status <jail>)。
数据库管理入口无任何登录失败处理措施且对全网或互联网开放,可被无限次口令猜测时,按高风险线索记录;失败锁定未覆盖最高权限账户,或未保留本地恢复通道导致锁定即失联,同样记录为高风险线索。
判定口径详见 22、高风险判定指引与加固对照表。
核查方法
show variables like "%connection_control%";
show global variables like 'interactive_timeout';
show global variables like 'wait_timeout';
示例输出(节选)
mysql> show variables like "%connection_control%";
+--------------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------------+-------+
| connection_control_failed_connections_threshold | 5 |
| connection_control_max_connection_delay | 86400 |
| connection_control_min_connection_delay | 60000 |
+--------------------------------------------------+-------+
mysql> show global variables like 'wait_timeout';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout | 1800 |
+---------------+-------+
加固操作:先安装插件(5.7.17+),再配置参数:
INSTALL PLUGIN CONNECTION_CONTROL SONAME 'connection_control.so';
INSTALL PLUGIN CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS SONAME 'connection_control.so';
[mysqld]
connection-control = FORCE_PLUS_PERMANENT
connection_control_failed_connections_threshold = 5 # 连续失败 5 次启用延迟
connection_control_min_connection_delay = 60000 # 每次失败追加延迟 60 秒
connection_control_max_connection_delay = 86400 # 延迟上限 1 天
会话超时(交互式/非交互式连接空闲超时,≤30 分钟):
set global interactive_timeout = 1800;
set global wait_timeout = 1800;
- 说明:connection_control 的"惩罚"是递增延迟而非账户锁定,测评判定时按「具备登录失败处理措施」口径结合延时效果认定。
05 传输加密(SSL/TLS)
对应控制点:GB/T 22239-2019 8.1.4.7 数据完整性 a)、8.1.4.8 数据保密性 a)、8.1.2.2 通信传输 a)b)(客户端与服务端间 SSL/TLS)
加固要点:客户端与数据库服务端之间的通信须加密并强制使用:MySQL
require_secure_transport=ON或账户级REQUIRE SSL/REQUIRE X509、PostgreSQLssl=on且pg_hba.conf用hostssl替代host并设ssl_min_protocol_version=TLSv1.2(12+)、MongoDBnet.tls.mode: requireTLS、达梦与金仓按对应版本手册启用通信加密;证书由内部 CA 或可信 CA 签发且在有效期内,禁用 SSLv3/TLS1.0/TLS1.1 与弱套件;集群内部节点间通信(副本集、复制链路)同样须加密并启用内部认证(MongoDBkeyFile或 x.509、MySQL 复制通道MASTER_SSL=1/SOURCE_SSL=1)。仅「支持加密」而未强制不构成符合。验证方法:服务端 SSL 参数与证书路径回显、证书有效期与签发者(
openssl x509 -in <cert> -noout -dates -issuer -subject)、pg_hba.conf中的hostssl行、客户端连接实测:以--ssl-mode=DISABLED或sslmode=disable连接应被拒,以加密方式连接后用\conninfo、SHOW STATUS LIKE 'Ssl_cipher';、db.serverStatus().security确认实际协商的协议与套件版本。
承载敏感数据(个人身份信息、鉴别信息、业务核心数据)的数据库通信全程明文(ssl=off、require_secure_transport=OFF、net.tls.mode: disabled、pg_hba.conf 全部使用 host 而非 hostssl),鉴别信息与数据可被链路嗅探还原时,按《高风险判定指引》可直接判高风险。
判定口径详见 22、高风险判定指引与加固对照表。
核查方法
show variables like '%ssl%';
select user,host,ssl_type from mysql.user;
示例输出(节选)
mysql> show variables like '%ssl%';
+-------------------------------------+----------+
| Variable_name | Value |
+-------------------------------------+----------+
| have_openssl | YES |
| have_ssl | YES |
| require_secure_transport | ON |
| ssl_ca | /etc/mysql/ca.pem |
+-------------------------------------+----------+
mysql> select user,host,ssl_type from mysql.user;
+------------------+-----------+----------+
| user | host | ssl_type |
+------------------+-----------+----------+
| root | localhost | |
| appuser | 192.168.% | SSL |
+------------------+-----------+----------+
have_ssl/have_openssl 为 DISABLED 表示未启用加密。
加固操作
- 证书准备:5.7 用
mysql_ssl_rsa_setup;8.0 起服务启动自动生成(工具 8.0.34 弃用、8.4 移除),生产建议统一改用 CA 签发证书:
mysql_ssl_rsa_setup --datadir=/var/lib/mysql
- 配置
/etc/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
require_secure_transport = ON # 强制所有连接走 TLS(5.7+)
- 账户粒度强制加密:
ALTER USER 'user'@'host' REQUIRE SSL;
- 说明:若数据库已禁止远程管理(host 仅 localhost/127.0.0.1/::1),传输加密要求已在网络层闭环,可不启用 SSL(报告中说明即可)。
06 远程管理与主机限制
对应控制点:GB/T 22239-2019 8.1.4.1 身份鉴别 c)(远程管理时防止鉴别信息在传输中被窃听)、8.1.2.2 通信传输 a)b)
加固要点:数据库远程管理一律走加密通道并限制来源:禁用明文管理方式,管理连接使用 SSH 隧道、堡垒机或已启用 TLS 的原生协议(PostgreSQL 关闭
host ... trust行、MongoDB 3.6+ 已移除 HTTP 状态接口须确认未启用旧版net.http.enabled、MySQL 关闭不需要的管理插件与端口);SSH 侧禁止 root 直接登录、优先密钥认证;数据库监听端口只放行运维网段与堡垒机地址,不得对办公终端区或互联网全开放。管理账户与来源限制清单须与运维台账一致。验证方法:
ss -tlnp确认监听地址与端口、pg_hba.conf/sys_hba.conf中的管理来源行、堡垒机纳管清单与运维会话录像策略、从非授权地址连接被拒的实测记录、SSH 配置回显(sshd -T | grep -Ei "permitrootlogin|ciphers")。
数据库远程管理仍使用明文协议或未限制管理来源,管理端口直接对互联网开放,鉴别信息可被嗅探、管理入口可被爆破时,按《高风险判定指引》可直接判高风险。
判定口径详见 22、高风险判定指引与加固对照表。
核查方法
select user,host from mysql.user where user='root';
select user,host from mysql.user where host = '%'; -- host 为 % 即不限来源
加固操作
- root 禁止远程:root 的 host 应仅为
localhost/127.0.0.1/::1; - 业务账户限定来源网段(精确到网段或 IP,避免 %):
GRANT ALL PRIVILEGES ON student.* TO 'teacher'@'192.168.56.%' IDENTIFIED BY 'Admin123' WITH GRANT OPTION;
FLUSH PRIVILEGES;
<databases-name> 为授权库(* 为全部库);host 支持 IP/网段(如 192.168.1.%)/%;密码需符合复杂度要求。
- 清理多余账户(注意 drop 与 delete 的区别):
select user,host from mysql.user where account_locked='N' and host!='localhost';
drop user 'user'@'host'; -- drop 同步清理各权限表
delete from mysql.user where user='xxx' and host='localhost';
flush privileges; -- 用 delete 方式删必须执行 flush
07 连接数限制
对应控制点:GB/T 22239-2019 8.1.4.4 入侵防范 a)~f)(最小安装与组件收敛、监听与端口限制、危险能力关闭、漏洞与补丁管理)
核查方法
show variables like "%connections%";
加固操作(my.cnf):max_connections = 100(全实例上限,按业务容量评估);max_user_connections = 50(单账户上限,0 为不限)。此项属可用性/资源保护类要求,测评结合业务量判定。
08 日志与审计
对应控制点:GB/T 22239-2019 8.1.4.3 安全审计 a)~d)(数据库审计策略、审计记录内容、留存与保护)
加固要点:启用数据库审计并覆盖:用户登录注销、账户与权限变更(DDL/DCL)、对敏感数据与关键表的访问、审计策略自身的修改;审计记录须包含事件日期时间、用户、事件类型、是否成功、客户端地址等要素;审计功能由独立的安全审计员账户管理,系统管理员不得删除或篡改审计记录;审计日志留存不少于 6 个月并定期备份,容量写满时按策略告警而非静默覆盖。社区版无原生审计能力时(PostgreSQL 需 pgAudit、MongoDB 社区版无 auditLog、MySQL 社区版无 audit_log),须部署数据库审计系统、堡垒机或操作系统层审计作为替代,并在报告中写明测评单元边界与替代措施的实际效果。
验证方法:审计开关与审计策略配置回显(PostgreSQL
SHOW shared_preload_libraries;含 pgaudit +pgaudit.log参数 +\dx确认扩展已创建;MySQLSHOW VARIABLES LIKE '%audit%';或企业版audit_log_policy;MongoDB 企业版auditLog配置段;达梦与金仓的审计参数与审计项/审计对象配置结果)+ 一段真实审计记录样例(含时间、用户、来源 IP、操作对象、结果)+ 审计记录留存起始时间与备份记录 + 用系统管理员账户尝试删除审计记录被拒的实测。
数据库未启用任何审计且承载敏感数据,或审计记录可由系统管理员账户自行关闭与删除、留存不足 6 个月,安全事件无法溯源时按高风险线索记录(多与访问控制、剩余信息保护不符合项合并判定)。
判定口径详见 22、高风险判定指引与加固对照表。
旧版文章称"MySQL 默认启用日志审计,此项默认符合"——不成立:general_log 默认关闭;错误日志默认开启但不记录操作明细。测评应按日志类别分别判定,通常为部分符合,整改见下。
核查方法
show variables like 'log%';
show variables like 'general_log%';
show variables like 'slow_query_log%';
示例输出(节选)
mysql> show variables like 'general_log%';
+------------------+-------------------------------+
| Variable_name | Value |
+------------------+-------------------------------+
| general_log | ON |
| general_log_file | /var/log/mysql/mysql.log |
+------------------+-------------------------------+
加固操作(my.cnf,按需开启):
[mysqld]
log_timestamps = SYSTEM # 日志时间戳用系统时区
general_log = ON # 一般查询日志:记录所有 SQL(含审计价值;磁盘开销大,按需)
general_log_file = /var/log/mysql/mysql.log
log_error = /var/log/mysql/error.log
slow_query_log = ON
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 2
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log # 二进制日志
expire_logs_days = 30 # 8.0 起推荐改用 binlog_expire_logs_seconds = 2592000
审计要求落地方式(任选,测评均可认可):
- 开启 general_log 并转发至集中日志服务器(留存 ≥6 个月);
- 使用企业审计类组件(MySQL Enterprise Audit / Percona Audit Log Plugin);
- 前置数据库审计网关/日志审计设备采集。
日志留存与轮转(logrotate,/etc/logrotate.d/mysql):
/var/log/mysql/*.log {
daily
rotate 26
compress
missingok
create 640 mysql adm
postrotate
mysqladmin -uroot -p'口令' flush-logs
endscript
}
时间同步:主机需配置 NTP 保证日志时间准确(ntpq -p -n、ntpstat 核查,配置见 11 号)。
09 禁止 .mysql_history 记录敏感操作
对应控制点:GB/T 22239-2019 8.1.4.10 剩余信息保护 a)b)(鉴别信息与敏感数据所在存储空间释放前清除;数据库侧含会话历史文件、临时表、回收站对象与导出中间文件)
加固要点:鉴别信息与敏感数据所在存储空间在释放或重新分配前须清除:核查会话历史与客户端记录文件不含明文口令与敏感查询(MySQL 的
.mysql_history须禁用或重定向、PostgreSQL 的.psql_history、客户端脚本与 CI 日志中的连接串);删除的敏感表、表空间与数据文件须确认物理文件已移除而非仅逻辑删除(PostgreSQLDROP TABLESPACE后核验目录、达梦与 Oracle 系的回收站对象须PURGE);临时表、导出中间文件与过期备份按周期清理;口令散列不得以明文形式出现在配置、脚本与日志中。验证方法:
MYSQL_HISTFILE与--histignore配置、~/.mysql_history与~/.psql_history抽样检索是否存在明文口令的结果、数据目录与备份目录中残留中间文件清单、删除敏感对象后物理文件不存在的核验截图、口令散列存储方式回显。
客户端历史文件(.mysql_history/.psql_history)、备份导出的中间文件或代码仓库中存在明文口令与敏感数据,其他本地账户或离职人员可直接读取时,按高风险线索记录。
判定口径详见 22、高风险判定指引与加固对照表。
.mysql_history 会记录交互式 SQL 历史(含敏感语句)。核查与处理:
find / -name ".mysql_history" 2>/dev/null
rm -f /root/.mysql_history
ln -s /dev/null /root/.mysql_history
同时可导出 MYSQL_HISTFILE=/dev/null 环境变量。
10 文件读写防护(local_infile 与 secure_file_priv)
对应控制点:GB/T 22239-2019 8.1.4.4 入侵防范 a)~f)(最小安装与组件收敛、监听与端口限制、危险能力关闭、漏洞与补丁管理)
核查方法
show variables like 'local_infile';
show variables like 'secure_file_priv';
加固操作(my.cnf):
[mysqld]
local_infile = 0 # 禁用 LOAD DATA LOCAL INFILE(客户端侧任意文件读取)
secure_file_priv = /var/lib/mysql-files # 限定 LOAD_FILE/INTO OUTFILE 目录;NULL 为完全禁用
symbolic-links = 0 # 禁用符号链接,防通过链接跳转读写任意文件
- 说明:
secure_file_priv为空字符串(默认旧版本)表示不限路径,配合 FILE 权限可导出 webshell,属测评高频问题;普通业务账户不应授予 FILE 权限(select user,host,file_priv from mysql.user;)。
11 权限最小化与三权分立
对应控制点:GB/T 22239-2019 8.1.4.2 访问控制 a)d)f)(数据目录与关键文件权限、运行账户、特权存储过程与外部命令执行能力)
加固要点:数据库运行账户与文件权限最小化:实例不得以 root 或 Administrator 运行(PostgreSQL 强制非 root 启动、MySQL 使用
mysql系统账户、MongoDB 使用mongod账户、Windows 侧使用低权限专用服务账户);数据目录、配置文件、备份目录与日志目录权限收敛到运行账户(Linux 0700/0600,Windows 移除 Users 的完全控制),防止其他本地账户直接读写数据文件绕过数据库鉴权;数据库内特权能力(外部命令执行、文件读写、链接服务器、SUPER、COPY ... PROGRAM、达梦与金仓的系统包)按账户逐一收敛,禁止业务账户持有。验证方法:
ps -ef | grep -E "mysqld|postgres|mongod|dmserver"与Get-CimInstance Win32_Service确认运行账户、ls -ld或stat输出数据目录与关键文件权限、Windows 侧icacls输出、数据库内特权账户清单与特权能力授予情况(SHOW GRANTS、pg_roles.rolsuper、MongoDB 持有root/clusterAdmin角色的账户)。
数据库实例以 root 或 Administrator 运行,或数据目录与备份目录对普通本地账户可写,攻击者取得任一本地低权限账户即可直接改写数据文件绕过数据库鉴权,按高风险线索记录。
判定口径详见 22、高风险判定指引与加固对照表。
核查方法
select user,host,account_locked from mysql.user;
show grants for 'user'@'host';
select * from mysql.user where user='user' and host='host'\G
加固操作
- 按业务建专用账户,一库一账户、按需授权(禁止
GRANT ALL ON *.*); - mysql 系统库仅限 DBA 管理;不存在特权账户与越权访问;
- 三权分立示例:
sysadmin(业务运维)、secadmin(账户与权限管理)、audadmin(日志与审计查询),各司其职,避免一人全权; - mysql 进程不以 root 运行:
ps -ef | grep mysqld,应为 mysql 用户。
12 数据备份恢复
对应控制点:GB/T 22239-2019 8.1.4.9 数据备份恢复 a)~c)(本地备份、异地实时备份与热冗余)
加固要点:建立并实际执行备份策略:本地定时全量 + 增量或日志备份(MySQL
mysqldump/mysqlpump配合 binlog、PostgreSQLpg_dump/pg_basebackup配合 WAL 归档、MongoDBmongodump配合 oplog 或文件系统快照、达梦与金仓使用自带备份工具),备份文件与主数据分机存放并异地留存(三级要求异地实时备份或热冗余),备份数据同样加密并限制访问权限;每半年至少一次恢复演练并留存演练记录,RTO/RPO 与业务要求匹配。仅有备份脚本而无恢复验证不判符合。验证方法:备份策略与计划任务配置、最近若干次备份任务的执行日志与产物清单(大小、时间、存放位置)、异地备份或热冗余证据(异地备份目录、流复制或副本集状态:
SHOW REPLICA STATUS\G、SELECT * FROM pg_stat_replication;、rs.status())、恢复演练记录(时间、参与人、恢复耗时、数据一致性校验结果)、备份文件权限与加密方式。
核心业务数据库无任何备份,或备份与主数据同机同盘存放、从未做过恢复演练导致备份实际不可用,一旦数据被破坏或遭勒索加密即无法恢复,按《高风险判定指引》可直接判高风险。
判定口径详见 22、高风险判定指引与加固对照表。
核查方法:crontab -l 备份任务;备份文件存在性与时效;恢复演练记录。
加固操作
# 逻辑全备(InnoDB 推荐 --single-transaction)
mysqldump -uroot -p --single-transaction --all-databases --master-data=2 \
| gzip > /backup/mysql_all_$(date +%F).sql.gz
chmod 600 /backup/mysql_all_*.sql.gz
# crontab 每日 1:30
30 1 * * * /usr/bin/mysqldump -uroot -p'口令' --single-transaction --all-databases | gzip > /backup/mysql_all_$(date +\%F).sql.gz
- 备份目录与文件权限 600/700,与数据盘分离;
- 异地备份:将备份推送至备份服务器/异地机房(rsync/scp over ssh);
- 定期恢复演练并记录(
mysql -uroot -p < 恢复文件或 xtrabackup 流程)。
13 版本差异速查(5.6 / 5.7 / 8.0 / 8.4)
| 事项 | 5.6/5.7 | 8.0 | 8.4/9.x |
|---|---|---|---|
| 密码策略 | validate_password 插件(5.6.6+,plugin-load) | component_validate_password 组件(INSTALL COMPONENT 'file://component_validate_password'),变量名相同 | 同 8.0 |
| 口令字段 | 5.6 password;5.7 authentication_string | authentication_string | 同 |
| 默认认证插件 | mysql_native_password | caching_sha2_password(老客户端需兼容配置) | caching_sha2_password;mysql_native_password 默认禁用(9.0 移除),default_authentication_plugin 选项已删除 |
| TLS 证书 | 5.7 用 mysql_ssl_rsa_setup | 启动自动生成;工具 8.0.34 起弃用 | 工具已移除(8.4),启动自动生成 |
| binlog 保留 | expire_logs_days | binlog_expire_logs_seconds(推荐) | 同 8.0 |
| 口令有效期 | default_password_lifetime(5.7+,0=不过期,设 180 天) | 同 | 同 |
| 登录失败延迟 | connection_control(5.7.17+) | 同 | 同 |
参考依据
- GB/T 22239-2019《信息安全技术 网络安全等级保护基本要求》(8.1.4 安全计算环境各控制点(数据库管理系统自身安全);涉客户端与服务端通信时另含 8.1.2 安全通信网络):http://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=BAFB47E8874764186BDB7865E8344DAF
- GB/T 28448-2019《信息安全技术 网络安全等级保护测评要求》(测评对象边界认定、单元测评实施与结果判定:符合/部分符合/不符合/不适用):http://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=7E736CDF4502B6FF1258DD250AA3EC8C
- GB/T 22240-2020《信息安全技术 网络安全等级保护定级指南》、GB/T 25070-2019《安全设计技术要求》、GB/T 28449-2018《测评过程指南》,可在全国标准信息公共服务平台检索:http://openstd.samr.gov.cn/bzgk/gb/
- MySQL 官方参考手册(Server Administration / Security / validate_password / connection_control):https://dev.mysql.com/doc/
- 《网络安全等级保护测评高风险判定指引》(中关村信息安全测评联盟团体标准)——高风险情形判定口径,站内对照表:22、高风险判定指引与加固对照表
- 命令核验说明:MySQL 参数与命令以 MySQL 官方参考手册(Server Administration / Security / Replication)核验(核验日期 2026-09-02)。五处须留意:① 口令校验在 8.0 是
validate_password组件、参数写作validate_password.policy,在 5.7 是插件、参数写作validate_password_policy,安装语句分别为INSTALL COMPONENT 'file://component_validate_password';与INSTALL PLUGIN validate_password SONAME 'validate_password.so';,跨版本套用会直接报错;②connection_control插件须先安装并写入[mysqld]段的plugin-load-add,重启后以SHOW VARIABLES LIKE 'connection_control%';核验,社区版无 audit_log 插件须以企业版、Percona/MariaDB Server Audit 或外部数据库审计系统替代;③require_secure_transport=ON会拒绝所有非 TLS 连接,启用前须确认全部客户端(含备份脚本、监控探针、复制通道)已配置证书,否则业务立即中断,建议先按账户REQUIRE SSL灰度;④ 8.0 默认认证插件为caching_sha2_password,老旧客户端与部分驱动不支持,升级后出现连接失败时应优先升级驱动而非全局回退mysql_native_password(回退会降低散列强度,须在报告中记录原因);⑤wait_timeout收紧到 300~600 秒会影响使用长连接池的应用,须同步调整连接池的maxIdleTime/testOnBorrow,避免应用侧出现大量重连报错。