【OSG】macOS 10.12.2本地提權和XNU port堆風水
首發看雪論壇:【OSG】macOS 10.12.2本地提權和XNU port堆風水
0x00 簡介
從yalun10.2 中,我們可以學到很多新的漏洞利用技術,特別是XNU堆風水和繞過內核保護。 在本文中,我們將討論XNU堆風水的一些技術細節,並使用該技術在macOS中獲得root許可權。最後但同樣重要的是,漏洞源碼可以從以下網址下載:
nnzhengmin1989/macOS-10.12.2-Exp-via-mach_vouchernnnn0x01 內核堆棧溢出
為了使用XNU堆風水在macOSn10.12中獲得root許可權,我們需要一個內核漏洞。在本文中,我們選擇mach_voucher堆溢出為例,Mach_voucher_extract_attr_recipe_trap()n是可以在沙箱內被調用的Mach陷阱。這是在iOS 10和macOSn10.12中新添加的功能,但是它含有一個嚴重的緩衝區溢出漏洞。
nn在這個函數中,args->recipe_size是一個指向整數的用戶態指針,所以mach_voucher_extract_attr_recipe_trap()n將通過copyin() 從用戶態拷貝size的值。
nn
然後該函數使用sz值在內核堆上分配一個內存塊。但是,開發人員忘記了args->nrecipe_size是一個用戶態指針,然後將其用做copyin() 中的 size 值。 我們知道用戶態指針可能大於sz值,這將導致內核堆中的緩衝區溢出。
nn請注意,如果我們要在該地址上分配一個內存塊,我們可能無法控制用戶態指針的地址。不過這不是問題。如果遇到未映射的內存,copyin() 函數會自動停止。 所以,我們可以在高地址上分配一個內存塊,然後通過取消映射其餘的內存塊來控制溢出數據。
0x02 通過port進行堆風水
在iOSn10和macOSn10.12中,蘋果添加了一個新的防護機制,用以檢查在錯誤區域釋放的攻擊,因此我們無法使用經典的vm_map_copy(修改vm_map_size)技術來執行堆風水。另外,蘋果在iOSn9.2和macOSn10.11中添加了一個空閑列表(freelist)隨機化的機制,所以我們不能較容易地預測再分配的內存塊的位置。 為了解決這些問題,我們需要一個新的堆風水技術。在Yalun10.2中,qwertyoruiop使用OOL_PORTS來獲取可用於執行任意內核內存讀寫的內核任務埠。 這種技術繞過了XNU堆中的所有防護機制。接下來,我們將討論這種技術的細節。
Mach msg是XNU中最常用的IPC機制,大量消息通過 「complicated message」 發送。通過MACH_MSG_OOL_PORTS_DESCRIPTORnmsg_type的 」complicatednmessage」,我們可以向內核發送out-of-line埠。例如,我們發送了32個MACH_PORT_DEADnool埠(32n* 8位元組=0x100位元組)到內核的kalloc.256區域。
nnnnnn保存在machnmsg中的ool埠都是ipc_object類型的指針,這類指針可以指向用戶態地址。 因此,我們可以使用mach_voucher漏洞來溢出這些指針,並在用戶態下修改一個ipc_object指針,使它指向一個偽造的ipc_object。 另外,我們也可以在用戶態下為假的埠創建假的任務。
nnnnnn為了保證溢出正確的ipc_object指針,我們需要做一些堆風水操作。 首先,為了確保新分配的內存塊是連續的,我們向內核發送大量的ool埠消息。 然後使用在中間收到的一些消息戳一些slots。 然後我們再次發送一些消息,使得溢出點在slots的中間部位。 最後,我們使用mach_voucher在溢出點觸發堆溢出。
溢出之後,我們可以接收到剩餘得 mach 消息,來找到被破壞的埠(不是MACH_PORT_DEAD 埠)。
nn0x03 內核內存任意讀寫
首先,我們將偽造的ipc_object的io_bits設置為IKOT_CLOCK。所以我們可以使用clock_sleep_trap() 通過遍歷內核來獲取內核中計時任務的地址。 這個地址將幫助我們稍後找到內核數據。
然後我們將偽造的ipc_object的io_bits設置為IKOT_TASK,為假的埠製造一個假的任務。 通過將值設置為faketaskn+ 0x380(在arm64中為0x360),我們可以通過pid_for_task() 讀取任意32位內核內存。這是因為該函數不檢查任務的有效性,只返回((faketaskn+ 0x380)+n0x10)的值。 所以我們可以在沒使用任何工具和ROP的情況下獲得可造性內核讀取。
nnnn通過計時任務泄露內核地址,我們可以在內存中搜索內核鏡像的魔數,然後找到kslide。
獲取內核基地址後,我們可以遍歷所有進程來查找內核ipc_object和內核任務。然後我們可以dump出這些信息,給我們的偽造的ipc_object和任務。通過對假的ipc_object和任務使用task_get_special_port() ,我們可以獲得內核任務埠。請注意,內核任務埠是非常強大的。它可以通過mach_vm_read()和mach_vm_write()進行任意內核內存讀寫。
0x04 root提權
每個進程的憑據信息,posix_cred結構,存儲在內核內存中。首先我們需要找到我們的進程信息(通過內核基址+nallproc),然後找到我們的利用程序的posix_cred結構數據。 之後,我們通過kernel_task_port使用mach_vm_write() ,將cr_ruid(實際用戶ID)值設置為0(也就是root)。最後,而且非常重要的是,我們可以使用system(「/ bin /nbash」)獲取rootnshell!
0x05 總結
在本文中,我們介紹了如何使用mach_voucher堆溢出和port堆風水來實現macOSn10.12.2上的本地提權。漏洞源碼可以從下面的網址下載:
nnzhengmin1989/macOS-10.12.2-Exp-via-mach_vouchernn0x06 參考
- Yalu 102: kpwn/yalu102
n 1004 - iOS/MacOS kernel memory corruption due to userspace pointer being used as a length - project-zero - Monorailn
n 1004 - iOS/MacOS kernel memory corruption due to userspace pointer being used as a length - project-zero - Monorailn
推薦閱讀:
※新浪微博客戶端的 iOS 推送為何會比安卓慢?
※想買手機,ios還是安卓?為什麼?
※為什麼iPhone的硬體比安卓的差,卻依然流暢過安卓?
※iPhone 有哪些好用的通知中心插件?
※人民網點評蘋果「降頻門」該給消費者一個說法!
TAG:iOS |