作者:啟明星辰ADLab
原文鏈接:https://mp.weixin.qq.com/s/93HyZBf803WucqEUG0uI7g

一、漏洞背景

近日,國外安全研究人員披露一個Linux eBPF verifier組件錯誤驗證漏洞,此漏洞源于bpf驗證系統在Linux內核中沒有正確計算某些操作的寄存器邊界跟蹤,導致本地攻擊者可以利用此缺陷進行內核信息泄露或特權提升,該漏洞編號為CVE-2020-27194。

二、影響范圍與防護措施

影響范圍

  • Linux-5.7 ~ Linux-5.8.14
  • ?Ubuntu 20.10

防護措施

  • 及時更新升級內核
  • 將kernel.unprivileged_bpf_disabled.sysctl設置為1,臨時限制普通用戶權限

三、漏洞原理與調試分析

漏洞原理

該漏洞和Pwn2own2020比賽中使用的CVE-2020-8835漏洞原理一致,均是錯誤計算了寄存器邊界跟蹤,導致可以繞過驗證器檢查達到越界讀寫。缺陷代碼出現在kernel/bpf/verifier.c的scalar32_min_max_or()函數中,該函數是在commit_id:3f50f132d840中引入的,該功能實現了顯式的ALU32(32位計算類操作)寄存器邊界跟蹤,處理OR運算時,調用scalar32_min_max_or()函數進行32位寄存器邊界跟蹤,該函數實現如下:

行5365和行5366,直接將dst_reg寄存器中的64位無符號值賦值給32位有符號值,這明顯是錯誤的。例如設置dst_reg->umin_value=1,dst_reg->umax_value=0x600000001,當進行如上操作后,dst_reg->s32_min_value為1,但是dst_reg->s32_max_value也將是1,因為0x600000001的高位將被截斷,這時dst_reg寄存器的范圍從[1,0x600000001]變成了[1,1],這會被驗證器識別為常數1,進而繞過驗證器檢查。漏洞補丁中,進行了正確的32位有符號值賦值操作,如下所示:

調試分析

首先將寄存器的umin_value設置為0x1,可以通過如下BPF指令實現:

此時寄存器的狀態如下所示:

設置完umin_value后,設置umax_value為0x600000001,可以通過如下BPF指令實現:

斷點命中后,調用棧如下所示:

執行完BPF_JMP_REG(BPF_JLT,BPF_REG_6,BPF_REG_5,1)指令后,將R6寄存器范圍設置為0x1到0x600000001之間。R6寄存器狀態如下所示:

接著設置R6寄存器中32位的無符號最小值和最大值,

設置完之后,R6寄存器狀態如下所示:

紅框中設置的值是必須要保證的,需要提前進行設置,方便后面繞過if判斷進入缺陷代碼塊中。接著設置R6寄存器32位有符號最小值和最大值,代碼如下所示:

行5355,if語句判斷不成立,會走到行5362分支中,調試情況如下所示:

觸發漏洞后,R6寄存器狀態如下:

此時s32_min_value和s32_max_value都為0x1,在驗證器中,R6寄存器的32位有符號取值為常數1。但R6寄存器的取值實際是有范圍的。接著將R6寄存器進行32位MOV到R7寄存器中,執行到如下代碼所示:

此時,src_reg寄存器如下所示:

執行MOV操作之前,R7寄存器狀態如下所示:

執行MOV操作后,R7寄存器狀態如下所示:

R7寄存器為常量1,實際運行情況下是有范圍的,可以設置為2。 執行BPF_ALU64_IMM(BPF_RSH,BPF_REG_7,1)后,即R7 >>= 1,R7寄存器如下所示:

此時umin_value和umax_value為0,即為R7寄存器進行右移操作后,在驗證器中被識別為常數0,此時R7寄存器進行加減運算都不會發生越界,繞過了驗證器的邊界檢查。但是如果R7寄存器實際設置為2,2>>1為1,R7寄存器為1,此時和R7寄存器進行加減運算,達到越界讀寫。

四、漏洞復現

在Linux-5.7.7版本中進行漏洞利用,成功提權。

五、參考鏈接

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-27194
https://github.com/torvalds/linux/commit/5b9fbeb75b6a98955f628e205ac26689bcb1383e
https://github.com/torvalds/linux/commit/3f50f132d8400e129fc9eb68b5020167ef80a244
https://scannell.me/fuzzing-for-ebpf-jit-bugs-in-the-linux-kernel/


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1391/