第30章:MySQL安全加固
第30章:MySQL安全加固
构建安全的数据库环境
30.1 安全加固概述
30.1.1 安全威胁
常见威胁:
- SQL注入攻击
- 暴力破解
- 权限滥用
- 数据泄露
- 拒绝服务攻击(DoS)
30.2 账户安全 ⭐⭐⭐⭐⭐
30.2.1 删除默认账户
删除匿名用户和测试数据库:
-- 查看所有用户
SELECT user, host FROM mysql.user;
-- 删除匿名用户
DELETE FROM mysql.user WHERE user = '';
-- 删除test数据库
DROP DATABASE IF EXISTS test;
-- 刷新权限
FLUSH PRIVILEGES;
30.2.2 禁用root远程登录
只允许root本地登录:
-- 查看root用户
SELECT user, host FROM mysql.user WHERE user = 'root';
-- 删除root远程登录
DELETE FROM mysql.user WHERE user = 'root' AND host != 'localhost';
-- 或修改root只能本地登录
UPDATE mysql.user SET host = 'localhost' WHERE user = 'root';
FLUSH PRIVILEGES;
30.2.3 强密码策略
配置密码策略:
# my.cnf
[mysqld]
# 密码验证插件
validate_password.policy = STRONG
validate_password.length = 12
validate_password.mixed_case_count = 1
validate_password.number_count = 1
validate_password.special_char_count = 1
# 密码过期
default_password_lifetime = 90
# 密码重用限制
password_history = 5
password_reuse_interval = 365
修改用户密码:
-- 设置密码过期
ALTER USER 'app_user'@'localhost' PASSWORD EXPIRE INTERVAL 90 DAY;
-- 设置密码历史
ALTER USER 'app_user'@'localhost' PASSWORD HISTORY 5;
-- 设置密码重用间隔
ALTER USER 'app_user'@'localhost' PASSWORD REUSE INTERVAL 365 DAY;
30.2.4 限制登录失败次数
配置登录失败锁定:
-- MySQL 8.0.19+
ALTER USER 'app_user'@'localhost'
FAILED_LOGIN_ATTEMPTS 3
PASSWORD_LOCK_TIME 1; -- 锁定1天
-- 解锁用户
ALTER USER 'app_user'@'localhost' ACCOUNT UNLOCK;
30.3 网络安全 ⭐⭐⭐⭐⭐
30.3.1 绑定IP地址
只监听内网IP:
# my.cnf
[mysqld]
bind-address = 192.168.1.10
# 或只监听本地
bind-address = 127.0.0.1
30.3.2 修改默认端口
修改默认端口(3306):
# my.cnf
[mysqld]
port = 13306
30.3.3 防火墙配置
配置防火墙:
# CentOS/RHEL
# 只允许指定IP访问MySQL
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="3306" accept'
firewall-cmd --reload
# Ubuntu
# 只允许指定IP访问MySQL
ufw allow from 192.168.1.0/24 to any port 3306
ufw enable
30.4 SSL/TLS加密 ⭐⭐⭐⭐
30.4.1 生成SSL证书
生成证书:
# 使用mysql_ssl_rsa_setup生成证书(MySQL 5.7+)
mysql_ssl_rsa_setup --datadir=/var/lib/mysql
# 查看生成的证书
ls -l /var/lib/mysql/*.pem
# ca.pem:CA证书
# server-cert.pem:服务器证书
# server-key.pem:服务器私钥
# client-cert.pem:客户端证书
# client-key.pem:客户端私钥
30.4.2 配置SSL
服务器配置:
# 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
# 要求所有连接使用SSL
require_secure_transport = ON
查看SSL状态:
-- 查看SSL变量
SHOW VARIABLES LIKE '%ssl%';
-- 查看当前连接是否使用SSL
SHOW STATUS LIKE 'Ssl_cipher';
30.4.3 要求用户使用SSL
创建要求SSL的用户:
-- 创建用户并要求SSL
CREATE USER 'secure_user'@'%' IDENTIFIED BY 'Password@123' REQUIRE SSL;
-- 修改现有用户要求SSL
ALTER USER 'app_user'@'%' REQUIRE SSL;
-- 要求X509证书
ALTER USER 'app_user'@'%' REQUIRE X509;
客户端连接:
# 使用SSL连接
mysql -u secure_user -p \
--ssl-ca=/path/to/ca.pem \
--ssl-cert=/path/to/client-cert.pem \
--ssl-key=/path/to/client-key.pem
30.5 审计日志 ⭐⭐⭐⭐
30.5.1 开启审计日志
使用audit_log插件(MySQL Enterprise):
-- 安装插件
INSTALL PLUGIN audit_log SONAME 'audit_log.so';
-- 配置
SET GLOBAL audit_log_policy = ALL;
SET GLOBAL audit_log_format = JSON;
使用general_log(不推荐生产环境):
-- 开启general_log
SET GLOBAL general_log = ON;
SET GLOBAL general_log_file = '/var/log/mysql/general.log';
-- 查看日志
tail -f /var/log/mysql/general.log
30.5.2 监控可疑活动
监控登录失败:
# 查看错误日志中的登录失败
grep "Access denied" /var/log/mysql/error.log
30.6 数据加密 ⭐⭐⭐⭐
30.6.1 表空间加密
开启表空间加密(MySQL 5.7+):
-- 创建加密表
CREATE TABLE sensitive_data (
id INT PRIMARY KEY,
credit_card VARCHAR(100)
) ENCRYPTION = 'Y';
-- 修改现有表为加密表
ALTER TABLE users ENCRYPTION = 'Y';
配置加密密钥:
# my.cnf
[mysqld]
early-plugin-load = keyring_file.so
keyring_file_data = /var/lib/mysql-keyring/keyring
30.6.2 binlog加密
开启binlog加密(MySQL 8.0.14+):
SET GLOBAL binlog_encryption = ON;
30.7 SQL注入防护 ⭐⭐⭐⭐⭐
30.7.1 使用预处理语句
预处理语句(推荐):
-- ✅ 使用预处理语句(安全)
PREPARE stmt FROM 'SELECT * FROM users WHERE id = ?';
SET @id = 1;
EXECUTE stmt USING @id;
-- 应用程序中使用参数化查询
-- Java: PreparedStatement
-- Python: cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
-- PHP: $stmt->bind_param("i", $user_id);
避免拼接SQL:
-- ❌ 不安全:SQL拼接
SELECT * FROM users WHERE name = 'admin' OR '1'='1';
-- ✅ 安全:预处理语句
PREPARE stmt FROM 'SELECT * FROM users WHERE name = ?';
30.8 安全配置清单
30.8.1 my.cnf安全配置
推荐配置:
[mysqld]
# 1. 网络安全
bind-address = 192.168.1.10
port = 13306
# 2. SSL/TLS
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
# 3. 密码策略
validate_password.policy = STRONG
validate_password.length = 12
default_password_lifetime = 90
# 4. 禁用危险功能
local_infile = OFF
skip-symbolic-links
# 5. 日志
log_error = /var/log/mysql/error.log
slow_query_log = ON
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
# 6. 限制
max_connections = 500
max_connect_errors = 10
30.8.2 安全检查清单
检查项:
- [ ] 删除匿名用户
- [ ] 禁用root远程登录
- [ ] 删除test数据库
- [ ] 配置强密码策略
- [ ] 绑定内网IP
- [ ] 配置防火墙
- [ ] 开启SSL/TLS
- [ ] 最小权限原则
- [ ] 定期备份
- [ ] 监控审计日志
- [ ] 禁用local_infile
- [ ] 定期更新MySQL版本
30.9 本章总结
本章学习内容:
- ✅ 安全加固概述
- ✅ 账户安全(删除默认账户、强密码)⭐⭐⭐⭐⭐
- ✅ 网络安全(绑定IP、防火墙)⭐⭐⭐⭐⭐
- ✅ SSL/TLS加密⭐⭐⭐⭐
- ✅ 审计日志⭐⭐⭐⭐
- ✅ 数据加密⭐⭐⭐⭐
- ✅ SQL注入防护⭐⭐⭐⭐⭐
- ✅ 安全配置清单
重点掌握:
- 删除匿名用户和test数据库
- 禁用root远程登录
- 配置SSL/TLS
- 使用预处理语句防止SQL注入
- 最小权限原则
安全措施:
- 账户安全:强密码、删除默认账户
- 网络安全:绑定IP、防火墙、SSL
- 数据安全:加密、备份
- 审计:日志监控
面试重点:
- 如何加固MySQL安全
- 如何防止SQL注入
- 如何配置SSL
- 安全配置清单
下一章预告: 企业级实战案例
练习题
- 如何删除匿名用户?
- 如何禁用root远程登录?
- 如何配置强密码策略?
- 如何配置SSL/TLS?
- 如何防止SQL注入?
- 如何开启审计日志?
- 如何加密表数据?
- 安全配置清单有哪些?
- 如何限制登录失败次数?
- 实战:加固一个MySQL服务器
继续学习: 第31章:企业级实战案例