GreatSQL社區原創內容未經授權不得隨意使用,轉載請聯繫小編並註明來源。 GreatSQL是MySQL的國產分支版本,使用上與MySQL一致。 介紹 從 MySQL 8.0.4 開始,MySQL 預設身份驗證插件從 mysql_native_password 改為 caching_sha2_pa ...
- GreatSQL社區原創內容未經授權不得隨意使用,轉載請聯繫小編並註明來源。
- GreatSQL是MySQL的國產分支版本,使用上與MySQL一致。
介紹
從 MySQL 8.0.4 開始,MySQL 預設身份驗證插件從 mysql_native_password
改為 caching_sha2_password
。相應地,libmysqlclient
也使用 caching_sha2_password
作為預設的身份驗證機制。
起因
在這之前 MySQL 5.6/5.7 使用的預設密碼插件是 mysql_native_password
。mysql_native_password
的特點是不需要加密的連接。該插件驗證速度特別快,但是不夠安全,因為,mysql_native_password
使用的是於 SHA1 演算法,NIST(美國國家標準與技術研究院)在很早之前就已建議停止使用 SHA1 演算法,因為 SHA1 和其他哈希演算法(例如 MD5)容易被破解。
其實從 MySQL 5.6 開始就引入了更安全的認證機制:ha256_password
認證插件。它使用一個加鹽密碼(salted password)進行多輪 SHA256 哈希(數千輪哈希,暴力破解更難),以確保哈希值轉換更安全。但是,建立安全連接和多輪 hash 加密很耗費時間。雖然安全性更高,但是驗證速度不夠快。
改進
MySQL 試圖結合倆者的優點。於是在 MySQL-8.0.3 引入了一個新的身份驗證插件 caching_sha2_password
,作為sha256_password
的代替方案,在sha256_password
的基礎上進行了改進補上了短板,既解決安全性問題又解決性能問題。與此同時 sha256_password
將退出時代的浪潮。MySQL 預計在未來版本中將其刪除。使用 sha256_password
進行身份驗證的 MySQL 帳戶建議轉為 caching_sha2_password
。
結果
因為預設身份驗證機制的更改,大家在使用 MySQL 8.0
時候出現了很多相關的問題。網上的大部分教程都是教人改回mysql_native_password
驗證方式 mysql_native_password
。但是筆者認為,MySQL 更改預設插件是為了更好的安全性考慮。如果有 MySQL 服務要公網上使用,建議還是儘量使用 caching_sha2_password
作為認證插件。
示例:使用舊版本客戶端連接時報錯:
shell> mysql -uroot -p
ERROR 2059 (HY000): Authentication plugin 'caching_sha2_password' cannot be loaded
具體機制分析
mysql_native_password
mysql_native_password
作為 MySQL 5.6/5.7 的預設密碼插件 。其優點是它支持 challenge-response
(挑戰應答方式),這是非常快的驗證機制,無需在網路中發送實際密碼,並且不需要加密的連接。
客戶端連接MySQL實例時,首先需要從伺服器端獲得一個20位元組的隨機數。
此外,mysql_native_password
使用了新的哈希演算法進行認證校驗。對於用戶的原始密碼,通過SHA1(SHA1(password))兩次哈希計算結果保存在 mysql.user
表的 authentication_string
列中。其中用戶密碼通過哈希計算後保存,沒有加鹽(salt)。
通過上述這樣的處理,MySQL資料庫本身已然非常安全。然而,隨著時間的推移,目前存在以下兩種潛在風險:
- SHA1哈希演算法也已經變得比較容易破解。
- 相同的密碼擁有相同的哈希值。
SHA1、MD5等之前的哈希演算法都已然不再安全,更為安全的SHA256、SHA512哈希演算法也已推出。作為數據存儲最終承載者,應該使用更新的加密機制機制。
caching_sha2_password
在cache_sha2_password密碼認證機制下,其改進如下所示:
- 保存在
authentication_string
中的哈希值為加鹽後的值,即使兩個不同用戶的密碼相同,保存在電腦中的哈希值也不同。 - 哈希演算法升級為了更為安全SHA256演算法。
- 哈希演算法的
round
次數從原來的兩次,提升為了5000次,round
次數越多,每次計算哈希值的代價越大,破解難度也就越大。 - 用TLS的加密或RSA密鑰傳輸方式從客戶端將密碼傳送到服務端。
通訊過程解析
- 對於大多數連接嘗試,當密碼的哈希值有緩存在記憶體中時,它的驗證是基於 SHA256 的
challenge-response
機制(與mysql_native_password
中基於 SHA1 的challenge-response
機制相比更快),下圖演示了在有哈希緩存時的驗證流程。
- 客戶端連接服務端
- 服務端給客戶端發送 Nonce(20 位元組長的隨機數據)
- 客戶端使用 XOR(SHA256(password), SHA256(SHA256(SHA256(password)), nonce)) 生成 Scramble 發送給服務端
- 服務端檢查 username/SHA256(SHA256(user_password)) 是否在記憶體緩存條目中存在,存在則證明合法;發送 fast_auth_success 包到客戶端
- 服務端發送 OK 包到客戶端
- 進入命令階段
Nonce 是一個在加密通信只能使用一次的數字。在認證協議中,它往往是一個隨機或偽隨機數(salt),以避免暴力攻擊。
- 當沒有這種緩存時,
caching_sha2_password
需要使用安全連接進行密碼交換。考慮到用戶更改和FLUSH PRIVILEGES
操作頻率比較低,所以在大多數情況下,使用的都是基於challenge-response
的身份驗證,不用建立安全連接。這省去了建立安全連接需要耗費的資源。下圖總結了完整的驗證流程。
- 客戶端連接服務端
- 服務端給客戶端發送 Nonce(20 位元組長的隨機數據)
- 客戶端使用 XOR(SHA256(password), SHA256(SHA256(SHA256(password)), nonce)) 生成 Scramble 發送給服務端
- 服務端檢查 username/SHA256(SHA256(user_password)) 是否在記憶體緩存條目中存在,不存在則發送 perform_full_authentication 包到客戶端繼續認證
- 客戶端收到 perform_full_authentication 包,可以進行如下處理
- 如果安全連接已經建立基於 ,則可以直接發送明文密碼到服務端
向服務端發起獲取公鑰的請求(或者指定服務端公鑰文件),使用公鑰+Nonce加密密碼,發送加密後的密碼到服務端
伺服器通過 SHA256 演算法計算得到哈希值,判斷是否用戶認證通過,通過則發送 OK 包到客戶端 - 進入命令階段
這裡詳細解釋一下 RSA 非對稱加密的通信過程:
首先先明確一個概念:非對稱加密演算法中,有兩個密鑰:公鑰和私鑰。如果用公鑰進行加密,只有對應的私鑰才能解密;反之亦然。
RSA 密鑰交換過程:
伺服器生成一對密鑰並將公鑰向其他方公開(明文發送給客戶端);
客戶端使用伺服器的公鑰對密碼進行加密後發送給伺服器;
伺服器用對應的私鑰對加密信息進行解密。
因為客戶端用公鑰加密的信息只能用伺服器的私鑰解密,所以這個連接過程可以視為加密通信。
需要註意的地方
預設身份驗證插件的更改意味著:
在 MySQL 8.0.4 之後創建的所有新用戶將預設使用 caching_sha2_password
作為身份驗證插件。
mysql> SELECT USER,PLUGIN FROM mysql.`user` ;
+------------------+-----------------------+
| USER | PLUGIN |
+------------------+-----------------------+
| root | caching_sha2_password |
| mysql.infoschema | caching_sha2_password |
| mysql.session | caching_sha2_password |
| mysql.sys | caching_sha2_password |
+------------------+-----------------------+
6 rows in set (0.06 sec)
libmysqlclient
預設使用 caching_sha2_password
,可以通過手動修改切換到其他的身份驗證插件。
對於使用 caching_sha2_password 插件的客戶端,連接到伺服器時,密碼不會暴露為明文。密碼傳輸是如何進行的取決於是否使用安全連接或 RSA 對密碼加密:
- 如果連接是安全的,可以不使用 RSA 密鑰。適用於使用 TLS 加密的 TCP 連接,以及 Unix 套接字文件和共用記憶體連接。密碼以明文格式發送,但不能被竊聽,因為連接是安全的。
- 如果連接不是安全的,可以使用 RSA 密鑰對。適用於未使用 TLS 加密的 TCP 連接和 named-pipe 連接。RSA 僅用於客戶端和伺服器之間的密碼交換,防止密碼被截取。當伺服器接收到使用公鑰加密的密碼後,它使用私鑰解密。一個隨機字元串用在加密中,防止重放攻擊(repeat attacks)。
在 MySQL 8.0.3 以上版本中。預設自動完成 RSA 密鑰對進行密碼交換。
關於主從複製
複製本身是支持加密的連接。在 MySQL 8.0.4中,添加了複製對 RSA 加密的支持。
如果用於複製的用戶使用了 caching_sha2_password
身份驗證插件,並且沒有啟用安全連接( 在group_replication_recover
y 啟用SSL支持),MySQL 將使用 RSA 密鑰對進行密碼的交換,可以把主節點的公鑰手動拷貝到從節點的伺服器中,也可以設置成:自動為請求加入組的節點提供公鑰。
-
CHANGE MASTER
可以通過以下倆個參數來啟用基於caching_sha2_password
RSA 密鑰來交換密碼:指定 RSA 公鑰路徑 - MASTER_PUBLIC_KEY_PATH ="key_file_path" #從服務端獲取 RSA 公鑰 - GET_MASTER_PUBLIC_KEY = {0 | 1}
-
Group Replication 可以通過以下倆個參數來啟用基於
caching_sha2_password
RSA 密鑰來交換密碼:#指定 RSA 公鑰路徑 ––group-replication-recovery-public-key-path #從服務端獲取 RSA 公鑰 ––group-replication-recovery-get-public-key
資料庫升級
資料庫升級到 MySQL 8.0.4 會怎樣?
在升級之前創建的用戶,身份認證插件不會更改。在升級之後創建的用戶預設使用 aching_sha2_password
身份驗證插件。除非使用 --default-authentication-plugin
手動指定認證插件插件。因為不會更改升級前已有用戶。因此,使用升級後依然可以用舊版本的客戶端連接這些用戶。
相應地,libmysqlclient
支持 mysql_options() C API
函數的 MYSQL_DEFAULT_AUTH
選項。(對於 MySQL 包中可用的基於 libmysqlclient 的客戶端工具,可以用 ––default-auth
命令行選項達到相同的目的。)
建議使用 cache_sha2_password
因為它更安全。並且升級 libmysqlclient
到 MySQL 8.0.4 或更高版本,以便支持新的身份驗證插件。
參考資料
MySQL 8.0.4 : New Default Authentication Plugin : caching_sha2_password
MySQL 8.0密碼認證機制升級,不知道可能導致業務不可用!!!
組複製安裝部署 | 全方位認識 MySQL 8.0 Group Replication
Enjoy GreatSQL