作者:騰訊科恩實驗室
議題概要
據估計,全球有超過30億的智能手機,而基帶是智能手機的重要組成部分,負責處理和與移動無線網絡(如2G、3G、4G等)通信。因此對基帶進行安全性評估的重要性不容小覷。由于目前有關基帶的研究主要是用于灰色產業,因此公開的研究資料非常有限。此外,無線電協議和軟件的復雜性也導致基帶研究的門檻非常高。基帶可以在無需任何用戶交互的情況下從無線網絡遠程訪問,這個特性也讓它具有非常高的研究價值。
本議題將討論現代智能手機基帶設計以及安全對策。該議題將以Mobile Pwn2Own 2017基帶項目中使用的0day漏洞為例,闡述騰訊安全科恩實驗室發現并利用該漏洞實現遠程代碼執行的過程和細節。通過利用該漏洞,騰訊安全科恩實驗室最終完成了在更新后的華為Mate 9 Pro上無用戶交互條件下的遠程代碼執行,并在該項目上贏得了10萬美元獎金。華為也在第一時間響應并打補丁解決了這個問題,展現了企業非常專業的合作精神與責任擔當。更多詳細信息歡迎關注騰訊科恩實驗室官方微信號:KeenSecurityLab,回復“基帶安全”即可獲得《現代智能手機基帶破解》研究技術細節白皮書!

作者簡介
Marco Grassi,騰訊科恩實驗室高級研究員,研究涉獵iOS、Safari、VMWare、基帶等多個方向,多次作為核心成員參與Pwn2Own、Mobile Pwn2Own并獲得冠軍,多次在國際安全會議上進行演講,包括Black Hat USA, DEF CON, CanSecWest, ZeroNights, Codegate, HITB and ShakaCon等。

劉穆清,騰訊科恩實驗室安全研究員,主要研究固件安全、二進制分析、安全研究工具開發,同時也是CTF選手,作為騰訊eee戰隊及0ops戰隊隊員曾多次參與CTF比賽,并和A0E聯隊成員一起參與了今年的DEF CON CTF。

謝天憶,騰訊科恩實驗室高級研究員,CTF選手,騰訊eee戰隊及A0E聯隊隊長,Pwn2Own 2017 VMware項目冠軍隊伍成員,Mobile Pwn2Own 2017 Baseband項目及“Master of Pwn”冠軍隊伍成員。

議題解析
現代智能手機是一個非常復雜的系統,它包含一個主CPU以及許多次級CPU,這些CPU共同協作完成各項任務。其中,主CPU也可以稱為AP(應用程序處理器)。在這些CPU中,我們可以找到Wi-Fi SoC模塊和基帶模塊。

AP運行各種操作系統(如Android或iOS),而基帶運行RTOS(實時操作系統)。它們作為系統獨立存在,通常通過USB、PCI-e、共享內存或其他機制進行通信。如果僅在基帶上實現代碼執行,并不意味著可以在AP上實現代碼執行。

事實上,讓我們決定將研究目標定位在基帶模塊的原因有許多,主要原因如下:
- 基帶不太容易理解并且攻擊面審計比較少;
- 基帶可以在遠距離且在無需用戶交互的情況下遠程破解;
- 基帶在漏洞利用的緩解措施方面,相比較現代操作系統(如Android和iOS)要落后一些。
- 由于基帶一般是來自第三方,因此設備制造商沒有辦法審計基帶源代碼。
- 基帶是一個非常復雜的系統。
基帶基本上就是一個在手機獨立的CPU中運行的固件黑盒。在某些方面,它和物聯網設備類似,其上運行一個實時操作系統(RTOS),負責調度系統組件的各種任務。由于基帶芯片需要支持多種協議棧,其實現通常非常復雜。相關的協議規范文檔通常就有數萬頁之多。
一般來說,在系統中,每個網絡層都有一個任務與其對應,例如MM任務,SM任務等。通過定位無線電消息被解析和處理的地方可以更容易地找到消息處理程序,之后就可以開始尋找消息處理程序的內存泄露錯誤。

作為第一步,我們需要找到并分析固件。由于我們將華為作為一個研究案例進行展示,所以我們將重點關注該固件。

我們可以在Android phone文件系統中找到文件名為“sec_balong_modem.bin”的固件文件。 該文件由Android內核加載并傳遞給TEE(可信執行環境)進行簽名檢查,再將其加載到基帶中。我們使用IDA Pro對其進行逆向分析。
在分析過程中,我們迅速注意到華為基帶缺乏ASLR和棧cookie,此外,其他許多廠商也缺乏這些保護措施。第二步我們收集運行時信息。之前是通過使用“cshell”在基帶上獲得有限的調試能力,但最近它被移除了。
我們嘗試后發現當基帶崩潰時,它會將有用的日志輸出給AP用來進行日志記錄。除此之外,當我們在Android內核中運行代碼,我們可以在物理內存0x80400000地址開始讀取數據來獲取基帶內存數據。這為我們后續調試基帶利用方案提供很大幫助。
我們還可以找到一個描述NVRAM格式的開源項目,開源項目地址為:https://github.com/forth32/balong-nvtool。
網上其他的信息也非常有用。我們花了一些時間做調研,在GitHub發現一個泄漏的舊版本華為基帶源代碼。盡管代碼并不是最新的,但這份源代碼對于逆向工程起到很大的幫助作用。此外,我們還在網上找到理解無線電協議所需的所有3GPP規范。
但是我們究竟是如何攻擊基帶呢?
毋庸置疑的是我們一定是通過無線電通信進行攻擊的。這種攻擊的“傳統”思路是模擬一個假基站,然后攻擊手機。

最常見的方法是使用SDR(軟件定義無線電)。一方面,SDR的價格在可接受的范圍內,另一方面,一些開源工程為我們的研究提供了幫助。這些積極因素有效地降低了我們的研究難度。SDR可以是USRP(通用軟件無線電外設)或BladeRF(USB 3.0超高速軟件定義無線電)。一臺帶有SDR的筆記本電腦就可以模擬一個基站(BS)。由于一些無線電技術沒有采用相互認證的方式,因此手機會連接到那些惡意構造的偽基站。
但實際真的那么好利用嗎?事實并沒有想象的那么簡單,我們并不能直接使用SDR和開源軟件。我們Pwn2Own漏洞實際是在華為基帶的CDMA(碼分多址)部分。CDMA是一種3g網絡,在部分地區也有使用UMTS(通用移動通信系統)進行3G網絡傳輸。
我們使用的bug是在CDMA 1x SMS傳輸層消息部分中一個負責解析PRL(出國優選漫游列表)消息的函數中。這個bug的簡化版本如下:

這里我們注意到了一個函數:memcpy_s。這個函數和memcpy一樣,可以將指定長度的數據復制到另一塊內存區域中,但和memcpy不同,除了原有的三個參數(源地址、目的地址和源數據長度)外,該函數還增加了一個size_t類型的參數,用來表示目的地址的存儲空間大小。利用這個參數,在復制時,memcpy_s函數可以檢查被拷貝的數據大小不會超過目的地址的大小,從而在無意中避免了很多bug。
但這并不會影響我們要利用的漏洞,因為我們控制拷貝數據的目的地址而不是長度。我們在了解memcpy_s的基礎上再來查看這個bug,可以看到消息處理器在解析消息時,會提取部分偏移量/長度,然后在沒有檢查的情況下,它們被添加到byte_pos,從而導致可利用的棧溢出。

那么我們該如何觸發這個bug呢?首先需要建立一個CDMA網絡。但這并不容易。目前并沒有公開的實現方法可以在SDR上運行運行CDMA 1x基站。我們也沒有時間自己再實現一遍,所以我們想出了一個不走尋常路的解決方案。我們購買并更改了一臺Rohde&Schwarz CMU200設備。

這臺設備本身是用來測試設備的信令和非信令功能。它還支持CDMA 1x標準,我們將通過逆向工程以及打補丁的方式使用這臺設備完成發送任意數據包的需求。

這臺設備常規的工作流程如下:

但我們希望設備可以直接轉發PDU而不對其進行編碼和數據包組裝:

那么該怎么做才能實現這樣的目標呢?CMU 200運行在MS-DOS和Windows 3.x版本系統上,用戶可以在UI圖形界面中發送短消息。我們首先研究設備的文件系統以及逆向PE文件。

我們找到一個名稱為“C2KMS.DL3”的文件,這個文件會讀取短消息的文件內容,并將短消息傳送到B83 CDMA模塊進行發送。我們在這里更改了一個長度檢查,但是我們不能完全控制數據。

所以我們需要進一步修改B83模塊固件。我們在文件系統中找到了B83固件,在恢復文件格式之后,對它進行逆向分析。

非常幸運的是,首先B83子板基于PowerPC平臺(一種精簡指令集RISC的中央處理器架構),而我們也有其固件對應的反編譯器。其次,固件本身沒有進行簽名檢查,只有CRC(循環冗余校驗)。此外,二進制文件中符號表數據也保留著!

我們繼續定位“buildSmsMsg”函數,并修改函數使得可以攜帶任意數據。然后我們刷新B83模塊,此時我們就可以發送任意的PDU(協議數據單元)了。

現在我們將要嘗試觸發bug并使基帶crash!我們該如何利用這個bug呢?這個過程也并不像看起來那么簡單! 攻擊payload是一條畸形的CDMA 1x SMS傳輸層消息。其SMS_MSG_TYPE字段必須是00000000,表示SMS點對點消息。

該消息由TLV格式的參數組成,其中一些參數必須被設置正確才能確保觸發有漏洞的函數,包括:
- Teleservice Identifier(PARAMETER_ID 00000000)
- Originating Address(PARAMETER_ID 00000010)

在這些參數中,Bearer Data(PARAMETER_ID 00001000)會在漏洞函數中被解析:

Bearer Data(PARAMETER_ID 00001000)在漏洞函數中被解析為由TLV格式的子參數組成的結構。為此我們必須適當地配置子參數以表示該消息為PRL消息。

類型為Message Display Mode (SUBPARAMETER_ID 00001111)的子參數最為關鍵,其中:
- MSG_DISPLAY_MODE字段必須設為0x03
- RESERVED字段必須設為0x10

漏洞代碼的基本功能是對Bearer Data中的子參數進行排序,緩沖區溢出就發生在該部分代碼中。乍一看,這種利用似乎非常容易,因為沒有NX/ASLR/Stack Canary等保護措施,看起來就像90年代的典型棧溢出利用。但這是真的嗎?
事實上,盡管有多條路徑可以觸發漏洞函數,但并不是所有的路徑都可以通過空口消息觸發。其中有一條路徑可以通過空口消息觸發,但是此時能夠被溢出的那個緩沖區并不在棧上,而是在全局變量段中。還有另一條將緩沖區放在棧上的路徑,但限制條件是只有當手機從USIM卡中讀取短消息的時候才能觸發,看上去對遠程利用這個漏洞沒什么幫助。到這里為止,所有的可能性都被考慮過了,但仍然沒有發現任何明顯可行的方法,似乎前方是一條沒有出口的死路。

但永不放棄始終是我們的信條。通過對該部分邏輯更深刻地理解,我們最終找到了一條非常深但是十分穩定的路徑。
基帶處理PRL消息的整個過程如下:
- 通過空口接收信息
- 解碼消息(第一次觸發漏洞函數,但緩沖區不在棧上)
- 編碼消息
- 將消息寫入USIM卡
- 從USIM卡中讀出信息
- 解碼消息(第二次觸發漏洞函數并且緩沖區在棧上)
Payload必須能通過第一次解碼和編碼的過程,并在第二次解碼的過程中溢出棧緩沖區。為了構造這樣的payload,我們需要一些簡單的數學上的抽象:
- Payload:x
- 解碼函數——dec(x)
- 編碼函數——enc(x)
- 棧溢出ROP鏈:p
- 目標:對于給定的p,找到一個x使得p = dec(enc(dec(x))) 讓我們用更優雅、更數學的方法來解決這個數學問題。我們的目標變為: 對給定的p,找到一個x,使得p = dec(x)且x = enc(dec(x))
- 這里的x也稱為復合函數enc(dec(x))的不動點
因此可以很容易導出p = dec(x) = dec(enc(dec(x))),正是我們想要的結果。通過這種方法構造的payload適用于任意多次的解碼和編碼過程,而不僅僅是一兩次。此外,CMU200設備限制TP層消息(也就是我們的payload)的長度必須小于等于130字節,更給我們的構造過程增加了難度。
事實證明,構造這個Payload并不是一帆風順的,但它是可以實現的! 更多細節請閱讀我們的白皮書。我們也把這個漏洞的利用過程改編成了今年TCTF預選賽中的一道pwnable題目——Mighty Dragon,其名字正是來源于基帶的代號“霸龍”。在當時的比賽中僅有一支隊伍解出了這道題目,可見這道題是非常有挑戰性的,歡迎感興趣的小伙伴踴躍嘗試,關注微信號“KeenSecurityLab”并回復“Mighty Dragon”獲取題目下載鏈接。
在我們實現漏洞利用之后,我們如何展示呢?我們不能像在Windows上那樣運行一個calc.exe計算器可執行程序來進行演示。最終,我們決定將手機IMEI修改成1337XXX,這樣我們可以從手機設置UI看到修改后的變化。
在成功得到基帶中的代碼執行能力后,我們可以得到很多信息,比如間諜短信,電話,互聯網流量,甚至可以修改這些信息。盡管比賽沒有要求完成基帶繞過,但許多其他研究人員的研究結果表明這是可以實現的。例如Project Zero的Gal使用WiFi芯片中的DMA來修改內核內存,Comsecuris使用MTK基帶中的路徑遍歷來覆蓋AP中的文件。這也和瀏覽器漏洞類似,在實現第一個RCE(遠程代碼執行)之后,你可以結合沙箱逃逸漏洞構建完整的攻擊鏈。基帶在實現第一個RCE之后,也可以構建一條基帶逃逸攻擊鏈,并得到完整的系統控制。
最后,我們想和大家說的是,只要你足夠堅定,在現代基帶實現遠程終端控制是完全有可能的。這種攻擊也是真實的存在的。究其根本,一方面基帶是由內存不安全的語言編寫的,因此無法避免內存破壞問題,另一方面,基帶安全也一直沒有受到足夠的重視。

我們也希望基帶在未來的部署中可以考慮更多安全緩解措施,也許將來也會用內存安全的語言編寫基帶。
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/667/
暫無評論