MySQL 使用者、權限與資料庫安全完整指南

database security

安裝完 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 留言