安裝完 MySQL 之後,最方便的操作方式可能是什麼事情都使用 root。但是在真正的 Production Environment 中,這卻是非常危險的做法。
資料庫安全(Database Security)的核心原則不是只有「有沒有設定密碼」,還要考慮:誰可以從哪裡登入,登入之後可以對哪些資料做什麼事情?
因此 MySQL Security 至少包括:
- User Account (使用者帳戶)
- Authentication (驗證)
- Privilege (權限)
- GRANT (授予權限)
- REVOKE (取消權限)
- Role (角色)
- Least Privilege (最小權限)
- Network Access (網路存取)
- Encryption (加密)
- Audit (監看)
- Backup Security (備份安全)
MySQL Account 不只是 Username
MySQL 帳號通常由:
'user'@'host'
包含帳號以及後綴來共同決定,後綴就是決定這個帳號可以從何處登入。
例如:
'app'@'localhost'
'app'@'192.168.1.%'
以上並不是完全相同的 Account。
因此管理 MySQL User 時不能只看 username,還必須考慮 username + host。
例如 :
'username'@'localhost' 限制: 只能從 MySQL 資料庫本機端登入。
'username'@'192.168.1.100' 限制: 只能從 特定的 IP 位址(例如 192.168.1.100)進行連線登入。
'username'@'192.168.1.%' 限制: 允許從 特定網段(例如 192.168.1.1 到 192.168.1.254)的任何一台電腦登入。
'username'@'%' 限制: 允許從 任何 IP 位址(任意遠端主機)進行連線登入。
因此如果沒有必要的話,盡量少給 'username'@'%' 這種類型的帳號。
建立 MySQL User
CREATE USER 'shop_app'@'localhost'
IDENTIFIED BY 'StrongPassword';
建立後,這個帳號並不是自然就擁有所有 Database 權限,接下來才依照需要授權。
GRANT 權限
假設 shop_app 只需要存取 shop Database,可以依需求授予:
GRANT SELECT, INSERT, UPDATE
ON shop.*
TO 'shop_app'@'localhost';
代表它可以 SELECT、INSERT、UPDATE,但是並沒有直接授予 DROP、CREATE USER、GRANT OPTION 等高風險權限。
REVOKE 收回權限
如果之後發現 shop_app 不應該 UPDATE,可以:
REVOKE UPDATE
ON shop.*
FROM 'shop_app'@'localhost';
權限管理不是建立帳號時設定一次之後就永遠不管,而應該定期進行 Privilege Review。
使用 SHOW GRANTS
SHOW GRANTS
FOR 'shop_app'@'localhost';
它可以協助確認這個帳號目前到底擁有哪些權限。
正式環境應該定期檢查:
- 已離職人員帳號
- 不再使用的 Application Account
- 權限過大的 User
- 不必要的 Host Access
- 不必要的 GRANT OPTION
Least Privilege 最小權限原則
資料庫安全最重要的原則之一,就是 最小權限原則(Principle of Least Privilege)。
意思是:使用者只取得完成工作所需要的最低權限。
例如報表系統只需要 SELECT,就不要給 INSERT、UPDATE、DELETE、DROP。
Application 如果只使用某一個 Database,也不要直接:GRANT ALL ON *.*
因為一旦 Account 被竊取,攻擊者能做的事情也會受到權限限制。
Application 不應該使用 root
Web Application,例如 PHP、Python、Java、Node.js,連線 MySQL 時都應該使用專屬 Application Account。
shop_web
report_system
erp_api
backup_service
而不是所有 Application 都使用 root,不同系統、不同帳號、不同權限、不同風險範圍,都應該設定不同的帳號跟權限。
Role 是什麼?
如果公司有很多 Reporting User,每一個都需要相似權限,可以建立 Role:
CREATE ROLE 'report_reader';
再授權:
GRANT SELECT
ON sales.*
TO 'report_reader';
意思是授權給 report_reader 這個角色對於 sales 這個資料庫下的所有表單具有 Select 權限。
然後:
GRANT 'report_reader'
TO 'user1'@'localhost';
如此便可以從「User → 一堆 Privilege」轉變為「User → Role → Privileges」,如此大型環境會比較容易管理。
密碼只是安全的一部分
好的 Password Policy 很重要,但不能把 Database Security 等同於 Strong Password。
還需要考慮:
- 帳號是否真的需要存在
- 可以從哪些 Host 登入
- Account 是否被 Lock
- Password 是否過期
- 是否限制 Failed Login
- 是否使用 SSL/TLS
- 是否具有過高 Privilege
Authentication 只是第一關,Authorization 才決定登入之後能做什麼。
不要把 Database Port 隨意暴露到 Internet
如果 MySQL 的 3306 Port 直接對整個 Internet 開放,就代表任何人都有機會嘗試連線。
比較安全的架構通常應考慮:
Internet
│
▼
Web / Application Server
│
▼
Private Network
│
▼
MySQL
而不是讓 Internet 直接連到 MySQL 3306。
SQL Injection 與 MySQL Security
SQL Injection 雖然主要屬於 Application Security,但資料庫權限設計可以降低事故影響。
如果 Application Account 只有必要的 SELECT / INSERT / UPDATE,和擁有 GRANT ALL ON *.*,造成的損害可能完全不同。
所以應該一起考慮:
Prepared Statement
+
Input Validation
+
Least Privilege
Backup 也必須受到保護
Production Database 權限做得很好,但如果 backup.sql 任何人都能下載,那 Database Security 幾乎等於失效。
Backup 可能包含完整 Customer Data、Account Data、Orders、Email 與 Internal Data,因此 Backup 必須同樣進行:
- Access Control
- Encryption
- Retention
- Secure Storage
Log 與 Audit
安全事件發生後,還必須回答:
- 誰登入?
- 什麼時間登入?
- 從哪裡登入?
- 執行什麼操作?
- 修改哪些資料?
因此 Database Administration 也必須建立:
- Server Log
- Authentication Log
- Application Log
- Audit Strategy
- Log Retention
定期進行 Account Review
MySQL Accounts
↓
哪些仍在使用?
↓
哪些可以刪除?
↓
Host 是否合理?
↓
Privilege 是否過大?
↓
Role 是否正確?
↓
Password Policy 是否符合要求?
安全管理不是安裝 MySQL 時做一次,而是一個持續的生命週期。
MySQL Security 可以整理成五個層次
第一層:Network
誰可以連到 MySQL Server?
第二層:Authentication
你是誰?
第三層:Authorization
你可以做什麼?
第四層:Data Protection
資料傳輸、Storage 與 Backup 是否受到保護?
第五層:Audit
出了事情之後能不能追蹤?
Network
↓
Authentication
↓
Authorization
↓
Least Privilege
↓
Encryption
↓
Logging / Audit
↓
Backup Security
真正的 Database Security,不是單純阻止別人登入,而是做到每一個 Account 都只能在必要的地方,執行必要的操作。
- MySQL CREATE USER 教學
- MySQL GRANT 完整教學
- MySQL REVOKE 教學
- SHOW GRANTS 怎麼看?
- MySQL Role 權限管理
- Least Privilege 最小權限原則
- MySQL root 帳號安全
- MySQL Password Policy
- MySQL SSL/TLS
- MySQL Backup Security
- Database Audit
- SQL Injection 與 Database Privilege

0 留言