一、系統內部安全:文件權限是底線
標準安全目錄結構 (以 /usr/local/mysql 為例)
drwxrwxr-x root root bin/
drwxrwxr-x root root include/
drwx------ mysql mysql var/ ← 數據目錄 700,僅 mysql 用戶可讀寫
drwx------ mysql mysql mysql/ ← 系統庫
drwx------ mysql mysql test/ ← 測試庫
-rw------- mysql mysql *.MYD ← 數據文件
-rw------- mysql mysql *.MYI ← 索引文件
-rw------- mysql mysql *.frm ← 表定義
修正權限命令
chown -R mysql:mysql /usr/local/mysql/var
chmod -R go-rwx /usr/local/mysql/var # 移除組/其他所有權限
⚠️ **舊版本風險**:MySQL 3.21 `var` 775、3.22 `var` 770 均不安全,3.23+ 默認 700 較安全。
二、授權表與最小權限原則
- **刪除匿名用戶**:`DELETE FROM mysql.user WHERE User='';`
- **禁用 root 遠程**:`DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost','127.0.0.1','::1');`
- **刪除 test 库**:`DROP DATABASE test; DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%';`
- **業務用戶單庫單表授權**:`GRANT SELECT,INSERT,UPDATE,DELETE ON app_db.* TO 'app_user'@'10.0.1.%';`
- **定期審計**:`SELECT User, Host, Select_priv, Insert_priv... FROM mysql.user;`
三、網絡層安全
- bind-address:`bind-address = 10.0.1.10` (僅綁內網 IP),不綁 `0.0.0.0`
- skip_name_resolve=ON:禁用 DNS 反解,防 DNS 攻擊、加速連接
- SSL 傳輸加密:生成憑證 → `require_secure_transport=ON` → 用戶 `REQUIRE SSL`
- 端口修改:非標準端口 (如 13306) 降低掃描暴露 (非核心防禦)
- 防火牆/安全組:僅允許應用服務器 IP 段訪問 3306
四、編程層防注入與最佳實踐
- **參數化查詢 / 預處理語句**:PDO `prepare()` / MySQLi `prepare()` — **根治 SQL 注入**
- **嚴禁拼接 SQL**:`"SELECT * FROM t WHERE id = " . $_GET['id']` ❌
- **ORM/Query Builder**:Laravel Eloquent / ThinkPHP Db / MyBatis 等框架層面防護
- **錯誤信息不外露**:生產環境關閉詳細 SQL 錯誤輸出,記錄日誌供排查
- **字段白名單**:`INSERT/UPDATE` 僅允許預定義字段,防止 Mass Assignment
五、實用技巧與冷知識
| 技巧 | 場景 | 命令/配置 |
| 只讀實例 | 報表/備份庫 | `SET GLOBAL read_only=ON;` (超級用戶除外) |
| 限制單用戶連接數 | 防單客戶端佔滿連接池 | `max_user_connections=100` |
| 慢查詢日誌 | 發現隱患 SQL | `slow_query_log=ON`, `long_query_time=1` |
| 二進制日志格式 ROW | 主從一致性、審計細粒度 | `binlog_format=ROW` |
| 定期輪換密碼 | 合規要求 | `ALTER USER 'u'@'%' PASSWORD EXPIRE INTERVAL 90 DAY;` (8.0+) |
| 數據掩碼導出 | 脫敏交付測試 | `SELECT MD5(id), LEFT(phone,3), '***' FROM users;` |
六、應急響應預案
- 發現異常 → `SHOW PROCESSLIST` 定位惡意會話 → `KILL id`
- 懷疑洩露 → 立即 `FLUSH PRIVILEGES` 刷新權限、輪換受影響賬號密碼
- 備份驗證 → 定期 `mysqldump --single-transaction` + 定期恢復演練