MySQL数据库安全加固实战:防注入、权限最小化与远程访问控制完整教程

数据库是网站最核心的资产,也是攻击者最想拿到的东西。根据安全机构的统计,Web 攻击中 SQL 注入、弱口令爆破、未授权访问常年占据高危漏洞榜单前三名。很多站长把精力都放在 Nginx、PHP 加固上,却忽略了 MySQL 本身——结果就是网站被脱库、数据被勒索,甚至整个服务器被拖入挖矿肉鸡大军。这篇文章不讲虚的,直接给你一套可以照抄的 MySQL/MariaDB 安全加固方案,从权限最小化、远程访问控制到 SQL 注入防护,每一步都附上可执行的代码。

第一步:账号权限最小化,别再用 root 连网站

在宝塔面板里建站,默认会用 root 账号连接数据库,这是最危险的用法。一旦网站代码存在 SQL 注入漏洞,攻击者拿到的就是数据库的最高权限,可以读写所有库、执行所有命令。正确的做法是:每个网站单独建库、单独建账号,权限只给该库的增删改查,绝不授予 FILE、PROCESS、SUPER 等高危权限。

-- 1. 为网站创建独立数据库
CREATE DATABASE IF NOT EXISTS zhujib_com DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 2. 创建独立账号,密码强度至少 16 位混合字符
CREATE USER 'zhujib_user'@'localhost' IDENTIFIED BY 'Your-Str0ng-P@ssw0rd-2026';

-- 3. 只授予该库的常用权限,注意不要用 GRANT ALL
GRANT SELECT, INSERT, UPDATE, DELETE ON zhujib_com.* TO 'zhujib_user'@'localhost';

-- 4. 刷新权限立即生效
FLUSH PRIVILEGES;

同时要定期清理高危账号和匿名账号,这一步可以用官方提供的安全初始化脚本一键完成:

# 交互式安全初始化:删匿名账号、禁止 root 远程登录、移除测试库
mysql_secure_installation

# 非交互式核查当前所有账号,重点看 host 是否为 % 
SELECT user, host, authentication_string FROM mysql.user;
# 发现 host 为 '%' 的 root 或空密码账号,立即删除
DROP USER 'root'@'%';
FLUSH PRIVILEGES;

注意:mysql_secure_installation 会要求设置 root 密码并移除匿名用户,执行前请确保已备份数据库。如果你的网站是 WordPress,wp-config.php 中的 DB_USER、DB_PASSWORD 也要同步改成新账号,改完记得给配置文件设置 644 权限,避免被旁站读取。

第二步:封死远程访问,数据库只对应用服务器开放

MySQL 默认监听 3306 端口,如果这个端口直接暴露在公网,攻击者就能用工具对数据库进行暴力破解。很多被脱库的案例,根因就是 3306 裸奔在公网,弱口令一猜就中。正确的姿势:让 MySQL 只监听内网 IP,公网一律不放行。

# 编辑 MySQL 配置文件(宝塔面板:/etc/my.cnf 或 /etc/mysql/my.cnf)
[mysqld]
# 只监听本机,如果是独立数据库服务器,改为内网 IP 如 10.0.0.5
bind-address = 127.0.0.1
# 关闭 skip-networking 不影响本地 socket 连接
# 重启生效
systemctl restart mysqld   # CentOS
systemctl restart mysql    # Debian/Ubuntu

如果应用和数据库不在同一台机器(比如前后端分离架构),那就通过防火墙做白名单放行,只允许应用服务器 IP 访问 3306 端口。宝塔面板操作路径:安全 → 防火墙 → 添加端口规则,放行 3306 并填写来源 IP;命令行方式如下:

# 仅允许应用服务器 10.0.0.8 访问本机 3306
iptables -A INPUT -p tcp -s 10.0.0.8 --dport 3306 -j ACCEPT
# 其余来源一律拒绝
iptables -A INPUT -p tcp --dport 3306 -j DROP
iptables-save > /etc/sysconfig/iptables

# 使用 firewalld 的系统:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.8" port protocol="tcp" port="3306" accept'
firewall-cmd --reload

改完之后,用命令验证 3306 端口是否还能从公网访问到:

# 从本机外的另一台服务器执行,正常情况下应超时或拒绝
nmap -p 3306 你的服务器IP
# 或使用在线端口检测工具,确认 3306 处于 closed/filtered 状态

第三步:SQL 注入防护,应用层与数据库层双管齐下

权限和端口都加固了,还要防住 SQL 注入这条最常见的攻击路径。SQL 注入的本质是攻击者把恶意 SQL 拼进了你的查询语句,所以最有效的防线永远在应用层——参数化查询。PHP 使用 PDO 预编译,Java 使用 PreparedStatement,Node.js 使用参数占位符,绝不要用字符串拼接 SQL。

// PHP PDO 参数化查询(正确示范)
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ? AND status = ?');
$stmt->execute([$_POST['email'], 1]);
$user = $stmt->fetch();

// 错误示范:直接拼接,这是 SQL 注入高危写法
// $sql = "SELECT * FROM users WHERE email = '" . $_POST['email'] . "'";

数据库层可以再加一道保险:限制单条 SQL 的长度和数量,即使应用层防御被绕过,也能把危害降到最低。同时开启查询日志和慢查询日志,便于事后溯源攻击载荷:

# my.cnf 中开启审计类日志
[mysqld]
general_log = ON
general_log_file = /var/log/mysql/access.log   # 生产环境建议按需开启,防日志膨胀
slow_query_log = ON
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2

# 配合日志做注入特征检索
grep -iE "union.*select|sleep\(|information_schema|load_file" /var/log/mysql/access.log

另外强烈建议开启系统层面的加固:禁用 MySQL 的 FILE 权限(防止 SELECT … INTO OUTFILE 写 WebShell)、设置独立低权限系统账号运行 mysqld、数据库备份文件不要放在网站根目录且名称不要用 db_2026.sql 这种可猜测的名字。

总结

数据库安全加固没有捷径,核心就三件事:权限最小化、访问受控、注入可防。用独立账号代替 root、用内网绑定和防火墙白名单封死 3306、用参数化查询堵住注入,这三步做完,你的数据库已经能挡住 90% 以上的常见攻击。如果你没有精力自己维护这套安全体系,也可以选择云数据库服务或交由速度网络的专业运维团队托管加固,把安全交给专业的人,自己专注业务。

给TA打赏
共{{data.count}}人
人已打赏
0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
在线客服
在线客服
热线电话
QQ客服
电子邮箱
suduwangluo