hash(哈希)長度擴(kuò)展攻擊
b站的書寫體驗(yàn)不得不讓人稱道啊
????到目前為止我還沒有遇到過這種攻擊(可能是攻擊過于古老),但是我覺得還是值得拿出來研究一下的。
????問題來源:諸如md5或者sha1的一些hash加密的加密原理層的缺陷導(dǎo)致了漏洞,具體為:當(dāng)md5加密參數(shù)存在用戶可控變量時(shí) (md5(secret+args); args可控)時(shí) , 用戶可以用過控制args變量來來控制最后的加密結(jié)果md5(....)而不需要知道secret值。
????多說無益,來點(diǎn)題目(這里以php為例:)

????分析一下代碼,在開始之前我根據(jù)時(shí)間戳定義了一個(gè)長度為15的隨機(jī)secret,然后從文件中讀取靜態(tài)的secret。接下來判斷是否存在user字段cookie,如果沒有初始化user為admin,hash為secret和admin的md5值。最后主要邏輯段判斷是否存在cookie,如果存在進(jìn)入驗(yàn)證,如果user字段的值等于admin,則終止,不等于的話繼續(xù)判斷secret和cookie中的user的md5值是否強(qiáng)等于cookie中hash的字段值。
????可以很明顯的從題目中分析出幾點(diǎn):
md5(secret+cookie.user)要等于hash
secret未知
已知條件:md5(secret+"admin") 但是user不能傳admin? &&? len(secret) = 15????????????
????這里可以引入hash長度擴(kuò)展攻擊,但我們要先理解消息摘要算法的實(shí)現(xiàn)。這里拿 md5 算法舉例。
????md5加密過程分為補(bǔ)位,補(bǔ)長度和計(jì)算消息摘要,下面分條闡述,并以加密abc為實(shí)例
????????1.補(bǔ)位:把原始消息化為bit字節(jié)單位的數(shù)據(jù),然后后面補(bǔ)上10000....(n個(gè)0)使得最后len(message) % 512 == 448 ,這里的len測的是message的bit位數(shù), 然后補(bǔ)100
????????關(guān)于單位:8bit (比特)=? 1 bytes(字節(jié)),深入一點(diǎn)講,這里的message的length等于把a(bǔ)bc轉(zhuǎn)換為bytes類型然后轉(zhuǎn)換為整數(shù)來測試他的二進(jìn)制最高位,懂得都懂我也不贅述
????

????????'abc'的bit長度為23,然后補(bǔ)到448

????????2.補(bǔ)長度
????????把剛剛得到的數(shù)據(jù)補(bǔ)到64 字節(jié),根據(jù)進(jìn)制轉(zhuǎn)換,64bytes =??512bits 剛剛是448bits,也就是說還少了64bits也就是8bytes,bytes數(shù)和字符數(shù)等價(jià),但是這里注意的是補(bǔ)位過后,第 57 個(gè)字節(jié)儲(chǔ)存的是補(bǔ)位之前的消息長度,abc
是 3 個(gè)字母,也就是 3 個(gè)bytes字節(jié),24 bit,換算成 16 進(jìn)制為 0x18,也就是57位需要我們補(bǔ)上0x18然后再補(bǔ)7個(gè)隨意字符。
????????后面查閱了下文檔,發(fā)現(xiàn)也可以用64位表示出初始字符串的長度,這樣就不用再補(bǔ)7個(gè)字符了,就直接就完成了補(bǔ)完8個(gè)bytes(字節(jié))。
????????注意:因?yàn)榍懊嫠械娜际茄a(bǔ)數(shù)據(jù),所以可以以8為組整拆分?jǐn)?shù)據(jù)分別化為bytes數(shù)據(jù)

????????到這里為止數(shù)據(jù)已經(jīng)構(gòu)造完成了,至于為什么這么構(gòu)造,原因是為滿足后面處理中對(duì)信息長度的要求,要求信息長度為512的整數(shù)倍
????????3.計(jì)算消息摘要
? ? ? ? ?對(duì)消息進(jìn)行分組以及padding后,MD5算法開始依次對(duì)每組消息(填充好的消息按照64字節(jié)分組)進(jìn)行壓縮,經(jīng)過64輪數(shù)學(xué)變換。這個(gè)過程中,一開始會(huì)有定義好的初始化向量,為4個(gè)中間值,初始化向量不是隨機(jī)生成的,是標(biāo)準(zhǔn)里定義死的,是的,你沒看錯(cuò),這是“硬編碼”!
????????????? ?

???????????引用了道哥文章里的話,太精辟了就直接拿過來了,總結(jié)來說就是md5的計(jì)算是固定數(shù)據(jù)的輪計(jì)算。
????????? ?最后一輪產(chǎn)生的鏈變量經(jīng)過高低位互換(如:aabbccdd -> ddccbbaa)后就是我們計(jì)算出來的 md5 值。
????
????Hash長度擴(kuò)展攻擊?
????????????Length Extension?的理論基礎(chǔ),就是將已知的壓縮后的結(jié)果,直接拿過來作為新的壓縮輸入。在這個(gè)過程中,只需要上一次壓縮后的結(jié)果,而不需要知道原來的消息內(nèi)容是什么。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ---道哥永遠(yuǎn)滴神!
????????? ?攻擊目的:在未知secret并且知道一段由包含secret加密的結(jié)果的情況下通過控制可控變量得到md5(secret+可控)的值
????? ?????攻擊原理:帶上我個(gè)人的一點(diǎn)理解來說,先再贅述下md5加密原理,在我們padding全部結(jié)束之后進(jìn)行消息摘要,經(jīng)過64輪計(jì)算之后,把加密結(jié)果(4段)分別逆序然后拼接起來作為密文輸出。在我們得到這段密文之后,如果下次加密還是用的上次加密相同的密文并且密文后接了可控?cái)?shù)據(jù),我們就可以利用可控量進(jìn)行手動(dòng)填充原始數(shù)據(jù)使其達(dá)到正常加密前兩步padding后的結(jié)果(給出密文的那次加密),又因?yàn)槭欠纸M加密,所以每組的加密結(jié)果互不干涉(這也就是ECB的詬病),所以我們可以手動(dòng)添加(控制)最后一組明文,并根據(jù)上一次加密的結(jié)果逆向再和庫中固定的加密輪密鑰來演算出我們新添加的一組明文的加密結(jié)果,進(jìn)而推出最后的新密文,演算細(xì)節(jié)不詳細(xì)展開,不然快變成密碼學(xué)而不是web了。
????????? ?回到題目,我們現(xiàn)在有了md(secret+"admin")的值,要求md5(secret+cookie.user) === hash , 已知密文的一段md5 + 新的驗(yàn)證里由可控字段user,完全滿足hash擴(kuò)展攻擊的條件。
攻擊流程:
?????? ?查看cookie取出初次加密的md5值

????? ?這里使用hashpump構(gòu)造user并計(jì)算hash,把\x替換成瀏覽器可識(shí)別數(shù)據(jù)類型%

????????md5: 9d9096a97e358bbeddd3533c8d0f9c29
????????user:admin%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%a0%00%00%00%00%00%00%00feng
????????不急著打,先分析下user數(shù)據(jù),就如上文我所說的一樣,先按照得到已知密文的初始明文構(gòu)造數(shù)據(jù)并填充到滿足可以進(jìn)行消息摘要的明文,然后再隨意構(gòu)造一段明文,最后的根據(jù)已知密文并填充數(shù)據(jù)計(jì)算最后的新md5結(jié)果是hashpump幫我們完成的。
????????然后將數(shù)據(jù)替換掉

????? ? 刷新下頁面

? ??????攻擊成功
如何修復(fù)?
? ? ? ??加密可控消息
????? ? md5(secret + md5($_COOKIE['user']))
大型攻擊案例
phpwind 利用哈希長度擴(kuò)展攻擊進(jìn)行g(shù)etshell
https://www.leavesongs.com/PENETRATION/phpwind-hash-length-extension-attack.html
參考鏈接
http://blog.chinaunix.net/uid-27070210-id-3255947.html
https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks
hashpump下載
https://github.com/bwall/HashPump
write by@feng2020
3630?0648?2483?2480?2092?4502 0x62?4541