Check Point的研究員@Eyal Itkin在今年向glibc提交了一個commit-其中針對malloc中的single-linked list結構(fastbin / tcache)設計了一種機制「Safe Linking」,很大程度上提升了heap結構的安全性,拉高了所有針對fastbin/tcache攻擊的難度,主要遏止了以下的手法:
fastbin/tcache上的fd/next指標會先和heap ASLR random bytes做XOR後才儲存。
首先先把glibc 2.31 & 2.32拿來diff一下,開頭就看到了一段針對Safe-Linking新增的說明。
也就是說,現在fastbin/tcache上面的fd/next指標,會和和heap ASLR random bytes做XOR encoding,舉個例子
假設P為0x0000BA9876543210,而heap基底位址為0x0000BA9876543000
先做shift取得heap base random的部分:0x0000000BA9876543
最後得到0x0000BA93DFD35753。
看完上述例子會發現攻擊者如果沒有洩漏出heap ASLR的話,就不能將pointer改寫為想控制的值,算是很大程度提升攻擊的難度。
但到目前為止雖然能防止攻擊者,但我們自己同樣也不曉得這個pointer是否有被改寫過,這時候額外的aligned check機制就被引入了。
平常由於記憶體位址對齊的關係,chunk address的LSB都是0,但經過XOR之後就不是這樣了,0x0~0xf都有可能,但總歸最後XOR解碼回去時必須要是0才合理,所以這時額外引入對齊檢查機制,這導致了攻擊者:
Safe Linking作者用一個簡單對齊檢查就解決了很多問題,真的厲害。
先檢查一下fastbin開頭
再來要把chunk挑出來的時候也順便檢查
最後最近用過的fastbin會被丟進tcache裡做快取,這時候把fastbin chunk拿到tcache時也會檢查。
當tcache偵測到double free的時候會順便檢查
首先,要記住一點是Safe Linking只保護next/fd指標,代表HEAD仍然可以利用。不過fastbin HEAD因為遠在libc裡面而不在heap上,所以重點放在tcache上。
由於所謂的tcache HEAD儲存在TPS(tcache_perthread_struct)裡面,而TPS結構位於heap,這就讓攻擊者還有機會做exploit,這時有兩種情境。
複習一下,由於tcache為了消弭double free攻擊,chunk free掉之後會在chunk某欄位放上TPS位址(key),所以要丟進tcache之前檢查一下如果有這東西就代表double free發生(先不聊edge case),有點像是會場在手上蓋出入場印章的感覺(?。
But這個機制換句話說,就是讓攻擊者有免費方法可以生出沒有XOR過的heap address在chunk上,這時候配上UAF就有可能可以做exploit。
但由於key欄位記憶體位址前面放的是XOR過的next欄位,改到他就會觸發檢查機制,所以這個UAF必須稍微刁鑽一點,要能夠繞過前面存放next指標。
這個就很直觀了,因為TPS位於heap前方,所以如果能夠直接往前覆寫到TPS結構體內的東西、例如index[-1]這類,就有很多操作空間了,但實際上面臨兩個問題:
由於上述提到的攻擊都是針對TPS結構,為此我找到了作者在reddit討論串給出的想法。
作者也認為整個tcache上的設計是導致這些攻擊仍然存在的原因,他也再次強調Safe-Linking是針對”next”指標做保護,意旨在阻擋攻擊者:
如果稍微知道Windows NT Heap的機制就會知道,Windows使用了一個獨立的cookie來對heap entry做編碼,基於這項事實我向作者提問:
答案並不讓人意外,仍然是效能與實作的考量。
有趣的是,作者也將這套Safe Linking保護機制發了PR提交給了google牌的tcmalloc,但遺憾的是google以效能考量reject掉了。