首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 安全防護 23 條鐵律:從存取控制到加密傳輸的完整防禦體系

     編輯:MySQL 資料庫相關知識

資料庫安全是系統防線的最後一道關卡。MySQL 官方文檔提煉的 23 條安全建議,涵蓋網路傳輸、認證授權、權限最小化、審計監控、參數硬化等全維度。本文重新組織並深度解析這 23 條鐵律,構建可落地的 MySQL 安全防護體系。

網路層防護(第 1、8、9 條)

1. 跨網段連線必須加密通道

生產環境跨 VPC/公網/IDC 連線,強制使用 SSH 隧道 或 SSL/TLS 加密:

# SSH 隧道範例(本地 3307 轉發至遠端 3306)
ssh -L 3307:localhost:3306 user@db-server -N

# MySQL 客戶端啟用 SSL
mysql -h 127.0.0.1 -P 3307 -u app_user -p --ssl-mode=REQUIRED

MySQL 5.7+ 預設支援 SSL,需配置 ssl-ca、ssl-cert、ssl-key 並啟用 require_secure_transport=ON。

8. 防火牆隔離資料庫港口

  • 資料庫**嚴禁直接暴露公網**
  • 安全組/防火牆僅放行應用伺服器 IP 段存取 3306
  • 部署於 DMZ 區或私有子網,應用層透過堡壘機/VPN 運維

9. 定期掃描 3306 埠暴露風險

# 外部視角掃描
nmap -p 3306 
# 或簡易測試
telnet  3306
# 如能連通 → 立即整改防火牆規則

認證與授權核心(第 2、4、5、6、7、12、17、18、20、21 條)

2. 正確修改密碼流程(5.7+ 語法)

-- 登入
mysql -u root -p
-- 修改(5.7.6+ 推薦 ALTER USER)
ALTER USER 'root'@'localhost' IDENTIFIED BY 'new_strong_password';
-- 或舊版相容
SET PASSWORD FOR 'root'@'localhost' = PASSWORD('new_strong_password');
-- 生效
FLUSH PRIVILEGES;

4. 保護 mysql.user 表:僅 root 可存取

  • 移除匿名帳號:DELETE FROM mysql.user WHERE User='';
  • 移除遠端 root:DELETE FROM mysql.user WHERE User='root' AND Host!='localhost';
  • 所有應用帳號**僅授予業務必要權限**

5. 使用 GRANT/REVOKE 精細授權

-- 僅授予特定庫、特定表、特定操作
GRANT SELECT, INSERT, UPDATE ON `mall_order`.* TO 'app_order'@'10.0.1.%' IDENTIFIED BY 'strong_pass';
-- 撤銷多餘權限
REVOKE DELETE ON `mall_order`.* FROM 'app_order'@'10.0.1.%';

6. 密碼儲存:單向雜湊而非明文/可逆加密

  • 應用層儲存密碼使用 bcrypt/argon2/PBKDF2(非 MD5/SHA1)
  • MySQL 內部 mysql.user 使用 caching_sha2_password (8.0 預設) 或 mysql_native_password

7. 強密碼策略:拒絕字典弱密碼

[mysqld]
validate_password_policy=STRONG
validate_password_length=16
validate_password_mixed_case_count=1
validate_password_number_count=1
validate_password_special_char_count=1

12. 應用帳號最小權限原則

應用角色建議權限禁止權限
唯讀報表SELECTINSERT/UPDATE/DELETE/DROP/ALTER
寫入服務SELECT, INSERT, UPDATEDROP/ALTER/GRANT/FILE
遷移/ETLSELECT, INSERT, UPDATE, DELETEDROP/ALTER/GRANT/SHUTDOWN
管理員ALL PRIVILEGES (受限主機)--

17. 嚴禁業務帳號持有 PROCESS/SUPER

  • PROCESS 可見所有執行中 SQL(含敏感參數)
  • SUPER 可 KILL 連線、修改全域變數、控制複寫
  • 僅 DBA 運維帳號持有,且限制來源 IP

18. FILE 權限僅限 DBA,防止任意讀寫檔案

-- 危險範例:讀取系統密碼檔
LOAD DATA INFILE '/etc/passwd' INTO TABLE temp;
SELECT * FROM temp;

生產庫嚴禁授予 FILE 給非 DBA 帳號。

20. 限制單帳號最大連線數

-- 全域限制
SET GLOBAL max_user_connections = 100;
-- 特定帳號限制 (需 SUPER 權限)
GRANT USAGE ON *.* TO 'app_user'@'%' WITH MAX_USER_CONNECTIONS 50;

21. GRANT 支援資源限制擴充

GRANT USAGE ON *.* TO 'app_user'@'%' 
    WITH MAX_QUERIES_PER_HOUR 10000
         MAX_UPDATES_PER_HOUR 5000
         MAX_CONNECTIONS_PER_HOUR 2000
         MAX_USER_CONNECTIONS 50;

SQL 注入與輸入驗證(第 10、11、13 條)

10. 參數化查詢 / 預處理語句 — 唯一根治方案

-- ❌ 錯誤:字串拼接
"SELECT * FROM users WHERE id = " + input_id

-- ✅ 正確:預處理參數綁定
PreparedStatement ps = conn.prepareStatement("SELECT * FROM users WHERE id = ?");
ps.setInt(1, input_id);

所有語言驅動(JDBC、PDO、MySQLdb、Go database/sql)均支援預處理,**嚴禁手動拼接 SQL**。

11. 輸入長度與型別驗證

  • 應用層驗證:長度、格式、範圍、字元集白名單
  • 資料庫層:欄位型別約束(VARCHAR(32)、TINYINT UNSIGNED)、CHECK 約束 (8.0.16+)

13. 使用驅動提供的跳脫函數(若必須動態構建)

傳輸加密與審計(第 3、14 條)

3. 啟用 SSL/TLS 傳輸加密

[mysqld]
require_secure_transport=ON
ssl_ca=/etc/mysql/ssl/ca.pem
ssl_cert=/etc/mysql/ssl/server-cert.pem
ssl_key=/etc/mysql/ssl/server-key.pem

驗證:SHOW VARIABLES LIKE 'have_ssl'; → YES;\\s 顯示 SSL: Cipher in use is TLS_AES_256_GCM_SHA384。

14. 學會使用 tcpdump 審計傳輸內容

# 捕獲 3306 埠流量並提取可列印字串
tcpdump -i eth0 -nn -s 0 -A 'port 3306' | strings
# 或寫入檔案離線分析
tcpdump -i eth0 -w mysql_traffic.pcap port 3306
wireshark mysql_traffic.pcap

系統層硬化(第 15、16、19、22 條)

15. 關閉符號連結支援

[mysqld]
skip_symbolic_links=ON

防止透過符號連結繞過目錄權限存取任意檔案。

16. 資料目錄權限最小化

chown -R mysql:mysql /var/lib/mysql
chmod 750 /var/lib/mysql
# 僅 mysql 使用者可讀寫

19. 不信任 DNS 時使用 IP 白名單授權

GRANT SELECT ON db.* TO 'user'@'10.0.1.10' IDENTIFIED BY 'pass';
-- 而非
GRANT SELECT ON db.* TO 'user'@'app-server.example.com' IDENTIFIED BY 'pass';

22. 啟動參數安全開關

語言/驅動跳脫函數
PHP (PDO)$pdo->quote() / 預處理
Java (JDBC)PreparedStatement
Python (MySQLdb/PyMySQL)cursor.execute(%s, params)
Go (database/sql)db.Query(sql, args...)
C/C++mysql_real_escape_string()

緊急恢復:重設 root 密碼(第 23 條)

# 1. 停止服務
systemctl stop mysqld

# 2. 跳過授權表啟動
mysqld_safe --skip-grant-tables --skip-networking &

# 3. 無密碼登入重設
mysql -u root mysql
UPDATE user SET authentication_string=PASSWORD('new_strong_pass') WHERE User='root';
FLUSH PRIVILEGES;

# 4. 正常重啟
systemctl restart mysqld

⚠️ --skip-networking 防止跳過授權期間外部連線入侵。

總結:建立持續安全運營體系

  1. 基線掃描:定期執行 mysql_secure_installation、Lynis、CIS Benchmark 檢查
  2. 權限審計:半年一次 SHOW GRANTS 全帳號審視,收回過期/過度權限
  3. 日誌審計:啟用 audit_log 外掛記錄所有 DDL/DML/登入/失敗嘗試
  4. 漏洞管理:訂閱 MySQL 安全公告,月度評估升級
  5. 應急預案:密碼洩露、SQL 注入、勒索軟體演練流程文檔化

安全非一次性配置,而是持續的**最小權限、加密傳輸、審計可追溯、快速應急響應**四大支柱建設。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
參數建議值效果
local_infile0禁用 LOAD DATA LOCAL(防止客戶端任意讀檔)
skip_grant_tables關閉 (預設)啟用則繞過所有權限檢查,**極度危險**
skip_show_databaseON隱藏 SHOW DATABASES(非 DBA 不需知庫清單)