作者:騰訊安全科恩實驗室
原文鏈接:https://mp.weixin.qq.com/s/mrUEtSbh7chpuTmHj1C0mQ
概要
近年來,5G蜂窩網絡被廣泛應用。設備為了加入5G網絡,都必須配備一個5G調制解調器,負責調制信號和執行無線電協議。該組件通常也被稱為基帶。這些組件非常重要,因為它們負責處理來自無線電網絡的不可信數據。在之前的工作中,科恩實驗室研究了上一代網絡(2G 3G 4G)的安全調制解調器,并實現了遠程無接觸的0-click代碼執行。
本次Black Hat USA 2021,科恩實驗室成員Marco與Xingyu Chen在北京時間8月6日凌晨以線上形式分享了議題《基帶利用:遠程5G智能手機代碼執行》。該議題探討了5G網絡發生的變化以及安全性方面的改進,并證明了仍然有可能通過無線的方式攻擊5G調制解調器完成遠程代碼執行。
議題完整白皮書下載見文末

作者簡介
Marco:
騰訊科恩實驗室高級研究員,研究涉獵iOS、Safari、VMWare、基帶等多個方向,多次作為核心成員參與Pwn2Own、Mobile Pwn2Own并獲得冠軍,多次在國際安全會議上進行演講,包括Black Hat USA, DEF CON, CanSecWest, ZeroNights, Codegate, HITB and ShakaCon等。
Xingyu Chen:
騰訊科恩實驗室安全研究員。主要研究虛擬化和移動安全,曾在不同的云產品和智能手機的低級固件中發現了許多關鍵漏洞。曾作為A*0*E聯合戰隊選手參加多場CTF比賽,也是DEF CON 28 CTF 決賽總冠軍隊伍成員。多次在國內外安全會議上進行演講,包括OffensiveCon、Zer0Con和Tensec等。

1.背景
多年來,5G網絡和基帶的安全問題一直沒有得到全面的討論。我們之前的工作是研究老一代網絡的安全性,并研究了市面上多款調制解調器的實現,安全研究員Amat Cama也發表了一項關于老一代網絡的研究,展示了如何在pwn2own競賽上成功地攻破三星Shannon基帶。來自Comsecuris的研究分析了三星和英特爾基帶的安全性。
建議讀者將上述這些研究作為理解和熟悉本文的參考。我們也將對研究背景和5G網絡的新概念進行簡單描述。
2.目標介紹
我們購買了當時可用的幾款5G智能手機,他們都支持5G中的“New Radio”。 5G設備區分: - 非獨立模式(NSA):該模式使用了5G新無線電,并利用了4G網絡的其他組件。 - 獨立模式(SA):該模式完全實現并使用了5G New Radio和5G網絡規范。由于我們認為未來將使用獨立模式(SA)作為標準,因此我們決定專注于該模式的研究。
我們的測試設備的SoC為Exynos 980并具有三星Shannon基帶。 基帶在其自己的ARM Cortex內核上運行自己的固件和RTOS,與運行Android操作系統的應用處理器 (AP) 分開。 AP和基帶可以例如通過PCI-e、共享內存或其他方式進行通信。我們從設備的OTA包中恢復了基帶固件。基帶固件位于modem.bin二進制文件中。解壓并找到加載地址后,我們可以在IDA Pro中加載它并開始尋找漏洞。
3.審計范圍和漏洞挖掘
經過一段時間的5G相關代碼審計,我們發現了多處漏洞,在此我們選擇了其中最穩定的一個來分享,希望您也會通過它對基帶當前的安全狀態有所認識。在審計調制解調器固件時,我們發現它仍然缺少Stack cookie保護。因此,考慮到在這種環境中缺乏調試功能,使用傳統的棧溢出將使我們的利用更容易。 本文選擇的bug是一個棧溢出。它不僅是棧溢出,而且是基帶內部XML解析器中的棧溢出。此 XML解析器負責解析從網絡到設備調制解調器的IMS消息。
3.1 攻擊背景
IMS是4G和5G網絡中的專用架構,常用的語音呼叫建立在其之上,稍后我們將看到為什么這對本研究很重要。基帶是一個IMS客戶端,負責處理VoLTE、VoNR消息,因此它必須能夠處理SIP消息,IMS服務器使用這些消息與基帶進行通信。 白皮書內查看INVITE消息示例 SIP 是一種基于文本的類似HTTP的協議,包括標頭和內容。 接收方(在本文中為基帶)需要解析來自服務器的消息。對于不同的消息,內容不僅可以是鍵值對,還可以是XML格式的文本。XML是一種復雜得多的數據格式,通常由專用庫處理。 以上都為基帶引入了一個新的攻擊面。
3.2 漏洞
我們的OTA RCE漏洞在基帶的IMS模塊。 在解析SIP協議消息的XML內容時,它會調用函數IMSPL_XmlGetNextTagName 。
由于我們的目標基帶沒有調試符號或信息,所以所有的函數名稱、類型和函數簽名,都是從日志字符串中提取,或是通過逆向工程手動恢復。
我們在這里提供了一個反編譯版本,其中省略了一些代碼。
int IMSPL_XmlGetNextTagName(char *src, char *dst) {
// 1. Skip space characters
// 2. Find the beginning mark '<'
// 3. Skip comments and closing tag
// omitted code
find_tag_end((char **)v13);
v9 = v13[0];
if (v8 != v13[0]) {
memcpy(dst, (int *)((char *)ptr + 1), v13[0] - v8); // copy tag name to dst
dst[v9 - v8] = 0;
v12 = 10601;
// IMSPL_XmlGetNextTagName: Tag name =
v11 = &log_struct_437f227c;
Logs((int *)&v11, (int)dst, -1, -20071784);
*(unsigned __int8 **)src = v13[0];
LOBYTE(result) = 1;
return (unsigned __int8)result;
}
// omitted code
}
此函數將從src解析XML標記并將其名稱復制到dst ,例如<meta name="viewport" content="width=device-width, initial-scale=1">到目標緩沖區。接下來,我們展示反編譯函數find_tag_end(手動命名)并解釋它是如何工作的:
char **find_tag_end(char **result) {
char *i; // r1
unsigned int v2; // r3
unsigned int cur_char; // r3
for (i = *result;; ++i) {
cur_char = (unsigned __int8)*i;
if (cur_char <= 0xD && ((1 << cur_char) & 0x2601) != 0) // \0 \t \n \r
break;
v2 = cur_char - 32;
if (v2 <= 0x1F &&
((1 << v2) & (unsigned int)&unk_C0008001) != 0) // space / > ?
break;
}
*result = i;
return result;
}
該函數通過跳過特殊字符來查找標簽的結尾,例如空格、‘/’、‘>’、‘?’。在了解整個功能的工作原理后,我們注意到根本沒有安全檢查。該函數不知道目標緩沖區和源緩沖區有多長。 因此,該函數的所有調用者都可能被傳統的緩沖區溢出所利用。通過交叉引用函數IMSPL_XmlGetNextTagName,我們發現了數百個調用位置。
它們中的大多數都容易受到攻擊,因為源緩沖區是從OTA 消息中獲取的,完全由攻擊者控制。
4. Exploit
我們選擇棧溢出是為了漏洞利用的便捷和可靠。正如我們之前所說,由于沒有棧cookie,所以我們可以簡單地溢出緩沖區,控制存儲在棧上的返回地址,并獲得代碼執行。 我們終于通過逆向工程找到了一個很好的候選者:
int IMSPL_XmlParser_ContactLstDecode(int *a1, int *a2) {
unsigned __int8 *v4; // r0
int v5; // r1
log_info_s *v7; // [sp+0h] [bp-98h] BYREF
int v8; // [sp+4h] [bp-94h]
unsigned __int8 *v9; // [sp+8h] [bp-90h] BYREF
int v10; // [sp+Ch] [bp-8Ch] BYREF
char v11[136]; // [sp+10h] [bp-88h] BYREF
bzero(v11, 100);
v10 = 0;
v4 = (unsigned __int8 *)*a1;
v8 = 10597;
v9 = v4;
// ------------------%s----------------------
v7 = &log_struct_4380937c;
log_0x418ffa6c(&v7, "IMSPL_XmlParser_ContactLstDecode", -20071784);
if (IMSPL_XmlGetNextTagName((char *)&v9, v11) != 1) {
LABEL_8:
*a1 = (int)v9;
v8 = 10597;
// Function END
v7 = &log_struct_43809448;
log_0x418ffa6c(&v7, -20071784);
return 1;
}
// omitted code
}
我們可以很容易地確認變量v11是棧上大小為100的緩沖區。潛在的棧溢出可能發生在這里。 在臨近的函數中也能發現類似的問題,例如IMSPL_XmlParser_RegLstDecode,IMSPL_XmlParser_ContElemChildNodeDecode。根據函數名,我們可以推斷觸發的標簽應該在元素Contact List內。通過向上交叉引用函數來總結調用棧并不困難。
IMSPL_XmlParser_RegInfoDecode --> IMSPL_XmlParser_RegInfoElemDecode --> IMSPL_XmlParser_RegLstDecode --> IMSPL_XmlParser_RegistrationElemDecode --> IMSPL_XmlParser_ContactLstDecode
這些函數名稱很容易理解。我們可以分辨出變異的payload可以通過SIP協議中的NOTIFY消息傳遞。 一個能讓基帶崩潰的簡單PoC可以從普通的NOTIFY消息構造。
由于payload是以XML格式發送,因此對payload存在限制。
記得上面提到的find_tag_end函數,它會將標簽名中的以下字符列入黑名單:"\x00\x09\x0a\x0d\x20\x2f\x3e\x3f"。 因此,在編寫ROP鏈和shellcode時我們不能使用所有可用的字符。除此之外,剩下的是ARM平臺上的傳統pwnable挑戰。
4.1 Exploitation Payload
白皮書內查看詳細PoC
利用點為函數IMSPL_XmlParser_RegLstDecode,為了避免在 ROP 執行后修復棧幀,并能讓基帶仍然正常工作,最好選擇一個較深的地方來觸發棧溢出。 所以registration中的一個元素標簽是個不錯的選擇。
payload結構:
有效載荷以 100 個字節“A”開頭,然后是棧中保存的寄存器 R4-R11,ROP 鏈從棧中復制 shellcode 并最終跳轉到 shellcode
4.2 漏洞利用的可視化演示
為了驗證我們是否在目標設備上獲得了RCE,我們可以檢查手機的ADB日志。它將顯示有關蜂窩處理器(CP)如何崩潰的信息。然而,這既不是一種方便的方式,也不是一種很好的視覺效果。因此,我們選擇通過在基帶內執行shellcode來修改設備的IMEI。按照設計,IMEI不應在手機分發后進行修改。當我們報告整個利用鏈時,這也被視為一個bug。NVRAM是Non Volatile Memory,用于存儲與基帶相關的持久化信息。IMEI是存儲在基帶NVRAM中的一項,但是要修改它的值,首先要知道它的索引。
白皮書內查看IMSSH_GetImei函數示例
基帶中有多個地方調用函數獲取IMEI。可以通過逆向函數GetImei來檢索索引。在我們的例子中,IMEI1/2的索引分別是0x39a4/0x39a5。有了索引,我們就可以通過在shellcode中調用API pal_RegItemWrite_File 來修改IMEI。
5.執行
5.1 環境配置
要觸發這個 bug,我們需要先搭建一個提供 IMS 服務的網絡,然后向基帶發送格式錯誤的短信。 我們的測試環境至少需要一個LTE網絡。 雖然它在技術上是一個影響4G和5G的漏洞,但在2020年初,5G的基礎設施還沒有成熟到足以支持像我們這樣的獨立研究人員測試其安全性。因此我們決定建立一個支持VoLTE的LTE網絡來測試設備。
5.1.1 SDR Choice
作為設置基站的首選硬件,我們選擇了Ettus USRP B210,這是一種在研究人員中非常流行的SDR無線電設備。

5.1.2 LTE network setup
我們使用了大量開源組件和硬件來完成我們的測試,以下是一些較為重要的: - srsENB: 這是srsLTE中的eNodeB實現。 它負責直接無線連接到移動手機(UE)。 - Open5GS:我們在LTE網絡中使用了它的EPC實現。它們是hss、mme、pcrf、pgw、sgw。 - sysmo-usim-tool&pysim:SIM卡編程工具。 - CoIMS&CoIMS_Wiki:修改手機IMS設置的工具。 - docker_open5gs:用于在docker容器中運行具有VoLTE支持的open5gs。
UE能夠在適當的LTE網絡設置后連接到網絡,然后我們可以繼續進行IMS服務器設置。在我們的測試中,幾乎所有不同廠商的基帶對eNodeB的頻率都非常敏感。您可以查看設備官方信息以獲取其支持的頻段,然后為srsENB選擇合適的Downlink EARFCN參數。

5.2 IMS server setup & hack
由于該漏洞只能由提供VoIP服務的惡意IMS服務器觸發,因此基本的LTE網絡不足以觸發該漏洞。不幸的是,滿足這種需求的基礎設施還遠未成熟。現有的開源項目Kamailio滿足了我們的需求,但還沒有在各種設備(包括我們使用的)上進行很好的測試。 需要付出巨大的努力才能使其工作并成功發送有效payload。 VoLTE服務器的基本組件是Rtpengine、FHOSS、P-CSCF、I-CSCF和S-CSCF。 以下是網絡拓撲:
SUBNET=172.18.0.0/24
HSS_IP=172.18.0.2
MME_IP=172.18.0.3
SGW_IP=172.18.0.4
PGW_IP=172.18.0.5
PCRF_IP=172.18.0.6
ENB_IP=172.18.0.7
DNS_IP=172.18.0.10
MONGO_IP=172.18.0.11
PCSCF_IP=172.18.0.12
ICSCF_IP=172.18.0.13
SCSCF_IP=172.18.0.14
FHOSS_IP=172.18.0.15
MYSQL_IP=172.18.0.17
RTPENGINE_IP=172.18.0.18

IMS(SIP)消息通過TCP或UDP套接字以IP數據的形式承載。因此,客戶端會首先選擇IPSec來進行消息傳輸。XML payload只能通過NOTIFY消息攜帶,因此我們的客戶端必須成功REGISTER和SUBSCRIBE。

在進行初步的搭建后,一加6(non-IPSec)、Google Pixel 3(IPSec)可以成功注冊VoLTE服務,這意味著我們的環境在高通的芯片上能夠很好地工作。但是在使用三星芯片的手機上,整個流程會在注冊時失敗。 但是這些設備能夠使用當地運營商的普通SIM卡注冊VoLTE,這讓我們對修改Kamailio配置和代碼充滿希望。 首先要做的是在電話上捕獲成功的注冊流量。 幸運的是,三星的Sysdump Utility中有一個內置的IMS調試工具IMS Logger,它允許我們查看來自應用程序的IMS流量。 下面是一個正常的注冊消息及其響應:
REGISTER message
Server responses with challenge to the UE
Failed registration response
Kamailio和本地運營商之間存在一些差異。 我們并不真正知道哪個字段是注冊失敗的關鍵。 我們方法是讓它們看起來盡可能相似。
在對Kamailio進行了一些更改后,我們取得了一點進展,我們收到了第二條注冊消息。 那么問題就到了服務器端,它并沒有提供STATUS 200響應。

經過調查,我們發現服務器和客戶端之間的IPSec不一致。 我們決定從服務器端強制禁用IPSec。以下是我們打的補丁:
Patch to remove IPSec related headers
Part of the cfg patch
5.2.1參考
VoLTE/IMS Debugging on Samsung Handsets using Sysdump \& Samsung IMS Logger Reverse Engineering Samsung Sysdump Utils to Unlock IMS Debug \& TCPdump on Samsung Phones
5.3. Payload Delivery
一旦UE注冊并訂閱到SIP服務器,服務器將發送NOTIFY消息以提供網絡中的基本信息,比如其他UE的聯系方式等。而payload會以XML的格式存在于NOTIFY消息中。該消息的負責模塊是S-CSCF。這是要修改以生成任意有效payload的函數:
str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus, str *explit_dereg_contact, int num_explit_dereg_contact, unsigned int reginfo_version);
6.結論
在這項研究中,我們展示了下一代Android設備配備的5G基帶安全狀態。盡管在網絡功能方面已經發生了演變,但我們看到在安全性方面仍然沒有過多進步。正如我們實際上已經展示的那樣,一些基帶缺乏最基本的安全措施,例如棧cookie保護,這讓攻擊者能夠使用緩沖區溢出等簡單攻擊無線攻擊它們。我們在三年前進行過安全研究,但是至今情況似乎沒有太大改善。 我們希望在三年后我們可以再次展示一些研究,在一個更加嚴格的環境中。
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1663/
暫無評論