網路與傳輸層防護
- SSH 隧道加密:跨非信任網路連線時,
ssh -L 3306:localhost:3306 user@mysql-host,應用連 localhost:3306
- SSL/TLS 強制:
REQUIRE SSL 帳號層級、require_secure_transport=ON 實例層級、驗證憑證鏈
- 防火牆限制 3306 埠:僅允許應用伺服器 IP、跳板機、管理 IP 存取
- 掃描驗證:
nmap -p 3306 、telnet 3306 確認僅受信 IP 可連
認證與密碼策略
- root 專用、禁用遠端登入:
UPDATE mysql.user SET Host='localhost' WHERE User='root'; FLUSH PRIVILEGES;
- 密碼複雜度:安裝
validate_password 元件,設定長度、字元類別、字典檢查
- 定期輪換:
ALTER USER 'app'@'%' PASSWORD EXPIRE INTERVAL 90 DAY
- 避免明文密碼:配置檔用
mysql_config_editor 加密儲存、環境變數注入
- 單向雜湊:MySQL 8.0 預設
caching_sha2_password,較 mysql_native_password 安全
權限最小化原則
- 應用帳號僅必要權限:
GRANT SELECT, INSERT, UPDATE, DELETE ON app_db.* TO 'app'@'app-server-ip'
- 嚴禁 GRANT ALL / SUPER / PROCESS / FILE:
SUPER:殺連線、改全域變數、複寫控制
PROCESS:SHOW PROCESSLIST 看所有查詢文本 (含敏感資料)
FILE:LOAD DATA INFILE '/etc/passwd' 讀任意檔案
- 資料庫層級隔離:每應用獨立資料庫、獨立帳號
- 資源限制:
GRANT ... WITH MAX_QUERIES_PER_HOUR 1000 MAX_CONNECTIONS_PER_HOUR 50
注入防禦與輸入驗證
- 參數化查詢 (Prepared Statements):所有語言驅動支援,絕不字串拼接
- 輸入驗證白名單:長度、型別、格式、業務規則
- 跳脫字元函數:各驅動提供
mysql_real_escape_string、PDO::quote、mysqli::real_escape_string
- 錯誤訊息不外露:生產環境關閉詳細錯誤、統一錯誤頁面
伺服器與作業系統強化
- 專用帳號啟動 mysqld:
user=mysql,非 root
- 關閉符號連結:
--skip-symbolic-links 防止目錄遍歷
- 資料目錄權限:
chown -R mysql:mysql /var/lib/mysql; chmod 750 /var/lib/mysql
- 本地載入限制:
local_infile=0 禁用 LOAD DATA LOCAL INFILE
- DNS 信任風險:
skip_name_resolve=ON 僅用 IP 授權、避免 DNS 劫持
- 連線數限制:
max_user_connections、max_connections 防止單帳號佔盡資源
審計與監控
- 啟用審計日誌:
audit_log 元件、記錄登入、查詢、DDL、失敗嘗試
- 定期掃描弱點:
mysql_secure_installation、Lynis、OpenVAS
緊急重置 root 密碼 (錯誤 1045)
# 1. 停止服務
systemctl stop mysqld
# 2. 跳過權限表啟動
mysqld_safe --skip-grant-tables --skip-networking &
# 3. 免密登入重置
mysql -u root mysql
UPDATE user SET authentication_string=PASSWORD('NewStrongPass!') WHERE User='root';
FLUSH PRIVILEGES;
# 4. 正常重啟
systemctl restart mysqld
版本差異提醒 (MySQL 8.0+)
PASSWORD() 函數已移除,用 ALTER USER ... IDENTIFIED BY
caching_sha2_password 預設驗證外掛,舊驅動需升級
mysql.user 表結構變更,authentication_string 取代 Password
- 角色系統
CREATE ROLE/GRANT ROLE 簡化權限管理