abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · qemu-colo-l4-oob
QEMU v11.1.2(4fc49f46dc95d4a27de2509e7fceb2931e91faeb)- COLO filter-rewriter
类别: OOB(堆缓冲区溢出 READ/WRITE)。可达性: 本地(guest)/ 远程(COLO 对端)。
parse_packet_early 只要 L2 加上 ip_hl*4 能放下就接受 IPv4。它从不要求最小 L4 头部。随后 fill_connection_key 在 transport_header 处读取四个字节,且没有剩余长度检查。filter-rewriter 用 g_malloc0(size) 复制该帧,并且在 SYN 已将连接迁移到 TCPS_SYN_RECEIVED 之后,当捕获长度止于传输层头部时,一个 conn->offset != 0 的 ACK 会把 th_ack / th_seq 写到该内存块之外。
COLO 并非默认启用。当配置了 -object filter-rewriter(以及 colo-compare)时它才开启。该 rewriter 上的 guest TX/RX 属于虚拟化安全模型。primary_in / secondary_in 上的 COLO 对端是一种网络协议,同样不可信。
一个 34 字节的 IPv4/TCP 帧就足以在 filter-rewriter 中触发 ASan 堆缓冲区溢出 READ。
| ID | 暂无 CVE |
| CWE | CWE-125 / CWE-787 |
| CVSS | 高危:8.2 CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H |
| 产品 | QEMU |
| 受影响版本 | v11.1.2(4fc49f46),启用 COLO rewriter/compare |
| 认证 | COLO rewriter netdev 上的 guest,或 COLO compare 对端 |
| 许可证 | GNU Affero GPL v3.0 |
| 实验环境 | 127.0.0.1:18770 / 18771 回环套接字 |
谁:启用 COLO 的 NIC 上的不可信 guest,或恶意的 COLO compare 对端。guest 到宿主 / 对端到宿主。QEMU 用户态堆。
| 方法 | 汇聚点 | 权限 |
|---|---|---|
| 完整头部 SYN 之后的短 IPv4/TCP ACK(34 字节帧,长度止于传输层头部) | filter-rewriter handle_primary_tcp_pkt / fill_connection_key | filter-rewriter 中的 ASan 堆缓冲区溢出 READ。控制完整头部 TCP 后 QEMU 仍存活。 |
| 同样的 L4 下限缺失 | parse_packet_early net/colo.c:43-98 | 数据包在缓冲区中没有 L4 头部的情况下被归类为 TCP。 |
SYN 之后,conn->offset != 0,rewriter 在 net/filter-rewriter.c:112-114 和 :216-218 处存储 th_ack / th_seq。IP 选项(ip_hl > 5)会把该写入偏移到下一个堆内存块上。可由 guest 触发的宿主堆 WRITE。
colo-compare 的 fill_pkt_tcp_info 根据 th_off<<2 设置 header_size,且没有对照 pkt->size 进行检查。payload_size 发生下溢。colo_compare_packet_payload 对两个数据包分配之外数十 KB 的内存执行 memcmp。导致崩溃以及宿主堆 READ。
在 ASan 下,rewriter 的 READ 会导致 QEMU 中止。没有 ASan 时,这是 hypervisor 进程中的实时堆 OOB。
net_fill_rstate 会拒绝 packet_len > NET_BUFSIZE)。该实验未演示 RIP 控制或 guest 到宿主的 shell。该类别是启用 COLO 的 netdev 上 QEMU 进程的堆 OOB。
我阅读了 net/colo.c,寻找包含 L4 的长度下限。该下限是 Ethernet 加上 VLAN 再加上 vnet_hdr。ip_hl 取自一个短尾部。随后 fill_connection_key 信任 transport_header。filter-rewriter 始终在 struct tcp_hdr 的偏移 13 处加载 th_flags。
错误方向:将 TAP 长度视为 COLO 边界(不同路径);将溢出作为第一个数据包发送(rewriter 需要先有 SYN,这样 conn->offset 才是有效的);将 colo-compare 的 th_off 下溢作为主要证据(rewriter 的 READ 先触发)。
cd lab
./run.sh
仅针对回环套接字 127.0.0.1:18770(filter-rewriter netdev)和 18771(colo-compare)。Pin 克隆自 github.com/qemu/QEMU 标签 v11.1.2 / 4fc49f46。启用 ASan。配置时启用 COLO proxy。仅作见证。
SUCCESS qemu-colo-l4-oob asan=heap-buffer-overflow access=READ sink=filter-rewriter control=alive QEMU-COLO-L4-OOB-WITNESS
复现:python3 qemu-colo-l4-oob-Abraxas-Labs.py。
parse_packet_early 必须在 IP 头之后要求完整的 L4 头(TCP 20、UDP 8、SCTP 12、AH 8),并在 size 结束于 transport_header 处或之前时拒绝。fill_connection_key 和重写器中的 th_* 存储必须检查剩余长度。colo-compare 必须在计算 payload_size 之前拒绝无法容纳于 pkt->size 的 th_off<<2。
4fc49f46dc95d4a27de2509e7fceb2931e91faebparse_packet_early · filter-rewriterGNU Affero GPL v3.0。参见 LICENSE。仅限回环实验环境。不提供任何担保。