作者: Hongli Han(@hexb1n) of Qihoo 360 C0RE Team
博客:http://blogs.#/post/Binder_Kernel_Vul_CH.html

前言

Binder是基于OpenBinder實現的,是Android系統的重要組成部分。Binder構建于Linux內核中的Binder驅動之上,系統中涉及到Binder通信的部分,都需要通過與Binder驅動交互來實現數據傳遞。由于Binder驅動在整個Android系統中發揮的重要作用,一直以來也是Android安全研究的重點之一。

在二進制的世界里,對象的生成和銷毀都有一定的流程和時間點,有一些是在編譯器層面來實現,有一些卻需要程序設計者來維護。一旦這個流程設計的不夠完美,使得攻擊者能夠通過非法操作擾亂其正常的生命周期便有可能造成一系列的安全問題。去年8月份我在對Binder驅動代碼進行安全審計的時候,發現了一枚如同《三體》中“水滴”一般的內核通殺漏洞,擁有了驚人的破壞力,僅用一個漏洞便可以實現任意地址讀、任意地址寫、寫任意內容、信息泄露。同時,Binder驅動也是目前為數不多的幾個可被沙箱中的進程訪問的驅動之一,該漏洞可能被用于沙箱逃逸。在如此重要的內核驅動中會潛伏這樣一枚通殺漏洞堪稱神奇。

基于這個漏洞,我們實現了對Pixel全系手機的ROOT,其中的Pixel 3也代表了谷歌安卓內核目前最高的安全防御水平,這也是Pixel 3自問世以來,全球范圍內首次公開的ROOT攻擊。這里要感謝@周明建@王曉東@姚俊@邵大成等團隊小伙伴的支持,讓漏洞利用能夠及早的完成,文末也附了我們的提權視頻鏈接[1]。

這個漏洞在2019年3月的Android Security Bulletin中已經公開,對應的漏洞編號為CVE-2019-2025。下文我將會介紹該漏洞危害、影響范圍、漏洞原理以及利用思路。

漏洞危害及影響范圍

漏洞危害

1) 通殺。目前國內外主流的Android機型基本都會受到影響;

2) 攻擊能力極強。該漏洞可實現較穩定的任意地址讀寫、寫任意內容、信息泄露,并且每觸發一次漏洞便可以任意寫一次、讀一次,Google現有的內核安全緩解措施對于這類能夠任意地址讀寫的漏洞暫無有效的防御策略;

3) 沙箱逃逸。可能用于沙箱逃逸,并直接提權到ROOT;

同時,Binder驅動已早在2015年初被合入Linux主線,使用了Binder模塊的平臺均有可能受到影響。

影響范圍

該漏洞屬于use-after-free問題,觸發時需要不同線程間同步競爭調用“binder_ioctl()”,而在早期的設計中,“binder_ioctl()”由一個效率較低的全局互斥鎖保護,見圖1。

image.png

圖1

而此問題后續被優化,從“drivers/android/binder.c”的commit日志可以看到,2016年11月14日的一個補丁將這個全局互斥鎖去掉,并優化為更加細粒度的互斥鎖來保護,見圖2。完整的補丁可參見鏈接[2]。

image.png

圖2

打上這個補丁的內核源碼便可能受到該漏洞的影響。

由于該漏洞具備通殺能力,目前市面上主流在用的2016年11月之后的內核版本多數都會受到影響,在修補該問題之前將會有大量的設備處于安全風險之中。成功ROOT后攻擊者可以獲得系統的最高權限,同時該漏洞可能被用于遠程攻擊鏈,若是被黑產利用將可直接對用戶的個人隱私、財產安全甚至人身安全造成嚴重的危害。目前Linux主線上已提供了針對該漏洞的補丁,Android廠商可參考附注鏈接[3]及時修補。

漏洞的成因

基礎知識

關于Binder機制這里就不做過多介紹了,接觸過Android的同學應該對它或多或少都有一定的了解。理解該漏洞需熟悉通過Binder通信的雙方的基本交互流程,以及中間用到一些結構體對象,網絡上關于Binder的資料非常豐富,可自行補充。

漏洞原理

當用戶進程通過調用"IPCThreadState::transact()"向server進程請求數據時,server進程會調用”IPCThreadState::sendReply()”向用戶進程回傳數據以作為響應。在這個過程中,server進程會陷入內核,并調用“binder_alloc_new_buf()”從用戶進程(“target_proc->alloc”)對應的”alloc->free_buffers.rb_node”紅黑樹中申請一個”struct binder_buffer”類型的對象,被申請得到的對象會從”alloc->free_buffers.rb_node”紅黑樹中移除,并鏈入到”alloc->allocated_buffers.rb_node”紅黑樹中進行維護,此后將”t->buffer->allow_user_free”賦值為0,以避免”t->buffer”在使用過程中被釋放,見圖3。

image.png

圖3

用戶進程擁有對該”t->buffer”的釋放權,不過要在用戶進程收到了server進程發來的消息,結束本次交互并銷毀所用的Parcel對象時。然而,我們可以試圖通過主動向內核發送”BC_FREE_BUFFER”請求來提前釋放該”t->buffer”對象,不過這需要滿足內核對各項參數的校驗,如圖4所示。

image.png

圖4

上文中提到的“t->buffer”可以通過向內核傳入對應的“data_ptr”值,再通過調用“binder_alloc_prepare_to_free()”函數來找到,其返回值會賦值給”buffer”,緊接著內核會檢查“buffer->allow_user_free”以及”buffer->transaction”的合法性,由于缺少互斥鎖的保護,這里存在一個條件競爭問題,如果用戶進程能在圖3中”t->buffer->allow_user_free”被賦值為0之前觸發到“binder_alloc_free_buf()->binder_free_buf_locked()->rb_erase()”,便有可能將其從”alloc->buffers”中移除,見圖5。

image.png

圖5

之后便可再選擇合適時機觸發”kfree()”將其釋放,而此時當server進程繼續使用”t->buffer”時便觸發了use-after-free問題。這樣我們就可以借助堆噴技術來實現任意地址讀寫以及信息泄露。

漏洞利用

內核中每年公開的漏洞數量都多達數百個,但真正能夠成功提權的寥寥無幾。而近年來隨著系統防護的不斷完善,此前一些可以用來ROOT的漏洞,如果處在現有的防護機制下也變的無能為力。在Android的通用模塊出現這類具備了任意地址讀寫、信息泄露能力,同時還可能用于沙箱逃逸的漏洞十分少見。即便隨著Android系統后續一些新的防護機制引入,這類漏洞仍有可能具備很強的攻擊潛力。由于漏洞的特點,攻擊手法也是仁者見仁智者見智,我們也做出來幾種不同的利用方案,這里會介紹漏洞利用的基本思路,具體的細節這里不會放出。

任意地址寫

調用合適的堆噴函數去占位該”t->buffer”對象,堆噴成功后,圖3中3178行所示的"t->buffer->data"可由攻擊者完全控制,而"tr->data.ptr.buffer"是server進程發給用戶進程的reply數據,可由攻擊者間接控制。當“copy_from_user()”函數被執行時,便觸發了任意地址寫問題。

任意地址讀

server進程此后又會調用“binder_enqueue_thread_work_ilocked()”函數向用戶進程發送消息,如圖6中3377行所示。

image.png

圖6

與此同時,用戶端進程在循環調用“IPCThreadState::talkWithDriver()”等待server進程的響應。當有消息到達時,內核會通過調用圖7中4100, 4107行所示函數,將server進程發送過來的“struct binder_transaction”類型的對象取出,并保存在變量”t”中,其中“t->buffer”是被我們控制的惡意對象,而"target_node"”struct binder_buffer”結構體的一個成員變量,若將其設置為非空值,將會被當成”struct binder_node”類型的指針,并從該指針加0x58、0x5c位置取值賦值給”tr.target.ptr””tr.cookie”。此后內核再調用4319行所示的”copy_to_user()”將數據傳遞給用戶進程。通過這一機制我們便可以實現任意地址讀。

image.png

圖7

信息泄露

通過尋找一些帶有敏感信息的結構體對”t->buffer”進行堆噴,“t->buffer->target_node”, “t->buffer->data_size”, “t->buffer->data”都將作為信息泄漏點,將堆噴結構體中的敏感數據泄露給用戶進程。

時間節點

  • 2018-08月份發現該漏洞,確認了漏洞危害及影響范圍;
  • 2018-09-28提交至Google;
  • 2018-10-06 Google回復郵件,進一步確認問題細節;
  • 2018-10-23 Google確認該問題;
  • 2018-11-02 提交漏洞利用至Google;
  • 2018-11-06 Linux kernel主線上修復該問題;
  • 2018-12-18告知漏洞公開時間,并多次在郵件中致謝;
  • 2019-03-05安全公告,漏洞編號為CVE-2019-2025;

image.png

我們是全球首個發現該漏洞并提交至Google的安全團隊,同時由于漏洞本身的嚴重性,并且我們成功利用這一漏洞繞過了代表谷歌安卓目前最高水平的內核防護機制,完成了針對Google旗下三款Pixel系列機型的完美ROOT,也收到了Google誠摯的致謝。

image.png

總結

漏洞在原理上擁有極強的攻擊能力,但在實際利用過程中還是有一定的門檻,需要非常熟悉漏洞利用技巧及內核的相關知識才能將其穩定的利用,我們在Pixel系列設備上能夠實現近100%的漏洞觸發成功率。在Android系統安全防護日臻健全的時代,這類通殺漏洞更是具備了稀缺性,也是黑產從業者夢寐以求的,安全研究人員如果不能趕在他們之前發現并修補該漏洞,一旦被黑產從業者掌握并大規模利用,造成的損失將難以估計。各家Android廠商也需盡快修復該問題,避免用戶暴露在安全風險之中。

參考

[1] https://weibo.com/tv/v/HaeCNbLmz?fid=1034:4324393006868015

[2] https://lore.kernel.org/patchwork/patch/805040/

[3] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7bada55ab50697861eee6bb7d60b41e68a961a9c


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