1 概述
CET(Control-flow Enforcement Technology)機制是 Intel提出基于硬件的?于緩解 ROP/JOP/COP的新技術。特別強調下,他是基于硬件?持的解決?案。從Intel的Tigerlake (11th gen),Alderlake (12th gen)/Sapphire-Rapid起,粗顆粒度地旨在預防前向( call/jmp )和后向( ret )控制流指令劫持來御防ROP的攻擊。
因此針對防御對象不同,CET技術又分為CET-SS用于針對ROP的ret指令和CET-IBT用于針對JOP/COP的jmp/call指令,見圖1 功守道。
圖1 功守之道
2 CET為何而生
在安全世界里,總是希望魔高一尺道高一丈。說到防御者CET,就不得不提他的進攻者ROP了。什么是ROP? 來看?個例?,假設程序中正常執行如下代碼?段,注意此時其中不含ret或call指令。
圖2 正常執行流
但是,如果稍加偏移?下解釋代碼的地址時,就會導致出現完全不?樣的指令,如下圖所示:
圖3 RET CALL的gadget
如果按照紅框中的順序解釋這些指令的時候,那么將會產??代碼預期的結果,會出現原代碼中未出現過的 ret 指令以及 call 指令,這些指令序列被稱為 gadget 。
通過仔細構造這些由ret指令終?的指令集,攻擊者可以執?原程序中?預期的任意惡意代碼,這種新產生ret攻擊被稱為 ROP 攻擊,同理還有COP/JOP(call/jmp)攻擊。
為了防御這種此類ROP攻擊,Intel工程師在2016年起在硬件機制上推出了CET緩解機制,針對不同的攻擊行為分為CET-SS(影子棧)和CET-IBT(間接跳轉跟蹤),即圖1 功守道所示。
3 CET
CET-SS和CET-IBT 在實現機制上屬于CPU內部異常,這里就涉及到中斷機制。當執行啟動CET發現執行執行流中沒有endbr64或函數返回ret和影子棧中shandow stack保存的ret不一致時,CPU內部出發異常,這里CET占用的中斷向量21號,觸發#CP并歸為陷阱執行中斷處理程序exc_control_protection(),對CET-SS CET-IBT分情況進行報錯。CET-IBT -> "traps: Missing ENDBR: xxx", CET-SS-> #CP(control protect)。
這里提一下CPU的異常,當CPU執行中發現ROP/JOP/COP后,CPU給自己發送中斷信號。注意異常不一定是錯誤,只要是異于平常就都是異常。有些異常不但不是錯誤,它還是實現內核重要功能的方法。CPU異常分為3類:
1.陷阱(trap),陷阱并不是錯誤,而是想要陷入內核來執行一些操作,中斷處理完成后繼續執行之前的下一條指令;
2.故障(fault),故障是程序遇到了問題需要修復,問題不一定是錯誤,如果問題能夠修復,那么中斷處理完成后會重新執行之前的指令,如果問題無法修復那就是錯誤,當前進程將會被殺死;
3.中止(abort),系統遇到了很嚴重的錯誤,無法修改,一般系統會崩潰。CET歸為陷阱。
圖4 CET中斷異常處理流程
3.1 CET-SS(Shadow Stack)
3.1.1 原理分析
Intel 提出了?種基于硬件的 CET 解決?案,其中之?的 shadow stack 機制?于緩解 ROP 攻擊。前?圖2可以得知 ROP 依賴于 ret 指令,其中要執?的后續指令地址從堆棧中獲得。因此 ROP 攻擊的前提是攻擊者能夠在堆棧中構造數據。那么再來看 shadow stack 機制是怎么?作的。
CET 使操作系統能夠創建?個 shadow stack (影?棧)。正常情況下,當執? call 指令時,會將 call 指令后?條指令地址壓棧。當啟?了 shadow stack 后,會同時在普通數據棧和 shadow stack 中壓?返回地址,隨后在執? ret 返回時,會將 shadow stack 中的返回地址和普通數據棧中的返回地址做對?,如匹配,則正常執?,如不匹配,則觸發#CP(Controlflow Protection) 異常。如下圖所示:
圖5 CET-SS針對ret指令觸發#cp異常
3.1.2 驗證方法
圖6 CET-SS test
以上內核代碼以ko的形式進行加載,然后通過用戶空間的app觸發系統調用,這里的app被名字也命為shadow_test_fork(內核函數和app名字一致了,容易產生混淆,請大家理解)。系統調用最終調到圖6中的shadow_test_fork()函數。發生如下異常報錯,見圖7。
圖7 CET-SS test result #CP
3.2 CET-IBT(Indirect Branch Tracking)
JOP/COP 攻擊?法與 ROP 類似,只不過是把 ROP 中以 ret 指令做跳板的關鍵點替換成了 call/jmp 指令。還是拿講述 ROP章節的兩幅圖(圖2 圖3)舉例,圖3中偏移解釋字節碼后出現了不同的指令,包含了:
圖8 CET-IBT call指令攻擊
這?指令序列,這就是 COP 中的 gadget ,以 call 指令為跳板,也就不需要 ret 指令的輔助了。這種不需要 ret 指令的攻擊場景下,前?所說的 shadow stack 機制就失效了。這種情況下, CET 的第?種機制 IBT(Indirect Branch Tracking) 就應運??了。
3.2.1原理分析
IBT(Indirect Branch Tracking),間接跳轉跟蹤"希望能防止攻擊者讓間接跳轉(例如,通過指針變量進行的函數調用)進入一個不應該走到的地方。功守道之中是為了應對JOP/COP的。
IBT 是為了防御面向跳轉編程的(jump-oriented programming);工作原理是試圖確保每個 indirect branch 的目標確實都是適合作為跳轉目標的。IBT 的方法有很多,每一種都有自己的優勢和劣勢。例如,內核在 5.13 開發周期中支持了編譯器實現的 IBT 機制。
在這種模式下,編譯器通過一個 "jump table, 跳轉表" 來完成每一個間接跳轉,不僅確保目標是要供間接跳轉使用的,而且要確保被調用函數的原型與調用者所期望的一致。這種方法是很有效的,但要增加很多編譯、運行時的開銷。
英特爾的 IBT 方法相當簡單,但優點是得到了硬件的支持,因此速度更快.如果 IBT 被啟用,那么 CPU 將確保每個間接跳轉都落在一條特殊指令(endbr32 或 endbr64)上(見圖9),該指令執行時跟 no-op 效果一致。如果發現意外,那么處理器將引發一次 control-protection(#CP)exception。
圖9 CET-IBT ENDBR標志嵌入輔助檢測
3.3.2測試方法
圖10 內核測試函數
圖11 CET-IBT 運行測試結果
3.3 硬件機制.
CPU 是如何實現這種校驗機制的呢?答案是?了 ENDBRANCH 狀態機。
CPU 在?戶態和內核態分別設有?個 ENDBRANCH 狀態機,狀態機共有兩個狀態,為 IDLE 和WAIT_FOR_ENDBRANCH 。初始狀態都為 IDLE ,當執?間接跳轉 call 的時候,狀態機會從 IDLE變為WAIT_FOR_ENDBRANCH ,這時候就意味著下?條指令就必須為 endbr32/64 ,如果是 endbr32/64 ,狀態機就會從 WAIT_FOR_ENDBRANCH 變回 IDLE ,如果不是則會觸發 #CP 異常。
圖12 狀態機
3.4 其他objtool
需要在所有的間接跳轉目標地址都添加 endbr 指令,這就為今后造成了一個潛在的陷阱:開發者可能會添加匯編函數但是忘記了這個指令。如果他們在沒有啟用 IBT 的情況下進行測試,那么這個問題就不會被注意到,可能直到有問題的代碼被合并后的某個讓人非常不爽的時間點才突然暴露出來。為了防止這種情況的發生,開發者加強了內核的 objtool 工具來檢查所有的間接跳轉,并確保所有的目標都恰當地標注(annotated)好了。
不過,有了這種檢查之后,還可以采取另一個步驟:objtool 還可以列出所有包含 endbr 指令但是永遠不會通過間接跳轉到達的函數。這些函數不需要進行標注,沒有它們的話,內核會更安全一些。因此,內核 build 的過程會從 objtool 中獲取該列表,并通過用 nop4 指令覆蓋 endbr 來 "封印" 這些函數。這就減少了攻擊者在啟用 IBT 時仍然可以選擇的攻擊目標。
正如 Peter Zijlstra 所指出的,刪除不需要的 endbr 指令還有一個也許是令人驚訝的好處。內核限制了 loadable module 所能使用的函數,而那些專有的(proprietary)module 則受限更多。那些專有的 module 經常使用一個技術就是在內核的符號表中查找到它們需要的、未 export 的函數,然后通過間接跳轉來調用它們,從而繞過內核的限制。但是,在啟用 IBT 后,任何缺乏 endbr 指令的函數都不再能以這種方式調用了。
4 性能分析
圖13 遞歸調用
圖14 CET性能分析
圖15 CET 性能分析
5 內核開發進度
內核開發者已經努力了一段時間,希望能讓英特爾 IBT 功能進入 Linux 內核。實現這個功能的第一個 patch(針對用戶空間代碼而不是針對內核)是由 Yu-cheng Yu 在 2018 年發布的。然后,這項工作似乎成了那些不斷穿越郵件列表的飛行荷蘭人(flying-Dutchman)patch 之一,從未能夠進入 mainline;第 30 版是 2021 年 8 月發布的,也沒有達到能夠合并的程度。類似的情況也發生在了用戶空間的影子堆棧(user-space shadow-stack)patch set 上,在經歷多次修訂后,這些 patch 最近被 Rick Edgecombe 接手了。
2021年年底,Peter Zijlstra 決定創建一個獨立的英特爾 IBT 實現來保護內核本身;第一個版是在去年 11 月發布的,Zijlstra 顯然是 "在周五晚上/周六早上趕工出來的"。這項工作發展得很快,3月初發布的第四個修訂版就是為 5.18 合并的版本了(鏈接見參考文檔CET-IBT patches)
這就是目前為止的情況了。從 2020 年底上市的 Tiger Lake 一代開始,英特爾處理器就支持 IBT 了,只支持了內核代碼。這并不是一個完美的工具,但它將提高攻擊者攻擊這類系統的門檻。同時,目前還不清楚用戶空間的支持何時(或是否)會進入 mainline 內核;到目前為止發布的 30 個修訂版中,有許多根本沒有收到任何 review 意見。該部分已經被Rick Edgecombe接手并發布了v1版本,后續我們拭目以待,希望能在6.2中會合入全部的CET代碼。
審核編輯:劉清
-
操作系統
+關注
關注
37文章
6826瀏覽量
123333 -
狀態機
+關注
關注
2文章
492瀏覽量
27541 -
JOP
+關注
關注
0文章
2瀏覽量
8392
原文標題:Intel CET 安全防御機制深度解析
文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論