作者:Cradmin@Tencent Blade Team
來源:騰訊安全應急響應中心
0x01 背景
中國武術博大精深,其中太極作為不以拙力勝人的功夫備受推崇。同樣如果從攻擊的角度窺視漏洞領域,也不難看出攻防之間的博弈不乏“太極”的身影,輕巧穩定易利用的漏洞與工具往往更吸引黑客,今天筆者要着墨分析的就是這樣一個擅長“四兩撥千斤”的0day漏洞。
0day漏洞的攻擊威力想必大家都聽說過,內核0day更因為其影響範圍廣,修復周期長而備受攻擊者的青睞。近期,國外安全研究者Vitaly Nikolenko在twitter[1]上公布了一個Ubuntu 16.04的內核0day利用代碼[2],攻擊者可以無門檻的直接利用該代碼拿到Ubuntu的最高權限(root);雖然隻影響特定版本,但鑒於Ubuntu在全球擁有大量用戶,尤其是公有雲用戶,所以該漏洞對企業和個人用戶還是有不小的風險。
筆者對該漏洞進行了技術分析,不管從漏洞原因還是利用技術看,都相當有代表性,是Data-Oriented Attacks在linux內核上的一個典型應用。僅利用傳入的精心構造的數據即可控制程序流程,達到攻擊目的,完全繞過現有的一些內存防護措施,有着“四兩撥千斤”的效果 。
0x02 漏洞原因
這個漏洞存在於Linux內核的eBPF模塊,我們先來簡單了解下eBPF。
eBPF(extended Berkeley Packet Filter)是內核源自於BPF的一套包過濾機制,嚴格來說,eBPF的功能已經不僅僅局限於網絡包過濾,利用它可以實現kernel tracing,tracfic control,應用性能監控等強大功能。為了實現如此強大的功能,eBPF提供了一套類RISC指令集,並實現了該指令集的虛擬機,使用者通過內核API向eBPF提交指令代碼來完成特定的功能。
看到這裡,有經驗的安全研究者可能會想到,能向內核提交可控的指令代碼去執行,很可能會帶來安全問題。事實也確實如此,歷史上BPF存在大量漏洞[3]。關於eBPF的更多細節,可以參考這裡[4][5]。
eBPF在設計時當然也考慮了安全問題,它在內核中實現了一套verifier機制,過濾不合規的eBPF代碼。然而這次的漏洞就出在eBPF的verifier機制。
從最初Vitaly Nikolenko公布的補丁截圖,我們初步判斷該漏洞很有可能和CVE-2017-16995是同一個漏洞洞[6],但隨後有2個疑問:
-
CVE-2017-16995在去年12月份,內核4.9和4.14及後續版本已經修復,為何Ubuntu使用的4.4版本沒有修復?
-
CVE-2017-16995是Google Project Zero團隊的Jann Horn發現的eBPF漏洞,存在於內核4.9和4.14版本[7],作者在漏洞報告中對漏洞原因只有簡短的描述,跟本次的漏洞是否完全相同?
註:筆者所有的代碼分析及調試均基於Ubuntu 14.04,內核版本為4.4.0-31-generic #50~14.04.1-Ubuntu[8]。
先來回答第二個問題,中間的調試分析過程在此不表。
參考以下代碼,eBPF的verifer代碼(kernel/bpf/verifier.c)中會對ALU指令進行檢查(check_alu_op),該段代碼最後一個else分支檢查的指令是:
-
BPF_ALU64|BPF_MOV|BPF_K,把64位立即數賦值給目的寄存器;
-
BPF_ALU|BPF_MOV|BPF_K,把32位立即數賦值給目的寄存器;
但這裡並沒有對2條指令進行區分,直接把用戶指令中的立即數insn->imm賦值給了目的寄存器,insn->imm和目的寄存器的類型是integer,這個操作會有什麼影響呢?