bohmiiidd/libimobiledevice-0DayVulnSuite

GitHub: bohmiiidd/libimobiledevice-0DayVulnSuite

针对 libimobiledevice 的 13 个漏洞概念验证集合,提供可复现的触发器用于补丁验证和 CVE 查阅。

Stars: 0 | Forks: 0

# libimobiledevice — PoC 集合(13 个发现) 这是针对 `finds.md` 中记录的宿主机端 `libimobiledevice` 错误的概念验证触发器, 每一个都包含了说明、根本原因、触发方式和影响 评估。 **范围 / 威胁模型。** 对端扮演*设备*(AFC daemon / service daemon)或 usbmux/TCP 通道上的 MitM。受害方是任何 链接了 `libimobiledevice` 并调用其公开 API(`idevice*` 工具、`ifuse`、GUI 应用)的宿主机进程。这**不是**互联网 RCE;它是一个“与你配对的恶意对端”模型。这里没有任何对第三方 的攻击 —— 它是用于修补/CVE 查阅的实验环境环回测试套件。 **验证基准**:基于 `1.4.0-9-gfa0f791` 检出版本(对于此处引用的每一行,它与当前上游的 `master` 版本完全一致 —— `src/afc.c` 已与 GitHub 上的版本进行过 diff 比对)。 ## 布局 | 文件 | 目的 | |------|---------| | `victim.c` | 用于 AFC 错误的宿主机客户端。仅使用公开的 AFC API;环回 TCP 垫片 | | `peer.py` | 恶意 AFC daemon 模拟器,每个 AFC 错误对应一种模式 | | `services_victim.c` | 用于 PLS/Ostrace/DBG/WI/RP 的宿主机客户端(公开 API + RSS 监视器) | | `services_peer.py` | 恶意服务 daemon 模拟器(pls, ostrace, dbg, wi, rp) | | `build.sh` | 编译两个测试客户端(`LIBROOT` = libimobiledevice 安装前缀) | | `run.sh` | 运行一个错误(索引 1..13):启动对端,运行受害端,打印特征 | | `README.md` | 本文件 | ## 快速开始(Linux / WSL) ``` # 1. 构建 library,然后构建 victims ./poc/build.sh # 2. heap overflow (finds.md Bug #2) ./poc/run.sh 2 # 3. 未配对的 key -> strdup(NULL) (Bug #5) ./poc/run.sh 5 # 4. 错误路径 double-free (AFC-4) ./poc/run.sh 6 # 5. reverse-proxy Connect hostlen 被忽略 (RP-1) ./poc/run.sh 10 # 6. 短 FILE_OPEN_RES handle 泄漏 (Bug #12) ./poc/run.sh 13 ``` ## 漏洞索引(与 `finds.md` 匹配) | # | ID | 组件 | 根本原因(单行概述) | 影响 | 运行 | |---|-----|-----------|----------------------|--------|-----| | 1 | Bug #1 | `afc.c` | `make_strings_list` 无界 `strdup`/`strlen` 遍历 | OOB **读取** / 泄漏(放大器) | `run.sh 1`(链式) | | 2 | Bug #2 / AFC-5 | `afc.c` | 分配 `entire_len`,接收 `this_len`;u64→u32 截断 | 堆**写入**溢出 | `run.sh 2` | | 3 | Bug #3 | `afc.c` | `service_receive` 前未检查 `malloc` | DoS(大部分被拦截) | `run.sh 3`(对照组) | | 4 | Bug #4 | `afc.c` | `make_strings_list` 中未检查 `malloc`/`strdup` | DoS / NULL 解引用 | `run.sh 4` | | 5 | Bug #5 / AFC-6 | `afc.c` | 不成对的键 → `strdup(*(ptr+1))` 且为 NULL | SEGV / 崩溃 | `run.sh 5` | | 6 | AFC-4 | `afc.c` | 出错时 `free(buf)` **但未 `return`** | Double-free / UAF | `run.sh 6` | | 7 | AFC-5 | `afc.c` | u64→u32 对 `entire`/`this` 长度的截断 | 堆溢出(截断项) | `run.sh 7` | | 8 | PLS-1 | `property_list_service.c` | 对端的 `pktlen` → `malloc(pktlen)` 无上限 | 内存 DoS | `run.sh 8` / `plsb` | | 9 | Ostrace | `ostrace.c` | 对端的 `rlen` → `malloc(rlen)` 无上限 | 内存 DoS | `run.sh 9` / `ostraceb` | | 10 | RP-1 | `reverse_proxy.c` | `hostlen` (buf[2]) 被忽略;`strdup(&buf[3])` | 错误的主机解析 / 设备驱动的连接 | `run.sh 10` | | 11 | DBG-1 | `debugserver.c` | 响应循环不断 realloc 直到收到 `#`;但永不出现 | 内存增长 DoS / 泄漏 | `run.sh 11` | | 12 | WI | `webinspector.c` | `realloc` 未检查 → 泄漏 + NULL `memcpy` | 泄漏 / NULL 解引用崩溃 | `run.sh 12` / `wif` | | 13 | Bug #12 | `afc.c` | `memcpy(handle, data, 8)` 仅由 `bytes > 0` 保护 | 堆**信息泄漏**(旧 chunk) | `run.sh 13` | 额外演示:`plsb`(PLS-1 有界 RSS 飙升),`ostraceb`(Ostrace 大 rlen 分配探测 —— RSS 保持平稳,参见 Ostrace 的注意事项),`wif`(WI 无界 realloc 增长)。 ## AFC 家族(`poc/peer.py` + `poc/victim.c`) 共享接收管道:公开 API(`afc_read_directory`, `afc_get_device_info`, …) → `afc_receive_data()` → `make_strings_list()` / `make_dictionary()` / `afc_get_device_info_key()`。 对端控制的标头(`src/afc.h`):`magic[8] "CFA6LPAA"`, `entire_length`, `this_length`, `packet_num`, `operation` —— 均为 u64。 ### Bug #2 / AFC-5 — 堆溢出:`this_len > entire_len` **位置:** `src/afc.c:308-314` ``` entire_len = (uint32_t)header.entire_length - sizeof(AFCPacket); // allocation size this_len = (uint32_t)header.this_length - sizeof(AFCPacket); // recv size buf = (char*)malloc(entire_len); if (this_len > 0) { err = ...service_receive(client->parent, buf, this_len, &recv_len); } ``` **根本原因。** 仅 `header.this_length < sizeof(AFCPacket)` 会被拒绝 (第 293 行)。没有 `this_len <= entire_len` 检查,没有 `entire_length >= sizeof(AFCPacket)` 检查,并且 u64 字段被静默 窄化转换为 `uint32_t`。`service_receive` (`src/service.c:177`) → `idevice_connection_receive_timeout` (`src/idevice.c:749`) 执行单次 最多 `size` 字节的 `recv`,因此对端使得宿主机**将 `this_len` 字节写入 `entire_len` 字节的缓冲区**。 **触发(对端):** 对于任何列表操作(`READ_DIR`/`GET_DEVINFO`/`GET_FILE_INFO`) 回复 `operation = DATA`, `entire_length = 40 + 0x18`, `this_length = 40 + 0x200` → 宿主机执行 `malloc(24)` 然后 `service_receive(buf, 512)`,接着 `make_strings_list(data, 512)` 从 24 字节的 chunk 中 越界读取 512 字节(Bug #1 链式反应)。 **影响。** 在任何使用 AFC API 的进程中发生堆**写入溢出** → glibc abort (`malloc(): corrupted top size`, exit 134) 或 SEGV (139);通过堆排布,这可以成为 代码执行原语。该溢出还将 `*bytes_recv` 输入到 `make_strings_list` 中,从而引发 Bug #1 的 OOB 读取。 **预期输出:** `victim exit=134` / `malloc(): corrupted top size`, 或 `exit=139`。 ### Bug #1 — `make_strings_list` 无界 `strdup`(放大器) **位置:** `src/afc.c:434-451` ``` nulls = count_nullspaces(tokens, length); // bounded by length (OK) list = malloc(sizeof(char*) * (nulls + 1)); for (i = 0; i < nulls; i++) { list[i] = strdup(tokens + j); // walks to '\0', ignores length j += strlen(list[i]) + 1; } ``` **根本原因。** `count_nullspaces` 是有界的,但 token 拷贝是无界的。 `strdup`/`strlen` 仅在遇到 NUL 字节时停止。 **诚实声明(已验证)。** 在传入真实的 `length` 下独立运行,它**不会** 发生 OOB 读取:每个 `strdup` 都会在缓冲区内已被 `count_nullspaces` 计数的 NUL 处终止。只有当 `length` 是一个谎言时 —— 比如接在 Bug #2 之后,或在其他堆破坏之后 —— 它才会变成真正的 OOB **读取**。这依然是一个设计缺陷(对比位于 `src/afc.c:453-495` 使用了 `strnlen` 的安全版本 `make_dictionary`),这也是为什么 Bug #2 会引发干净的崩溃,并可能将相邻堆内存的信息泄漏到返回的字符串中。 **影响。** OOB 读取 / 堆信息泄漏;Bug #2 的放大器。无独立运行 模式;`./poc/run.sh 1` 将运行 Bug #2 链式反应。 ### Bug #3 — `afc_receive_data` 中未检查 `malloc`(对照组) **位置:** `src/afc.c:311-314` **发现(已更正)。** 缺失的 `if (!buf)` 检查确实存在,但 文档中记录的“接收路径中的 NULL 写入”影响对于此 代码库是**错误**的:`service_receive_with_timeout` 拒绝 NULL 目标 (`src/service.c:161` → `SERVICE_E_INVALID_ARG`) 并且 `recv_len` 保持为 0,因此 `recv_len <= 0` 分支 (`src/afc.c:319`) 会进行清理(`free(NULL)`)并返回 错误。强制巨大的 `entire_len`(下溢)会导致 `malloc` 失败并退化为 优雅的 API 错误。 **影响。** 无可见影响。作为对照组保留: `./poc/run.sh 3` 应显示受害端*没有*崩溃(仅 API 错误)。 ### Bug #4 — `make_strings_list` 中未检查 malloc/strdup (DoS) **位置:** `src/afc.c:443-446` ``` list = (char**)malloc(sizeof(char*) * (nulls + 1)); // unchecked for (i = 0; i < nulls; i++) { list[i] = strdup(tokens + j); // unchecked j += strlen(list[i]) + 1; // strlen(NULL) if strdup failed } ``` **根本原因。** NUL 填充的正文使得 `nulls` 等于正文大小 → 列表 分配空间为 `8 * nulls`(64 位下)。`malloc`(→ 对 NULL 执行 `list[i]`) 或 `strdup`(→ `strlen(NULL)`)失败会使宿主机崩溃。两种失败模式都 依赖于 OOM 的发生。 **触发(对端):** 回复 `DATA`,带有全 NUL 的大正文(`--nulflood`, 默认 `0x10000000` → 64 位下 2 GB 的列表分配)。 **影响。** 内存压力下的拒绝服务。与 `practical-test/REPORT_TRIGGERS.md` 的记录一致,该记录在内存充足的主机上将其记录为“存活”。 ### Bug #5 / AFC-6 — 不成对的键 → `strdup(NULL)` **位置:** `src/afc.c:640-645` ``` for (ptr = kvps; *ptr; ptr++) { if (!strcmp(*ptr, key)) { *value = strdup(*(ptr+1)); // no check that a value follows break; } } ``` **根本原因。** 设备信息是一个以 NUL 分隔的扁平键/值列表,被转换为 一个带有 NULL 哨兵的 `char**`。**奇数**列表(单独的键)会使得匹配键的 `ptr+1` 指向 NULL 哨兵 → `strdup(NULL)` → `strlen(NULL)` → SIGSEGV。 **触发(对端):** 回复 `GET_DEVINFO`,正文仅为 `ModelNumber\0`; 受害端调用 `afc_get_device_info_key(client, "ModelNumber", &value)`。 **影响。** 可靠的 NULL 解引用 / 崩溃 (DoS)。在发生之前的 Bug #2 堆 破坏的情况下,该哨兵可能会受到攻击者的影响 → 通过 `strdup` 实现任意读取。 **预期输出:** `victim exit=139` (SIGSEGV)。 ### AFC-4 — 接收错误路径上的 double-free **位置:** `src/afc.c:314-328` ``` err = ...service_receive(client->parent, buf, this_len, &recv_len); if (err != AFC_E_SUCCESS) { free(buf); // 1st free debug_info(...); } if (recv_len <= 0) { // recv_len was NEVER updated on error free(buf); // 2nd free -> double free ... } ``` **根本原因。** 在 `service_receive` 失败时,代码释放了 `buf`,但**没有** `return`。 `service_receive_with_timeout` 出错时将 `recv_len` 留在 0 (它仅在成功时写入 `*received`),因此 `recv_len <= 0` 分支 被执行并再次释放。 **触发(对端):** 发送一个有效的 `OP_DATA` 回复标头,然后重置 连接(`SO_LINGER=0`)而不是发送正文。正文 `recv` 失败并返回 `ECONNRESET`,`recv_len` 保持为 0 → 重复释放。 **影响。** 宿主机进程中的 double-free / UAF → glibc abort (`free(): double free detected in tcache 2`, exit 134在 ASAN 下会发生可靠的 崩溃。 **预期输出:** `victim exit=134` 且带有 `free(): double free detected`。 ### AFC-5 — u64→u32 截断溢出 **位置:** `src/afc.c:308-309`(与 Bug #2 同行,不同入口) **根本原因。** 64 位标头字段在使用前被强制转换为 `uint32_t`。 对端设置超过 4 GiB 的长度在 u64 下本应是无害的,但发生了静默回绕: `entire_length = 0x1_0000_0030 → (u32) 0x30`, `this_length = 0x1_0000_0100 → (u32) 0x100`。宿主机随后执行 `malloc(8)` 和 `recv(216)` —— 这是一种 *纯粹通过截断*引发的溢出。 **触发(对端):** 回复 `DATA`,带有 `entire_length = 0x1_0000_0030`, `this_length = 0x1_0000_0100`,216 字节正文;受害端运行 `afc_read_directory`。 **影响。** 同属 Bug #2 类别:堆元数据破坏 / 崩溃。它是 共享的“AFC 接收长度验证”问题的 AFC-5 变体。 **预期输出:** `victim exit=134/139`(损坏的 top size / SEGV)。 ### Bug #12 — 从短缓冲区进行的 8 字节 `memcpy`(handle 泄漏) **位置:** `src/afc.c:868-872` (`afc_file_open`) 和 `src/afc.c:1099-1103` (`afc_file_tell`) ``` if ((ret == AFC_E_SUCCESS) && (bytes > 0) && data) { memcpy(handle, data, sizeof(uint64_t)); // only checks bytes > 0 ``` **根本原因。** `bytes`(对端可控的 `current_count`)的检查条件为 `> 0`, 而不是 `>= sizeof(uint64_t)`。1-7 字节的响应会使得 `memcpy` 从 只接收了 `bytes` 字节的缓冲区中读取 8 字节。 **实际泄漏的内容(已验证)。** 在 64 位 glibc 下,`malloc(1)` 具有 24 字节的 可用区域,因此 8 字节的读取仍停留在 chunk 内部,并复制了接收数据之后的**陈旧堆内容** —— 通常是当该 chunk 位于空闲链表上时的陈旧 tcache `next` 的低位字节。这不是活动标头,也不是 `main_arena`。在 ASAN 或其他分配器下,这是真正的 OOB 读取。 泄漏是可以观察到的,因为被污染的 handle 会被 `afc_file_read` (`readinfo->handle`, `src/afc.c:906`) 回显。注意 `handle == 0` 会被拒绝 (`src/afc.c:896`),因此对端必须至少返回 1 个非零字节。 **触发(对端):** 回复 `FILE_OPEN`,`FILE_OPEN_RES` 为 1-7 字节; 受害端运行 `afc_file_open → afc_file_read → afc_file_close`。对端打印 `RECV handle=0x…` 和 `OOB_bytes_in_handle=…`。 **影响。** 堆**信息泄漏**(陈旧 chunk / 先前的空闲链表字节)被反射 回对端 —— 有助于在后续的 Bug #2 漏洞利用中绕过 ASLR;但 其本身不会导致崩溃。 ## 服务家族(`poc/services_peer.py` + `poc/services_victim.c`) 独立的服务,相同的威胁模型(对端通过同一通道控制帧结构)。 ### PLS-1 — 无上限的 plist 包长度 **位置:** `src/property_list_service.c:210-216` ``` pktlen = be32toh(pktlen); content = (char*)malloc(pktlen); if (!content) { ... return PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR; } ``` **根本原因。** 对端的 4 字节大端序 `pktlen` 被直接用作 `malloc` 大小,**没有上限**。检查了 `malloc`,因此这是内存 耗尽,而不是溢出。可从 lockdown、restore、instproxy 和 所有由 plist 封装的服务访问(`property_list_service_receive_plist_with_timeout`, `include/libimobiledevice/property_list_service.h:119`)。 **触发(对端):** 发送 `pktlen = 0xFFFFFFFF` 然后 RST (`run.sh 8`, malloc 探测),或者发送 `pktlen = --size` 并流传 数据负载(`run.sh plsb`,接收时 RSS 飙升 + 占用已分配的内存)。 **影响。** 宿主机内存耗尽 / DoS。在启用了 overcommit 的内核上,4 GiB 的 分配会成功,并且客户端在阻塞时会一直持有它;`plsb` 直接 展示了 RSS 的增长(受害端会打印 `peak_rss`)。 ### Ostrace — 无上限的 `rlen` → `malloc(rlen)` **位置:** `src/ostrace.c:157-168`(以及位于约 243 行的工作循环) ``` if (msgtype == 1) rlen = be32toh(rlen); else if (msgtype == 2) rlen = le32toh(rlen); char* buf = (char*)malloc(rlen); // uncapped res = ostrace_error(service_receive(client->parent, buf, rlen, &received)); ``` **根本原因。** 对端可控的 `rlen`(msgtype 1 为大端序,2 为小端序)被 直接用作分配大小;没有上限,且 `malloc` 未被检查(NULL 稍后会被 `service_receive` 拒绝)。公开可达路径:`ostrace_get_pid_list` → `ostrace_receive_plist`。 **触发(对端):** 读取 `PidList` 请求,然后回复 `msgtype=1`, `rlen = 0xFFFFFFFF` + RST (`run.sh 9`), 或者 `rlen = --size` 并流传 (`run.sh ostraceb`, 分配探测)。 **影响。** 内存 DoS,与 PLS-1 同类。诚实声明(已验证):不同于 property_list_service(它会循环直到收到 `pktlen` 字节并使 缓冲区驻留),`ostrace_receive_plist` 执行**单次** `recv(rlen)` (`src/ostrace.c:168`),因此巨大的 `rlen` 仅会产生瞬时的虚拟 分配 —— 驻留 RSS 保持平稳(没有 plsb 那样的飙升)。此 DoS 指的是 无上限的分配本身(在 overcommit 下巨大的 `malloc`;否则为 NULL + 优雅的 `SERVICE_E_INVALID_ARG`)。 ### RP-1 — reverse-proxy Connect 主机解析 **位置:** `src/reverse_proxy.c:160-182` ``` if (bytes < 3) { ... return 0; } if (buf[0] == 0 && buf[1] == 3) { uint16_t *p = (uint16_t *)&buf[bytes - 2]; port = be16toh(*p); buf[bytes - 2] = '\0'; host = strdup(&buf[3]); // hostlen (buf[2]) is NEVER validated } ... int sockfd = socket_connect(host, port); // device-driven TCP connect ``` **根本原因。** Connect 二进制布局为 `0 3 `。 仅要求 `bytes >= 3`;`buf[2]` (hostlen) 被**忽略**,因此 `host` 是 索引 3 和强制 NUL 之间的所有字节 —— 不受限的内容 成为了传递给 `socket_connect` 的主机名。畸形/乱码的长度 → 奇怪的主机解析 → 宿主机打开一个到攻击者选择的主机:端口的 TCP 连接 (从恶意对端的角度看类似于 SSRF)。 **触发(对端):** 完成 v2 握手(Ctrl `BeginCtrl` ↔ `ConnPort`, 然后 Conn `HelloConn` ↔ `{Command: HelloConn}`),发送 `cmd=0x105`,接着发送带有 `hostlen=3` 但具有 9 字节主机 `"127.0.0.1"` 以及连接端口的 Connect 负载。宿主机记录 `Connect request to 127.0.0.1:` 并连接 回对端(对端打印 `conn2: host connected back`)。 **影响。** 宿主机向攻击者选择的端点发起由设备驱动的 出站 TCP 连接;被错误解析的主机字节最终进入 DNS/connect 调用。 属于逻辑缺陷,而不是内存破坏(`strdup` 受到 1 MiB 缓冲区内注入的 NUL 限制)。 ### DBG-1 — 无限响应增长 **位置:** `src/debugserver.c:450-471` ``` while ((checksum_length > 0)) { res = debugserver_client_receive_internal_char(client, &data); // 1 byte if (data == '#') receiving_checksum_response = 1; if (buffer_size + 1 >= buffer_capacity) { char* newbuffer = realloc(buffer, buffer_capacity+1024); if (!newbuffer) { return DEBUGSERVER_E_UNKNOWN_ERROR; } // leak: buffer not freed buffer = newbuffer; buffer_capacity += 1024; } buffer[buffer_size] = data; buffer_size += sizeof(char); } ``` **根本原因。** 校验和循环不断增长 `buffer`,直到 `#` + 2 个校验和 字符到达。从不发送 `#` 的对端会强制不受限制的 `realloc(+1024)` 增长; 在 `realloc` 失败时,函数返回而未释放 `buffer`(泄漏)。 公开入口:`debugserver_client_receive_response` (`include/libimobiledevice/debugserver.h:167`)。 **触发(对端):** 发送 ACK `+`, 前缀 `$`,然后大量泛洪数据字节**且没有 `#`** (`run.sh 11`)。受害端的逐字符接收循环不断重新分配;RSS 持续增长,直到对端停止 / 进程退出。 **影响。** 内存增长型 DoS;错误路径泄漏。ASAN 复现记录在 realloc 路径中报出 `allocation-size-too-big`。 ### WI — 未检查的 `realloc` + `memcpy` **位置:** `src/webinspector.c:221-230` ``` if (!packet) { packet = (char*)malloc(length * sizeof(char)); } else { newpacket = (char*)realloc(packet, (packet_length + length) * sizeof(char)); packet = newpacket; // NULL not checked } memcpy(packet + packet_length, buffer, length); // NULL -> SIGSEGV ``` **根本原因。** 通过 `realloc` 重新组装部分消息;其结果被 赋值给 `packet` 时未检查 NULL。在分配失败时,旧 指针丢失(泄漏)并且 `memcpy` 解引用了 NULL(崩溃)。公开入口: `webinspector_receive_with_timeout` (`include/libimobiledevice/webinspector.h:131`)。 **触发(对端):** - 正常路径 (`run.sh 12`):一个 `WIRPartialMessageKey` 数据块 + 一个 包含有效二进制 plist 的 `WIRFinalMessageKey` 数据块 → 客户端重新组装并 打印 plist(测试一次 realloc 路径)。 - 增长演示 (`run.sh wif`):大量部分数据块,没有终结块 → `packet` 无限 增长(内存 DoS;触发崩溃需要强制 `realloc` 失败,例如在 ASAN 的大小限制下)。 **影响。** OOM 下的堆泄漏;当 `realloc` 失败时发生可靠的 NULL-`memcpy` 崩溃;伴随无休止的部分流造成无限制的内存增长。 ## 运行矩阵 | run.sh | 对端模式 | 受害端模式 | 预期宿主机行为 | |--------|-----------|-------------|-------------------------| | `1` | bug2 | dir | 崩溃(通过 Bug #2 链触发 Bug #1) | | `2` | bug2 | dir | 崩溃:`corrupted top size` / SEGV | | `3` | bug3 | dir | 优雅的 API 错误(对照组) | | `4` | bug4 | dir | 依赖 OOM(可能会存活) | | `5` | bug5 | key | SIGSEGV (exit 139) | | `6` | afc4 | dfree | abort: `free(): double free detected` | | `7` | afc5 | trunc | 崩溃:`corrupted top size` / SEGV | | `8` | pls | pls | `UNKNOWN_ERROR` / 超时(无界 pktlen 探测) | | `plsb` | plsb | pls | `peak_rss` 增长至 pktlen 大小(接收时保持缓冲区) | | `9` | ostrace | ostrace | `UNKNOWN_ERROR` / 超时(无界 rlen 探测) | | `ostraceb` | ostraceb | ostrace | 仅分配探测;RSS 保持平稳(单次 recv 设计) | | `10` | rp | rp | `rp log: Connect request to 127.0.0.1:` + 连接回传 | | `11` | dbg | dbg | RSS 增长;接收永不完成 | | `12` | wi | wi | `got plist: …` (已重组) | | `wif` | wif | wi | RSS 增长;接收超时 | | `13` | leak | open-read | 对端:`RECV handle=0x…` + `OOB_bytes_in_handle=…` | 针对运行较慢的机器,可以调高 `TIMEOUT`(默认为 25 秒): `TIMEOUT=60 ./poc/run.sh plsb`。 ## 给维护者报告的备注 - 所有引用的代码在当前上游的 `master` 中均未更改 —— 这些不是 此检出版本的伪影。 - 修复方向: 1. `afc_receive_data`:要求 `sizeof(AFCPacket) <= this_length <= entire_length`,在 `uint32_t` 强制转换前以 64 位验证所有大小, 限制最大数据包,检查 `malloc`,并且接收量永远不要超过分配量。 2. `afc_receive_data` 错误路径:在 `free(buf)` 之后立即 `return err`(并 设置 `buf = NULL`)。 3. `make_strings_list`:使用 `strnlen`/有界遍历进行解析,如 `make_dictionary` 那样;检查 `malloc``strdup`。 4. `afc_get_device_info_key`:要求 `*(ptr+1) != NULL` / 偶数列表长度。 5. `afc_file_open`/`afc_file_tell`:要求 `bytes >= sizeof(uint64_t)`。 6. `property_list_service` / `ostrace`:在 `malloc` 前限制 `pktlen` / `rlen`。 7. `reverse_proxy`:验证 `buf[2]` (hostlen) —— 要求 `bytes >= 3 + hostlen + 2`;使用带有 `hostlen` 的 `strndup`。 8. `debugserver`:限制最大响应大小;在 realloc 失败时释放 `buffer`; 如果 `#` 永不出现则触发超时。 9. `webinspector`:检查 `realloc`/`malloc`;失败时释放 + 返回;限制总 `packet_length`。 - 为每个服务添加响应模糊测试器(变异的长度、奇数 K/V 列表、短 handle 响应、无休止的部分流);ASAN 能够立即捕获 #2/#1/#5/AFC-4/#12。
标签:Cutter, libimobiledevice, Maven, PoC, XXE攻击, 云资产清单, 暴力破解, 漏洞分析, 漏洞验证, 路径探测, 逆向工具, 逆向工程