MySQL全面安全加固實戰(zhàn)的全流程
前言
MySQL 加固核心目標(biāo):限制未授權(quán)訪問、最小化權(quán)限暴露、加密敏感數(shù)據(jù)、審計操作行為,以下方案覆蓋從基礎(chǔ)配置到高級防護(hù)的全流程,適配 MySQL 5.7+ / 8.0+(標(biāo)注版本差異處需重點注意)。
一、基礎(chǔ)環(huán)境加固(系統(tǒng) + 安裝層面)
1. 升級到穩(wěn)定安全版本
舊版本(如 5.6 及以下)存在大量未修復(fù)漏洞(如權(quán)限繞過、SQL 注入),優(yōu)先升級至:
- MySQL 5.7.30+(LTS 長期支持版)
- MySQL 8.0.20+(推薦,安全性更強(qiáng),默認(rèn)認(rèn)證插件更安全)
升級檢查:
SELECT VERSION(); -- 查看當(dāng)前版本
2. 以非 root 用戶運(yùn)行 MySQL
默認(rèn) MySQL 可能以 root 用戶啟動,若被入侵可能導(dǎo)致服務(wù)器提權(quán),需創(chuàng)建專用低權(quán)限用戶:
# 1. 創(chuàng)建 mysql 系統(tǒng)用戶(若未創(chuàng)建) useradd -r -s /sbin/nologin mysql # 2. 修改數(shù)據(jù)目錄/配置文件權(quán)限(Linux 示例) chown -R mysql:mysql /var/lib/mysql # 數(shù)據(jù)目錄 chown -R mysql:mysql /etc/my.cnf # 配置文件 chmod 700 /var/lib/mysql # 僅屬主可讀寫 chmod 600 /etc/my.cnf # 僅屬主可修改 # 3. 重啟 MySQL 并驗證運(yùn)行用戶 systemctl restart mysqld ps -ef | grep mysqld | grep -v grep # 確認(rèn)進(jìn)程屬主為 mysql
3. 清理無用組件與文件
- 卸載未使用的存儲引擎(如 CSV、BLACKHOLE,僅保留 InnoDB);
- 刪除安裝殘留的測試數(shù)據(jù)庫(
test庫)和示例表; - 移除無用的腳本(如
mysql_install_db舊腳本,MySQL 8.0 已廢棄)。
刪除 test 庫:
DROP DATABASE IF EXISTS test;
二、訪問控制加固(核心:限制 “誰能連、從哪連”)
1. 初始化安全配置(必做)
MySQL 提供內(nèi)置工具 mysql_secure_installation,一鍵完成基礎(chǔ)加固(需登錄 MySQL 后執(zhí)行):
mysql_secure_installation
按提示完成以下操作:
- 設(shè)置 / 修改 root 密碼(若未設(shè)置);
- 移除匿名用戶(
anonymous用戶,允許空密碼登錄); - 禁止 root 用戶遠(yuǎn)程登錄(默認(rèn)僅允許 localhost 訪問);
- 刪除 test 數(shù)據(jù)庫及匿名用戶對所有數(shù)據(jù)庫的訪問權(quán)限;
- 刷新權(quán)限表(
FLUSH PRIVILEGES)。
2. 清理冗余 / 危險用戶
(1)查看所有用戶及登錄主機(jī)
-- MySQL 5.7+ SELECT user, host, authentication_string FROM mysql.user; -- MySQL 8.0+(默認(rèn)認(rèn)證插件為 caching_sha2_password) SELECT user, host, plugin FROM mysql.user;
(2)刪除無用用戶
- 匿名用戶(
user=''或host='%'的空用戶); - 長期未使用的賬號;
- 權(quán)限過大的普通用戶。
-- 刪除匿名用戶(示例) DROP USER IF EXISTS ''@'localhost'; DROP USER IF EXISTS ''@'%'; -- 刪除指定用戶(如 test@'%') DROP USER IF EXISTS 'test'@'%'; FLUSH PRIVILEGES; -- 刷新權(quán)限
3. 限制用戶登錄主機(jī)(最小化訪問范圍)
避免用戶以 host='%'(允許所有主機(jī)登錄),僅授權(quán)信任的 IP / 網(wǎng)段:
-- 示例1:僅允許本地登錄(推薦 root 用戶) CREATE USER IF NOT EXISTS 'root'@'localhost' IDENTIFIED BY 'StrongP@ss123'; -- 示例2:允許指定 IP 登錄(如辦公網(wǎng) 192.168.1.0/24 網(wǎng)段) CREATE USER IF NOT EXISTS 'appuser'@'192.168.1.%' IDENTIFIED BY 'AppP@ss456'; -- 錯誤示例(禁止):允許所有主機(jī)登錄 CREATE USER 'baduser'@'%' IDENTIFIED BY 'weakpass'; -- 風(fēng)險極高
4. 最小權(quán)限原則分配權(quán)限
(1)拒絕給普通用戶高危權(quán)限
以下權(quán)限僅授予 root 或管理員,禁止給應(yīng)用用戶:
SUPER:修改全局參數(shù)、終止線程(可能用于提權(quán));FILE:讀寫服務(wù)器文件(可能泄露敏感數(shù)據(jù)或?qū)懭霅阂馕募?/li>SHUTDOWN:關(guān)閉 MySQL 服務(wù);CREATE USER:創(chuàng)建 / 刪除用戶(權(quán)限濫用風(fēng)險);ALTER/DROP:修改 / 刪除表(誤操作或惡意破壞)。
(2)應(yīng)用用戶權(quán)限示例(僅授予必要權(quán)限)
-- 給應(yīng)用用戶僅授予指定庫的查詢/插入/更新權(quán)限 GRANT SELECT, INSERT, UPDATE ON appdb.* TO 'appuser'@'192.168.1.%'; -- 給只讀用戶僅授予查詢權(quán)限 GRANT SELECT ON appdb.* TO 'readuser'@'192.168.1.%'; FLUSH PRIVILEGES;
(3)定期回收未使用權(quán)限
-- 查看用戶權(quán)限 SHOW GRANTS FOR 'appuser'@'192.168.1.%'; -- 回收權(quán)限(如回收 UPDATE 權(quán)限) REVOKE UPDATE ON appdb.* FROM 'appuser'@'192.168.1.%';
三、密碼安全加固(防止暴力破解)
1. 設(shè)置強(qiáng)密碼策略
(1)MySQL 5.7+ 配置(通過validate_password插件)
-- 啟用密碼驗證插件(默認(rèn)已啟用,若未啟用則執(zhí)行) INSTALL PLUGIN validate_password SONAME 'validate_password.so'; -- 查看當(dāng)前密碼策略 SHOW VARIABLES LIKE 'validate_password%'; -- 設(shè)置強(qiáng)密碼規(guī)則(修改 my.cnf 永久生效) [mysqld] validate_password_length = 12 # 密碼最小長度 12 位 validate_password_policy = STRONG # 強(qiáng)策略(需包含大小寫、數(shù)字、特殊字符) validate_password_special_char_count = 1 # 至少 1 個特殊字符 validate_password_mixed_case_count = 1 # 至少 1 個大小寫字母
(2)MySQL 8.0+ 配置(默認(rèn)啟用validate_password,策略更嚴(yán)格)
-- 8.0 新增參數(shù),禁止密碼與用戶名/主機(jī)名相同 SET GLOBAL validate_password_check_user_name = ON; -- 永久生效(my.cnf) [mysqld] validate_password_length = 12 validate_password_policy = STRONG validate_password_check_user_name = ON
2. 定期更換密碼 + 密碼過期策略
-- 設(shè)置用戶密碼過期時間(90 天,MySQL 5.7+ 支持) ALTER USER 'appuser'@'192.168.1.%' PASSWORD EXPIRE INTERVAL 90 DAY; -- 強(qiáng)制用戶下次登錄修改密碼 ALTER USER 'appuser'@'192.168.1.%' PASSWORD EXPIRE FORCE; -- 禁止重復(fù)使用最近 5 次密碼(MySQL 8.0+ 支持) SET GLOBAL password_history = 5;
3. 禁用明文存儲密碼
- MySQL 5.7+ 默認(rèn)使用
mysql_native_password插件(哈希存儲,仍有破解風(fēng)險); - MySQL 8.0+ 默認(rèn)使用
caching_sha2_password插件(更安全,支持加鹽哈希),建議所有用戶切換至此插件:
-- 修改用戶認(rèn)證插件(MySQL 8.0+) ALTER USER 'appuser'@'192.168.1.%' IDENTIFIED WITH caching_sha2_password BY 'NewStrongP@ss789'; -- 全局默認(rèn)使用 caching_sha2_password(my.cnf) [mysqld] default_authentication_plugin = caching_sha2_password
四、網(wǎng)絡(luò)安全加固(防止網(wǎng)絡(luò)層面攻擊)
1. 綁定內(nèi)網(wǎng) IP,禁止公網(wǎng)監(jiān)聽
默認(rèn) MySQL 監(jiān)聽 0.0.0.0(所有網(wǎng)卡),易被公網(wǎng)掃描,修改 my.cnf 綁定內(nèi)網(wǎng) IP:
[mysqld] bind-address = 192.168.1.100 # 僅監(jiān)聽內(nèi)網(wǎng) IP # 若無需遠(yuǎn)程訪問,直接綁定 localhost # bind-address = 127.0.0.1
重啟 MySQL 后驗證:
netstat -tuln | grep 3306 # 確認(rèn)僅監(jiān)聽指定 IP:3306
2. 防火墻限制 3306 端口訪問
僅允許信任的 IP / 網(wǎng)段訪問 MySQL 端口(3306),禁止公網(wǎng)開放。
(1)Linux 防火墻(firewalld)
# 允許 192.168.1.0/24 網(wǎng)段訪問 3306 firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="3306" accept' # 禁止其他所有 IP 訪問 3306 firewall-cmd --permanent --remove-port=3306/tcp # 重新加載防火墻規(guī)則 firewall-cmd --reload # 驗證規(guī)則 firewall-cmd --list-rich-rules
(2)Windows 防火墻
在 “高級設(shè)置” 中創(chuàng)建入站規(guī)則:僅允許指定 IP 訪問 3306 端口,拒絕其他所有。
3. 啟用 SSL/TLS 加密傳輸(防止數(shù)據(jù)竊聽)
MySQL 傳輸默認(rèn)明文,需啟用 SSL 加密客戶端與服務(wù)器的通信(MySQL 5.7+ 支持,8.0+ 默認(rèn)推薦)。
(1)生成 SSL 證書(自簽或 CA 簽發(fā))
# 生成 CA 證書(有效期 3650 天) openssl genrsa 2048 > ca-key.pem openssl req -new -x509 -nodes -days 3650 -key ca-key.pem > ca.pem # 生成服務(wù)器證書 openssl req -newkey rsa:2048 -days 3650 -nodes -keyout server-key.pem > server-req.pem openssl rsa -in server-key.pem -out server-key.pem openssl x509 -req -in server-req.pem -days 3650 -CA ca.pem -CAkey ca-key.pem -set_serial 01 > server-cert.pem # 生成客戶端證書(供應(yīng)用連接使用) openssl req -newkey rsa:2048 -days 3650 -nodes -keyout client-key.pem > client-req.pem openssl rsa -in client-key.pem -out client-key.pem openssl x509 -req -in client-req.pem -days 3650 -CA ca.pem -CAkey ca-key.pem -set_serial 02 > client-cert.pem # 修改證書權(quán)限(僅 mysql 用戶可讀) chmod 600 *.pem chown mysql:mysql *.pem mv *.pem /etc/mysql/ssl/ # 移動到安全目錄
(2)配置 MySQL 啟用 SSL(my.cnf)
[mysqld] ssl-ca = /etc/mysql/ssl/ca.pem ssl-cert = /etc/mysql/ssl/server-cert.pem ssl-key = /etc/mysql/ssl/server-key.pem # 強(qiáng)制客戶端使用 SSL 連接(可選,增強(qiáng)安全性) require_secure_transport = ON # MySQL 8.0+ 支持;5.7 用 ssl=1
(3)驗證 SSL 啟用
-- 服務(wù)器端驗證 SHOW VARIABLES LIKE '%ssl%'; # 若 have_ssl 為 YES 則啟用成功 -- 客戶端連接驗證(需攜帶證書) mysql -u appuser -p -h 192.168.1.100 --ssl-ca=/etc/mysql/ssl/ca.pem --ssl-cert=/etc/mysql/ssl/client-cert.pem --ssl-key=/etc/mysql/ssl/client-key.pem -- 連接后驗證 SSL 狀態(tài) STATUS; # 查看 SSL 行是否為 Cipher in use: xxx
4. 禁用 LOAD DATA LOCAL INFILE(防止文件泄露)
LOAD DATA LOCAL INFILE 允許客戶端讀取服務(wù)器本地文件,可能被利用泄露敏感數(shù)據(jù)(如 /etc/passwd),禁用:
[mysqld] local-infile = 0 # 服務(wù)器端禁用 [mysql] local-infile = 0 # 客戶端禁用
五、數(shù)據(jù)安全加固(保護(hù)數(shù)據(jù)不泄露、不丟失)
1. 啟用 InnoDB 透明加密(TDE,MySQL 8.0.16+ 支持)
對數(shù)據(jù)文件加密,防止磁盤被盜導(dǎo)致數(shù)據(jù)泄露:
[mysqld] innodb_encrypt_tables = ON # 全局啟用表加密 innodb_encrypt_log = ON # 重做日志加密 innodb_encryption_threads = 4 # 加密線程數(shù) innodb_encryption_rotate_key_age = 90 # 90 天輪換密鑰
(1)創(chuàng)建加密密鑰(需先設(shè)置密鑰環(huán)插件)
-- 啟用密鑰環(huán)插件(my.cnf 中配置) [mysqld] early-plugin-load-add = keyring_file.so keyring_file_data = /var/lib/mysql-keyring/keyring # 密鑰存儲路徑 -- 創(chuàng)建加密表(自動加密) CREATE TABLE appdb.user (id INT, name VARCHAR(20)) ENGINE=InnoDB;
2. 敏感字段應(yīng)用層加密
對密碼、手機(jī)號、身份證號等敏感字段,在應(yīng)用層加密后存儲(避免數(shù)據(jù)庫管理員直接查看):
- 推薦算法:AES-256-GCM(對稱加密,需妥善保管密鑰);
- 示例(MySQL 內(nèi)置 AES 加密,僅作演示,建議應(yīng)用層加密):
-- 加密存儲(密鑰需保存在應(yīng)用配置,而非數(shù)據(jù)庫)
INSERT INTO appdb.user (id, phone) VALUES (1, AES_ENCRYPT('13800138000', 'app_aes_key_2025'));
-- 解密查詢
SELECT id, AES_DECRYPT(phone, 'app_aes_key_2025') AS phone FROM appdb.user;
3. 定期備份 + 異地存儲(防止數(shù)據(jù)丟失)
(1)備份策略
- 全量備份:每日 1 次(使用
mysqldump或 Percona XtraBackup); - 增量備份:每小時 1 次(結(jié)合二進(jìn)制日志
binlog); - 備份文件加密存儲(如用
gpg加密)。
(2)mysqldump 備份示例(Linux)
# 全量備份(含結(jié)構(gòu)+數(shù)據(jù),--master-data 記錄 binlog 位置,用于增量備份) mysqldump -u root -p --all-databases --master-data=2 --single-transaction --quick --lock-tables=false > full_backup_$(date +%Y%m%d).sql # 加密備份文件 gpg -c full_backup_20251113.sql # 輸入密碼加密,生成 .gpg 文件 # 復(fù)制到異地存儲(如 FTP/OSS/S3) scp full_backup_20251113.sql.gpg user@backup-server:/backup/mysql/
(3)關(guān)鍵要求
- 定期測試恢復(fù)流程(確保備份可用);
- 備份文件保留至少 30 天;
- 異地存儲與生產(chǎn)環(huán)境物理隔離。
六、日志與審計加固(追溯安全事件)
1. 啟用關(guān)鍵日志
(1)錯誤日志(記錄啟動 / 關(guān)閉 / 異常錯誤)
[mysqld] log-error = /var/log/mysql/mysqld-error.log log-error-verbosity = 3 # 詳細(xì)日志級別
(2)慢查詢?nèi)罩荆▋?yōu)化性能,間接防范惡意慢查詢攻擊)
[mysqld] slow_query_log = ON slow_query_log_file = /var/log/mysql/slow.log long_query_time = 2 # 執(zhí)行時間超過 2 秒的查詢記錄 log_queries_not_using_indexes = ON # 記錄未使用索引的查詢
(3)二進(jìn)制日志(binlog,用于增量備份 + 操作追溯)
[mysqld] server-id = 1 # 唯一服務(wù)器 ID(主從復(fù)制/增量備份必需) log_bin = /var/log/mysql/mysql-bin # binlog 存儲路徑 binlog_format = ROW # 行級格式(更安全,避免 SQL 注入篡改日志) expire_logs_days = 7 # binlog 保留 7 天(避免磁盤滿)
2. 啟用審計日志(MySQL 企業(yè)版 / Percona Server)
社區(qū)版 MySQL 無內(nèi)置審計功能,需安裝第三方插件(如 audit_log)或使用 Percona Server(內(nèi)置審計插件):
# Percona Server 審計配置(my.cnf) [mysqld] plugin-load-add = audit_log.so audit_log_file = /var/log/mysql/audit.log audit_log_format = JSON # JSON 格式便于分析 audit_log_policy = ALL # 記錄所有操作(可按需調(diào)整為 LOGINS/DDL/DML)
3. 日志文件權(quán)限保護(hù)
# 修改日志目錄權(quán)限(僅 mysql 用戶可讀) chown -R mysql:mysql /var/log/mysql chmod 700 /var/log/mysql chmod 600 /var/log/mysql/*
七、配置文件加固(my.cnf/my.ini)
匯總核心加固配置(直接替換或追加到 [mysqld] 段):
[mysqld] # 基礎(chǔ)安全 bind-address = 192.168.1.100 local-infile = 0 symbolic-links = 0 # 禁用符號鏈接(防止目錄遍歷攻擊) max_connections = 1000 # 限制最大連接數(shù)(防止DoS攻擊) wait_timeout = 600 # 空閑連接超時 10 分鐘 interactive_timeout = 600 # 密碼策略(5.7+) validate_password_length = 12 validate_password_policy = STRONG validate_password_special_char_count = 1 # SSL 加密(8.0+) ssl-ca = /etc/mysql/ssl/ca.pem ssl-cert = /etc/mysql/ssl/server-cert.pem ssl-key = /etc/mysql/ssl/server-key.pem require_secure_transport = ON # 數(shù)據(jù)加密(8.0.16+) innodb_encrypt_tables = ON innodb_encrypt_log = ON early-plugin-load-add = keyring_file.so keyring_file_data = /var/lib/mysql-keyring/keyring # 日志配置 log-error = /var/log/mysql/mysqld-error.log slow_query_log = ON slow_query_log_file = /var/log/mysql/slow.log long_query_time = 2 log_bin = /var/log/mysql/mysql-bin binlog_format = ROW expire_logs_days = 7 # 禁用危險功能 disable-log-bin = OFF # 啟用 binlog(前面已配置,此處強(qiáng)調(diào))
八、定期維護(hù)與監(jiān)控
1. 定期安全檢查
- 每月執(zhí)行
mysql_secure_installation復(fù)查; - 每季度掃描 MySQL 漏洞(使用工具如 Nessus、OpenVAS);
- 每半年更新 MySQL 補(bǔ)丁(關(guān)注 Oracle 安全公告)。
2. 監(jiān)控關(guān)鍵指標(biāo)
- 異常登錄:監(jiān)控
Host為陌生 IP 的登錄記錄(查詢mysql.general_log或?qū)徲嬋罩荆?/li> - 慢查詢 / 大事務(wù):通過
slow.log或監(jiān)控工具(如 PMM、Zabbix)預(yù)警; - 權(quán)限變更:定期對比
mysql.user表,發(fā)現(xiàn)未授權(quán)的用戶 / 權(quán)限變更。
3. 應(yīng)急響應(yīng)預(yù)案
- 若發(fā)現(xiàn)數(shù)據(jù)泄露:立即禁用可疑賬號、切斷公網(wǎng)訪問、備份當(dāng)前數(shù)據(jù)、追溯攻擊源;
- 若遭遇暴力破解:臨時封禁攻擊 IP(防火墻 / 安全組)、修改所有賬號密碼、啟用二次驗證(如結(jié)合 PAM 插件)。
總結(jié)
MySQL 加固核心是 “最小權(quán)限 + 加密傳輸 + 數(shù)據(jù)保護(hù) + 審計追溯”,優(yōu)先完成 mysql_secure_installation、防火墻限制、密碼策略、禁用公網(wǎng)監(jiān)聽這 4 項基礎(chǔ)操作,再逐步推進(jìn) SSL 加密、TDE 存儲加密、審計日志等高級防護(hù)。
根據(jù)業(yè)務(wù)場景靈活調(diào)整(如內(nèi)網(wǎng)數(shù)據(jù)庫可簡化 SSL 配置,但必須限制登錄 IP;公網(wǎng)數(shù)據(jù)庫需強(qiáng)制 SSL + 二次驗證),定期復(fù)查加固效果,確保安全策略持續(xù)有效。
到此這篇關(guān)于MySQL全面安全加固實戰(zhàn)的文章就介紹到這了,更多相關(guān)MySQL安全加固內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
當(dāng)Mysql行鎖遇到復(fù)合主鍵與多列索引詳解
這篇文章主要給大家介紹了關(guān)于當(dāng)Mysql行鎖遇到復(fù)合主鍵與多列索引的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Mysql具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
MySQL學(xué)習(xí)第三天 Windows 64位操作系統(tǒng)下驗證MySQL
MySQL學(xué)習(xí)第三天教大家如何在Windows 64位操作系統(tǒng)下驗證MySQL,感興趣的小伙伴們可以參考一下2016-05-05
mysql函數(shù)拼接查詢concat函數(shù)的使用方法
下面小編就為大家?guī)硪黄猰ysql函數(shù)拼接查詢concat函數(shù)的使用方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-08-08
MYSQL Left Join優(yōu)化(10秒優(yōu)化到20毫秒內(nèi))
在實際開發(fā)中,相信大多數(shù)人都會用到j(luò)oin進(jìn)行連表查詢,但是有些人發(fā)現(xiàn),用join好像效率很低,而且驅(qū)動表不同,執(zhí)行時間也不同。那么join到底是如何執(zhí)行的呢,本文就詳細(xì)的介紹一下2021-12-12
MySQL中Multiple primary key defined報錯的解決辦法
這篇文章主要介紹了MySQL中Multiple primary key defined報錯的解決辦法以及相關(guān)實例內(nèi)容,有興趣的朋友們學(xué)習(xí)下。2019-08-08

