本文將探討利用哈希函數的長度擴展攻擊與服務端驗證間的安全隱患。

作者:Victory!

封面:Photo by vackground.com on Unsplash

簡介

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.52^254.9易受攻擊
SHA-512 (SHA-2)2^32.52^511.5易受攻擊
SHA-32^50未知不易受攻擊
BLAKE2s2^1122^241不易受攻擊
BLAKE2b2^2242^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 

免責聲明:作為區塊鏈資訊平臺,本站所發佈文章僅代表作者及嘉賓個人觀點,與 Web3Caff 立場無關。 本文內容僅用於資訊分享,均不構成任何投資建議及要約,並請您遵守所在國家或地區的相關法律法規。