Fugu 15 的发布,让 iPhone 的安全研究人员觉得,iOS 始终都不是不可攻破的。
然而,随着 Linus Henze 被 Apple 招安,iOS 16 再无越狱的动静。
与 iOS 15 不同的是,在 iOS 16 的发行周期内,甚至连已知可利用的内核漏洞都寥寥无几。
这不禁令人感慨,是否再也没有能够攻破 iOS 整条防线的机会?
2023 年 7 月,kfd 的发布,给黑客带来了一丝曙光。
以下为本期深蓝洞察年度安全报告的第三篇。
03
内核漏洞,一直是 iOS 完整攻击链不可或缺的一环。
只有实现了内核的读写原语,绕过重重防护机制,获取了系统的最高权限,才能算是一条攻击链或越狱的成功。
去年的《深蓝洞察 | 2022 年度最迟来的漏洞利用》曾写道:
在 iOS 15 发行周期内,尽管有多个实现内核任意读写能力的 PoC 发布,却一直没有针对最新 iPhone 型号的公开越狱工具出现。
然而谁都预想不到,今年的情况变得更加“恶劣”:
自从 2022 年年底 Ian Beer 公开 MacDirtyCow 漏洞以后,iOS 在相当长一段时间内再也没有任何公开的内核利用出现。
这一切表明,在重兵封堵内核各种安全隐患后,iOS 内核的安全性再一次得到了提升。
不过 2023 年 7 月,悄无声息地,felix-pb (@_p0up0u_) 发布了 kfd,掀起了一场轩然大波。
kfd 是 Kernel File Descriptor 的缩写,这意味着其在 iOS 内核上实现了一套强大的漏洞利用原语,能够实现任意内核地址读写。
在 kfd 中,felix-pb 使用了 Physical Use After Free (PUAF) 的利用手法。
要知道,自从 Apple 在 iOS 15 上引入 kalloc_type 机制之后,在内核中已经几乎不可能利用 UAF 漏洞了。而 PUAF 无疑是另辟蹊径,与传统的 UAF 不同,PUAF 涉及到指向内存区域物理地址的悬挂指针,而非虚拟地址。
通过巧妙触发漏洞,PUAF 能够获取 dangling PTE,然后,借助在物理页面中重新分配特定的内核对象,可以通过 PTE 直接从用户空间操作它们,从而实现了 KRKW 原语。
值得注意的是,PUAF 直接在物理内存上进行操作,而 kalloc_type 只能限制虚拟内存空间中类型对象的分配隔离。
因此,PUAF 可以绕过 kalloc_type 的限制,实现任意内核地址的读写。
令人惊讶的是,kfd 前后共公布了三个漏洞,它们的成因不同,但各自都有着触发 PUAF 的强大能力,分别是:puaf_physpuppet
, puaf_smith
和 puaf_landa
。
这些漏洞横跨 iOS 16 的各个版本,puaf_landa
更是直到 iOS 17 才被报告和修复,赢得了 $70,000 的赏金。
下面,我们简单概括一下这三个漏洞的成因:
1. puaf_physpuppet
-
漏洞类型:整数溢出
-
触发方式: vm_map(mach_task_self(), &address, (-1), 0, …)
-
漏洞成因:
vm_map_enter_mem_object_helper
中没有检查 size,会将 size 向上取整为 0
/*
* Note:
* - both "map_size" and "size" have been set to 0 because of an integer overflow.
*/
map_addr = vm_map_trunc_page(*address, VM_MAP_PAGE_MASK(target_map)); // map_addr := 0
map_size = vm_map_round_page(initial_size, VM_MAP_PAGE_MASK(target_map)); // map_size := 0
size = vm_object_round_page(initial_size); // size := 0
-
漏洞类型:整数溢出 -
触发方式: vm_copy(mach_task_self(), address, (0ull – address – 1), 0) -
漏洞成因: vm_map_copyin_internal
中没有 size,计算 src_end = src_addr + size = -1,向上取整为 0
src_end = src_addr + len; // src_end := (0ULL-1)
/*
* (0)
* @note:
* This trigger the integer overflow that can be considered the "root cause" vulnerability.
*/
src_start = vm_map_trunc_page(src_addr, VM_MAP_PAGE_MASK(src_map)); // src_start := C
src_end = vm_map_round_page(src_end, VM_MAP_PAGE_MASK(src_map)); // src_end := 0
3. puaf_landa
-
漏洞类型:条件竞争
-
触发方式: vm_copy 的同时调用 mblock
-
漏洞成因:在
vm_map_copy_overwrite_aligned
的 slow path 中,调用vm_fault_copy
之前释放掉了 dst_map 的锁,存在竞争窗口。
vm_map_unlock(dst_map); // map lock is dropped here
r = vm_fault_copy(
VME_OBJECT(copy_entry),
VME_OFFSET(copy_entry),
©_size,
dst_object,
dst_offset,
dst_map,
&version,
THREAD_UNINT);
// ...
vm_map_lock(dst_map); // map lock taken back here
然而,这一场战争还未结束,即使有了强大的 kfd 内核读写原语,也只是攻击链的一环而已。
直到 kfd 公开的半年之后,iOS 16 仍然没有任何公开的越狱工具,因为还有 PPL 的存在,这也是 iOS 漫长的安全防线中的最后一环。
不过,随着 23 年底 Kaspersky 对 Operation Triangulation 三角测量行动的披露,其中基于硬件 MMIO 绕过 PPL 的攻击补全了这最后一环,相信 iOS 16 的越狱工具发布也只是时间问题。
不出所料,在2月17日上午,opa334(@opa334dev)发布了 iOS 16 的完整越狱 Dopamine 2.0。
有趣的是,DARKNAVY 发现三角测量行动利用的内核漏洞和 kfd 的 puaf_smith
有着相同的 CVE 编号 —— CVE-2023-32434。
然而,通过对这两个漏洞进行分析,我们发现这两个漏洞的成因截然不同:三角测量行动利用的是 mach_make_memory_entry
中的整数溢出,而 puaf_smith
则是 vm_copy
中的整数溢出。
鉴于该 CVE 是由 Kaspersky 报告提交的,我们推测该 CVE 真实代表的漏洞为前者。而 puaf_smith
则是 felix-pb 在分析内核代码补丁时偶然发现的另一个漏洞。
felix-pb 也在项目中提到,该 CVE 号的修复涉及了多个整数溢出的改动。因此,出现了让人啼笑皆非的一幕:表面上同样的 CVE 号,背后却代表了完全不同的漏洞。
回顾 kfd 的三大漏洞,不难发现,它们都出自 iOS 的 Mach VM,作为 iOS 内核中的内存管理模块,这无疑是内核中最复杂的部分。
随着 iOS 防护机制的不断加入,诸如 Mach Port、IOKit 等模块的攻击面所剩无几,不禁让我们联想:
-
Mach VM 是否会成为 iOS 的下一个 Mach Port?
-
其复杂的实现逻辑下,是否还隐藏着更多危险的“珍宝”?
重重的新防御机制,对于漏洞利用来说,究竟是起始符,抑或是终结符,可能只有时间才能给出答案。
黑客的突破一直都在发生和持续,
毋庸置疑的是:
攻与防永远在悄无声息地博弈;
攻防对抗将持续不断地螺旋上升;
UAF 被堵死后会出现更强大的 PUAF;
旧的攻击面被修复后终究会有新的攻击面出现。
这,
就是安全研究的意义所在。
明日,请继续关注《深蓝洞察 | 2023 年度安全报告》第四篇。
原文始发于微信公众号(DARKNAVY):「深蓝洞察」2023 年度最多面的漏洞