0x01 Microsoft Windows
Microsoft Windows是美国微软公司以图形用户界面为基础研发的操作系统 ,主要运用于计算机、智能手机等设备。共有普通版本、服务器版本(Windows Server)、手机版本(Windows Phone)、嵌入式版本(Windows CE、Windows for IoT)等子系列,是全球应用最广泛的操作系统之一。
0x02 漏洞简介
微软上月发布的补丁包含一个可能执行代码的TCP/IP协议漏洞。tcpip.sys在对ipv6数据包进行重组时,NextHeaderOffset可能超出缓冲区范围,导致越界写的发生,利用该漏洞可以实现远程命令执行
0x03 漏洞详解
漏洞发生时,为如下函数调用栈
0: kd> kb
# RetAddr : Args to Child : Call Site
00 fffff80a`1f1842ea : ffffb00e`0cbef000 ffffb00e`0d333270 ffffb00e`0f5b4890 ffffb00e`00000050 : tcpip!Ipv6pReassembleDatagram+0x1e3
01 fffff80a`1f184442 : ffffb00e`00000000 fffff80a`1f1c61e8 00000000`00000000 ffffb00e`0d3138f0 : tcpip!Ipv6pReceiveFragment+0xae2
02 fffff80a`1f03bfdf : ffffb00e`0cbef000 ffffb00e`0cbef000 00000000`00000001 00000000`0000002b : tcpip!Ipv6pReceiveFragmentList+0x42
03 fffff80a`1f03de45 : fffff80a`1f1c1240 ffffb00e`0c8ec940 00000000`00000001 ffffb00e`0cbef000 : tcpip!IppReceiveHeaderBatch+0x3ef
04 fffff80a`1f044131 : ffffb00e`0d31eb90 ffffb00e`0d23e9c0 fffff803`94d7b001 00000000`00000000 : tcpip!IppFlcReceivePacketsCore+0x315
05 fffff80a`1f043e12 : 00000000`00000017 fffff803`00000001 fffff80a`1f001bf0 ffffb00e`0d23e901 : tcpip!FlpReceiveNonPreValidatedNetBufferListChain+0x271
06 fffff803`92ebce75 : 00000000`00000002 fffff803`931d1980 fffff80a`1f043d50 fffff803`94d7b1f0 : tcpip!FlReceiveNetBufferListChainCalloutRoutine+0xc2
07 fffff80a`1f0023a6 : ffffb00e`0cc1b7b0 00000000`00000000 ffffb00e`0c7ff870 ffffb00e`0d23e900 : nt!KeExpandKernelStackAndCalloutInternal+0x85
08 fffff80a`1e10392e : 00000000`00000000 fffff803`94d7b2c0 00000000`00000001 fffff80a`1de5f20d : tcpip!FlReceiveNetBufferListChain+0xb6
09 fffff80a`1e1028cc : fffff80a`1f522801 fffff803`94d7dd86 0000000e`00000000 fffff80a`00000001 : NDIS!ndisMIndicateNetBufferListsToOpen+0x11e
0a fffff80a`1eca6156 : 00000000`00000000 00000000`00000000 ffffb00e`0d0f4e40 ffffb00e`0d23e930 : NDIS!NdisMIndicateReceiveNetBufferLists+0x31c
0b fffff80a`1eca73e3 : ffffb00e`0d23e900 00000000`00000001 ffffb00e`0d0f4e40 fffff803`94d7b588 : e1i63x64!RECEIVE::RxIndicateNBLs+0x132
0c fffff80a`1ecae315 : ffffb00e`0c483830 ffffb00e`0d0f4000 ffffb00e`0d0f4001 fffff803`00000000 : e1i63x64!RECEIVE::RxProcessInterrupts+0x253
0d fffff80a`1ecae623 : ffffb00e`0c4226b0 00000001`00000000 00000001`00000000 00000000`00000000 : e1i63x64!INTERRUPT::MsgIntDpcTxRxProcessing+0x121
0e fffff80a`1ecaddb8 : ffffb00e`0e66f7d8 00000000`00000000 40200342`00000000 00000000`00000000 : e1i63x64!INTERRUPT::MsgIntMessageInterruptDPC+0x10f
0f fffff80a`1e104e69 : ffffda01`9d7c9010 ffffda01`9d7c9320 00000000`00000000 00000000`00000000 : e1i63x64!INTERRUPT::MiniportMessageInterruptDPC+0x28
10 fffff803`92e7f785 : ffffb00e`0d200000 fffff803`93155180 ffffb00e`0cc8e5d0 ffffb00e`0cc8e5d0 : NDIS!ndisInterruptDpc+0x1c9
11 fffff803`92e7ed10 : fffff80a`20dc79a8 00000000`002e593c 00000000`00140001 00000000`00000000 : nt!KiExecuteAllDpcs+0x335
12 fffff803`92f7500a : 00000000`00000000 fffff803`93155180 fffff803`931d1980 ffffb00e`0f6cc080 : nt!KiRetireDpcList+0x910
13 00000000`00000000 : fffff803`94d7c000 fffff803`94d76000 00000000`00000000 00000000`00000000 : nt!KiIdleLoop+0x5a
tcpip.sys 在使用IppReceiveHeaderBatch 函数处理接收到的数据包的同时,对 next header 的数值进行判断并调用相应函数处理对应头部,然后处理 fragment header ,漏洞发生在这个部位。
tcpip.sys 调用 Ipv6pReceiveFragmentList 函数对 fragment header 进行处理,然后对分片头进行重组
void Ipv6pReassembleDatagram(__int64 Packet, Reassembly_t *Reassembly, char OldIrql)
{
ExtensionHeaderLength = Reassembly->ExtensionHeaderLength;
TotalLength = ExtensionHeaderLength + Reassembly->DataLength;
HeaderAndOptionsLength = ExtensionHeaderLength + 0x28;
NetBufferList = NetioAllocateAndReferenceNetBufferAndNetBufferList(
IppReassemblyNetBufferListsComplete,
Reassembly,
0i64,
0i64,
0,
0);
NetBuffer = NetBufferList->FirstNetBuffer;
data = NdisGetDataBuffer(NetBuffer, HeaderAndOptionsLength, 0i64, 1u, 0) // 请求访问 NET_BUFFER 中的一段连续空间,请求的大小为 HeaderAndOptionsLength
Reassembly->IPv6.Payload_length = __ROR2__(TotalLength, 8);
*data = Reassembly->IPv6; // 复制 IPv6 header
memmove(data + 0x28, Reassembly->ExtensionHeader, Reassembly->ExtensionHeaderLength); // 复制 ExtensionHeader
*(data + Reassembly->nh_offset) = Reassembly->next_header; // 复制 next header
...
}
缓冲区 data 的大小为 HeaderAndOptionsLength,next header 的偏移值为 Reassembly->nh_offset。发生越界写的原因就是 Reassembly->nh_offset 的数值大于 HeaderAndOptionsLength。
接下来通过调试确定这两个数值的来源,测试用数据包组成如下:
0 1 2 3 4 5 6 7 8 9 a b c d e f
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
0000 | Ethernet II, 0x0e B | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +
0010 | |
+ IPv6 header, 0x28 B +
0020 | |
+ +--+--+--+--+--+--+--+--+--+--+
0030 | | Routing header, 8 B |93 59 -> ESP header, 8 B
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
0040 99 40 00 00 00 00|55 55 55 55 55 55 55 55 55 55 -> IV, 0x10 B
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
0050 55 55 55 55 55 55|eb 42 e4 0a 95 da 11 1d 21 a1| -> payload + padding + padding_length + next_header
+--+--+--+--+--+--+ + 0x30 B,已被加密
0060 |ea c7 31 c9 e1 24 48 8d f9 98 d4 98 82 b7 eb 5d|
+ +
0070 |b7 8f bf c6 3a 00 eb 22 7d 26 55 b7 43 9f 60 62|
+ +--+--+--+--+--+--+--+--+--+--+
0080 |e3 ea fe 8c 23 87|
+--+--+--+--+--+--+
然后对其进行解密,得到
0x00 -- -- -- -- -- -- 3a 00-00 01 56 56 56 56 55 55
0x10 55 55 55 55 55 55 55 55-55 55 55 55 55 55 55 55
0x20 55 55 55 55 55 55 01 02-03 04 05 06 07 08 09 0a
0x30 0b 0c 0d 0e 0e 2c
next header 字段的数值为 0x2c,即 Fragment Header for IPv6,进行调试
Packet->prefix_size = header_size;
Packet->nh_offset = Packet->prefix_size;
NetBufferList = Packet->net_buffer_list;
routing_header = NdisGetDataBuffer(NetBufferList->FirstNetBuffer, 8u, &Storage, 1u, 0);
len = 8 * routing_header->length + 8;
Packet->prefix_size += len;
Packet->nh_offset = Packet->prefix_size + LOWORD(NetBuffer->DataOffset) - data_offset + 9;
Packet->prefix_size += (iv_length + 8);
Packet->prefix_size += 8;
ExtensionHeaderLength = Packet->prefix_size - 0x30;
Reassembly->ExtensionHeaderLength = ExtensionHeaderLength;
Reassembly->nh_offset = Packet->nh_offset;
|<- data buffer size ->|
|<- 0x28 B ->|<- Extension Header 0x20 B ->|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| IPv6 header | Routing header | ESP header | IV | Payload |PL |NH |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
original packet:
+-----------------+-----------------+--------+--------+-//-+--------+
| Per-Fragment |Ext & Upper-Layer| first | second | | last |
| Headers | Headers |fragment|fragment|....|fragment|
+-----------------+-----------------+--------+--------+-//-+--------+
fragment packets:
+------------------+---------+-------------------+----------+
| Per-Fragment |Fragment | Ext & Upper-Layer | first |
| Headers | Header | Headers | fragment |
+------------------+---------+-------------------+----------+
+------------------+--------+-------------------------------+
| Per-Fragment |Fragment| second |
| Headers | Header | fragment |
+------------------+--------+-------------------------------+
o
o
o
+------------------+--------+----------+
| Per-Fragment |Fragment| last |
| Headers | Header | fragment |
+------------------+--------+----------+
0x04 漏洞范围
-
所有运行IPSEC的IPV6 windows设备
0x05 漏洞信息
-
漏洞名称:Windows TCP/IP 远程命令执行漏洞
-
漏洞编号:CVE-2022-34718
-
漏洞危害:严重 远程命令执行
-
漏洞poc:已知
-
漏洞exp:暂无
-
在野利用:存在
ps:网传exp疑似存在投毒嫌疑,请注意辨别
0x06 漏洞修复
官方已发布修复方案,请更新Windows系统至最新版本
原文始发于微信公众号(火山信安实验室):【漏洞通报】Windows TCP/IP 存在远程命令执行漏洞(CVE-2022-34718)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论