保护您的数据库的7大MySQL安全最佳实践

七项实用的MySQL安全检查,涵盖访问控制、网络暴露、TLS、补丁管理、日志记录和加密。

保护数据库的7大MySQL安全最佳实践

MySQL安全始于减少可连接的用户、限制其操作权限,并降低主机被攻破后的暴露风险。以下七项检查为生产数据库提供了实用的基线,而非声称单一设置就能让MySQL“安全”。

1. 安全用户访问管理

控制谁能访问数据库以及他们能做什么是第一道防线。这包括根据最小权限原则创建特定用户账户,即用户仅拥有执行任务所需的权限。

创建强账户

避免共享应用用户和弱密码。在自管理服务器上使用 mysql_secure_installation 删除匿名用户、移除测试数据库(如适用),并收紧初始root账户设置。

授予最小权限

使用 GRANT 语句指定应用所需的数据库、表和操作。避免为应用账户授予 ALL PRIVILEGES

示例:

CREATE USER 'webapp_user'@'10.0.10.%' IDENTIFIED BY 'use-a-real-secret-here';

GRANT SELECT, INSERT, UPDATE ON mydatabase.* TO 'webapp_user'@'10.0.10.%';

在正常的 CREATE USERGRANT 语句后无需执行 FLUSH PRIVILEGES。MySQL会自动更新这些语句的授权表。

定期审计账户:

SELECT user, host, account_locked FROM mysql.user ORDER BY user, host;
SHOW GRANTS FOR 'webapp_user'@'10.0.10.%';

2. 限制网络访问

限制MySQL的网络路径。有效默认值取决于MySQL版本和软件包,因此请检查运行中的服务器,而非假设它仅监听本地。

检查监听端口:

ss -ltnp | grep 3306

当仅本地客户端需要访问时,将MySQL绑定到localhost:

[mysqld]
bind-address = 127.0.0.1

如果应用服务器远程连接,则绑定到私有接口,并使用安全组、防火墙或网络ACL仅允许这些源访问端口 3306

3. 使用TLS加密连接

加密传输中的数据可防止窃听和中间人攻击。MySQL支持客户端-服务器连接的SSL/TLS加密。

服务器配置通常如下:

[mysqld]
ssl-ca=/path/to/ca.pem
ssl-cert=/path/to/server-cert.pem
ssl-key=/path/to/server-key.pem

客户端示例:

mysql -h your_host -u your_user -p --ssl-mode=REQUIRED

如需更严格的验证,请使用 --ssl-mode=VERIFY_IDENTITY,并确保主机名与证书匹配。REQUIRED 会加密连接,但不会强烈验证服务器身份。

4. 保持MySQL更新

软件漏洞经常被发现并修复。运行过时的MySQL版本可能使数据库暴露于已知漏洞。

跟踪您运行的发布流,应用安全更新,并在生产环境前在预发布环境中测试升级。如果使用托管数据库服务,请审查提供商的维护策略,并设置团队实际关注的维护窗口。

5. 强化MySQL服务器配置

除网络绑定外,其他配置选项也能增强安全性。

除非应用需要 LOAD DATA LOCAL INFILE,否则禁用 local_infile

[mysqld]
local_infile = 0

确保配置文件、TLS密钥和备份凭据仅对适当的系统用户可读。同时检查已安装的插件,移除不使用的插件。

6. 审计和监控日志

日志记录对于检测可疑活动以及安全事件后的取证分析至关重要。

MySQL Enterprise包含审计日志插件。社区部署通常根据环境使用操作系统日志、错误日志、代理日志、云数据库审计功能或第三方审计插件。

至少监控:

  • 失败的登录和身份验证错误。
  • 新用户、权限变更和特权语句。
  • 来自意外主机的连接。
  • 备份作业失败和恢复测试失败。

除非有特定的短期故障排除需求,否则不要在繁忙的生产服务器上启用通用查询日志。它可能产生大量I/O并捕获敏感的查询值。

7. 保护静态数据

SSL/TLS保护传输中的数据,而加密静态数据可在底层存储被攻破时提供保护。

使用存储或卷加密作为广泛基线。对于敏感字段,考虑应用层加密,这样数据库就不必持有解密数据所需的所有信息。

MySQL还提供加密函数,如 AES_ENCRYPT()AES_DECRYPT(),但不要将密钥硬编码在SQL中或将其与数据一起存储。

简化示例:

UPDATE users
SET sensitive_data = AES_ENCRYPT('user_private_info', @encryption_key)
WHERE user_id = 1;

SELECT AES_DECRYPT(sensitive_data, @encryption_key)
FROM users
WHERE user_id = 1;

对于实际系统,请使用适当的密钥管理流程。没有密钥轮换、访问控制和密钥材料备份的加密,可能将可恢复的事件转变为永久性数据丢失。

总结

从消除最多风险的控件开始:最小权限用户、私有网络访问、TLS、补丁管理和经过测试的备份。然后添加符合合规性和威胁模型的审计日志和加密控制。每次重大架构、基础设施或访问变更后,请重新审查设置。