哈希函數的隱藏危險:長度擴展攻擊與服務端驗證的安全隱患

簡介

Length Extension Attack 是一種與某些特定類型的哈希函數(如MD5,SHA-1 和SHA-2)的特性有關的攻擊。簡單來說,這種攻擊利用了一個事實,即知道H(message) 和message 的長度,我們可以輕鬆計算出H(message || padding || extension) 而不需要知道message 本身。其中“||” 表示連接,“padding” 是根據哈希函數的規定添加的。

這是因為這些哈希函數使用了Merkle-Damgård 結構,它將輸入切片為多個塊,並且每個塊的哈希值依賴於前一個塊的哈希值。這意味著一旦我們計算出了某個消息的哈希值,就有了一個狀態,可以從那裡開始並添加更多的塊。

一種服務端驗證模式

為方便描述漏洞場景,我們首先假設有這樣一種服務端驗證模式,即用戶嘗試登錄時,服務端會根據用戶的ID、名字以及一個僅服務端知道的30 位密鑰,通過特定的哈希算法生成一個哈希值,並將其下發給客戶端。隨後,當客戶端嘗試訪問某些特定接口,例如修改用戶權限的接口時,服務端會根據前端POST 的角色ID、角色名字、角色權限以及同樣的30 位密鑰,重新生成哈希進行驗證。如果上傳的哈希與服務端生成的哈希一致,則視為驗證通過,並將新的角色權限寫入數據庫。

為便於理解,下面是根據描述寫的一些簡單的代碼做為示例:

越權思路

由於驗證模式存在漏洞,攻擊者可以在不知道SecretKey 的情況下,通過重新構造交易請求,達到繞過權限驗證的目的。越權攻擊的核心思路在於利用長度擴展攻擊的特性。攻擊者首先需要獲取到原始的哈希值,並通過簡單的迭代算法計算出原始數據的長度。一旦得到這些信息,就可以將額外的越權參數添加到原始數據中,並利用相同的哈希算法生成惡意的哈希值。

長度擴展攻擊原理

Length Extension Attack 發生的原因在於部分哈希函數的內部機制。這些函數在處理輸入數據前,首先將數據分割成固定長度的塊,然後在每個塊的末尾進行填充以滿足特定的要求。這種設計導致攻擊者可以在知道原始消息哈希值和長度的情況下,通過填充和附加新數據,構造出新的有效哈希值。

以SHA-256 為例,其工作在512 比特的塊上。對於長度不是512 比特的倍數的數據,需要進行填充操作。其填充規則如下:

1. 在數據的末尾添加一個“1” 比特;

2. 添加一定數量的“0” 比特,使得數據的長度模512 等於448(詳細內容見 [1]);

3. 在最後面添加一個64 位長的塊,表示原始數據的長度。

簡而言之,將一個“1” 後面跟著m 個“0”,再加上一個64 位或128 位的整數,附加到消息的末尾,以生成長度為512*n 的填充消息。附加的整數是原始消息的長度。然後,填充消息將被哈希函數處理為n 個512 位的塊。

構造方法

在這個示例中,我們將以上面圖片提到的代碼做為一個特定的場景,其中數據字符串為data=”user_id=1&user_name=aa”,密鑰為SecretKey=”Length_extension_attack_secret”。服務端會解析上傳的數據中的data 字段,並通過分隔符& 解析出所需的參數user_id 和user_name。如果存在role 字段,服務端也會獲取該字段的值。然後,服務端會將所有字段與SecretKey 進行哈希運算,並與上傳的驗證哈希進行比較。如果哈希值一致,則認為參數符合規則,並直接使用。

首先,我們通過登錄loginHandler 接口獲取根據data 和SecretKey 使用SHA-256 生成的哈希值hash=”37d310d3465506486431fb2c2eb163f0f470479703f66dc9e5fdead8a3390c68″。

接下來,我們將探討破解的難度。以我們的測試情況為例,根據長度擴展攻擊的原理,只要知道H(message) 和message 的長度,我們就可以通過長度擴展攻擊添加新的數據。原來的message = SecretKey + data,現在我們手上已經有H(message),只需知道message 的長度,就可以構造一個新的哈希值。由於SecretKey 是一個30 位的密鑰,只需經過30 次迭代,就可以得知真正的message 的長度。因此,我們可以很容易地構造出一個新的哈希值。由於我們需要使用admin 的權限,所以我們要將惡意的字段”&role=admin” 拼接到原來的數據中。

我們可以利用長度擴展攻擊的特性,在不知道SecretKey 的情況下,添加新的數據並生成一個新的哈希值。這裡使用一個已經實現此功能的庫 [2] 來完成測試。再使用工俱生成新的哈希值。

由於adminActionHandler 的接口驗證是根據上傳的user_id,user_name 和role 來驗證hash 的,我們這時候上傳的數據是user_id=1,user_name=aa\x80\x00\x00\x00\x00\x00\x00\x00\ x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x70 以及role=admin,如下圖所示:

哈希值為84ae4ae437eeabf3bd8a26294392770b86f64a81998194156ac003d58a21acd0。之後就可以調用adminActionHandler 接口,服務端收到數據後,會把上傳的哈希與sha256(SecretKey + fakeData) 進行對比,通過驗證之後將會執行一些敏感操作。這樣,我們就成功地利用長度擴展攻擊繞過了服務端驗證,並實現了越權操作。

其他可能的攻擊場景

1. 文件完整性驗證:如果文件的完整性是通過連接密鑰和文件內容,然後對其進行哈希來驗證的,那麼攻擊者可能會擴展文件並生成一個有效的哈希,從而繞過完整性檢查;

2. Web 應用安全:在Web 應用中,如果使用了易受長度擴展攻擊的哈希函數來驗證用戶提交的數據,攻擊者可能會利用這一點來提交惡意數據;

3. 數字簽名:在某些數字簽名方案中,如果簽名是通過連接私鑰和消息,然後對其進行哈希來生成的,那麼攻擊者可能會擴展消息並生成一個有效的簽名;

4. 密碼存儲:雖然不常見,但如果密碼是通過連接密鑰(例如鹽)和密碼,然後對其進行哈希來存儲的,那麼攻擊者可能會嘗試使用長度擴展攻擊來破解密碼。

如何防範

1. 選擇不易受長度擴展攻擊的哈希函數,例如SHA-3;

2. 使用HMAC:HMAC 需要一個密鑰和一個消息作為輸入,輸出的結果既依賴於密鑰,也依賴於消息,因此攻擊者在不知道密鑰的情況下無法進行長度擴展攻擊;

3. 加強權限驗證:在服務端增加額外的權限驗證步驟,例如使用多因素認證。

以下是一些常用的Hash 算法的特性:

算法碰撞抵抗選擇前綴碰撞攻擊

預映像抵抗

長度擴展攻擊MD52^182^392^123.4易受攻擊SHA-12^61.22^63.42^160易受攻擊SHA-256 (SHA-2)2^65.5-2^254.9易受攻擊SHA-512 (SHA-2 )2^32.5-2^511.5易受攻擊SHA-32^50-未知不易受攻擊BLAKE2s2^112-2^241不易受攻擊BLAKE2b2^224-2^481不易受攻擊結語

對於長度擴展攻擊,一種有效的防護措施是使用不受此類攻擊影響的哈希函數,例如SHA-3 和BLAKE2。另外,還可以通過HMAC(密鑰散列消息認證碼)結構來進行防護。這些措施可有效提高系統的安全性,確保數據完整性和應用程序的穩定性。

參考鏈接:

[1] https://www.rfc-editor.org/rfc/rfc6234#page-8

[2] https://github.com/skerkour/kerkour.com/tree/main/blog/2023/sha256_length_extension_attacks

Total
0
Shares
Related Posts