报告编号:B6-2020-101901
报告来源:360-CERT
报告作者:360-CERT
更新日期:2020-10-19
0x01 前言
1.1 环境搭建
(1)攻击机环境:Ubuntu 20.04
安装scapy
sudoapt install python-pip3sudopip3 install scapy
(2)受害机环境:Windows 10 1909 x64
tcpip.sys 驱动版本:10.0.18362.476
(3)双机调试Windows 驱动:
https://blog.csdn.net/qq_21000273/article/details/52027708
断点:
bptcpip!Ipv6pUpdateRDNSSbptcpip!Ipv6pHandleRouterAdvertisementbptcpip!
Ipv6pHandleRouterAdvertisement+0xae4ccbptcpip!Ipv6pHandleRouterAdvertisement+0xae4dbbptcpip!Ipv6pUpdateRDNSS+0x99bptcpip!Ipv6pUpdateRDNSS+0xca
1.2 背景知识
涉及的包类型:
type:24 Route Information Optiontype:25
Recursive DNS Server Optiontype:134 IMCPv6 Router Advertisement
涉及的结构:
_MDL结构
typedef __struct_bcount (Size ) struct _MDL { struct _MDL *Next ;
CSHORT Size ; CSHORT MdlFlags ; struct _EPROCESS *Process ; PVOID MappedSystemVa ; PVOID StartVa ; ULONG ByteCount ; ULONG ByteOffset ;} MDL , *PMDL ;
_NET_BUFFER 结构
typedefstruct _NET_BUFFER {union{struct{PNET_BUFFERNext;
PMDLCurrentMdl;ULONGCurrentMdlOffset;union{ULONGDataLength;SIZE_TstDataLength;};PMDLMdlChain;ULONGDataOffset;};SLIST_HEADERLink;NET_BUFFER_HEADERNetBufferHeader;};USHORTChecksumBias;USHORTReserved;NDIS_HANDLENdisPoolHandle;PVOIDNdisReserved[2];PVOIDProtocolReserved[6];PVOIDMiniportReserved[4];NDIS_PHYSICAL_ADDRESSDataPhysicalAddress;union{PNET_BUFFER_SHARED_MEMORYSharedMemoryInfo;PSCATTER_GATHER_LISTScatterGatherList;};}NET_BUFFER, *PNET_BUFFER;
相关函数:
NdisGetDataBuffer 函数
PVOIDNdisGetDataBuffer(PNET_BUFFERNetBuffer,ULONGBytesNeeded,
PVOIDStorage,UINTAlignMultiple,UINTAlignOffset);
NetBuffer:指向NET_BUFFER 结构的指针
BytesNeeded:请求的连续数据的字节数
Storage:指向缓冲区的指针,如果调用者未提供缓冲区,则为NULL。缓冲区的大小必须大于或等于BytesNeeded中指定的字节数。如果此值为非NULL,并且请求的数据不连续,则NDIS将请求的数据将复制到Storage指向的地址。
Windows通过Ipv6pHandleRouterAdvertisement 函数处理 IPv6 路由器通告数据,在该函数中调用 NdisGetDataBuffer 函数从 NET_BUFFER 结构中访问连续或不连续的数据,通过 NET_BUFFER ->CurrentMdlOffset 字段来记录要访问数据起始地址相对于_MDL->MappedSystemVa 的偏移。
0x02 漏洞分析
2.1 漏洞背景
2020年10月14日,360CERT监测发现 Microsoft 发布了 TCP/IP远程代码执行漏洞 的风险通告,该漏洞是由于Windows TCP/IP堆栈 在处理IMCPv6 Router Advertisement(路由通告)数据包时存在漏洞,远程攻击者通过构造特制的ICMPv6 Router Advertisement(路由通告)数据包 ,并将其发送到远程Windows主机上,可造成远程BSOD,漏洞编号为CVE-2020-16898。
2.2 漏洞成因
根据rfc5006 描述,RDNSS包的length应为奇数,而当攻击者构造的RDNSS包的Length为偶数时,Windows TCP/IP 在检查包过程中会根据Length来获取每个包的偏移,遍历解析,导致对 Addresses of IPv6 Recursive DNS Servers 和下一个 RDNSS 选项的边界解析错误,从而绕过验证,将攻击者伪造的option包进行解析,造成栈溢出,从而导致系统崩溃。
RDNSS Option 数据包格式如下:
Type: 占8-bit,RDNSS 的类型为25
Length:8-bit无符号整数,单位长度为8个字节,所以Type, Length, Reserved, Lifetime一共占8个字节,一个单位长度,而一个IPv6地址占16个字节,两个单位长度,所以Length的最小值为3,且为奇数。
Reserved:保留字段
Lifetime:32-bit无符号整数,存活周期。
Addresses of IPv6 Recursive DNS Servers:保存RNDSS的IPv6地址,每个占16个字节,地址的数量会影响Length字段,number=(Length - 1) / 2。每增加一个地址,Length加2。
漏洞点存在于tcpip.sys -> Ipv6pHandleRouterAdvertisement 函数
漏洞调用链为:Icmpv6ReceiveDatagrams -> Ipv6pHandleRouterAdvertisement -> Ipv6pUpdateRDNSS
Ipv6pHandleRouterAdvertisement 函数存在两个循环,第一个循环遍历所有headers,做一些基本的验证,如length的大小,第二个循环用于处理包,并且该阶段不再验证,两个循环的伪代码如下:
//循环1while(1){……v28=(KIRQL*)NdisGetDataBuffer(v9,2u,v182,1u,0);
v27=v9->DataLength;actual_length_bytes=8*v28[1];……switch(v25){case 0x18u://case0x18(ICMPv6NDOptRouteInfo)……if(actual_length_bytes>0x18u||(v144=*((_BYTE*)NdisGetDataBuffer(v9,actual_length_bytes,v220,1u,0)+2),v144>0x80u)||v144>0x40u&&actual_length_bytes<0x18u//<-----【1】验证实际字节数,不能大于0x18||v144&&actual_length_bytes<0x10u){*a3=24;gotoLABEL_275;}break;case 0x19u://case0x19(ICMPv6NDOptRDNSS)//<-----【2】if((*(_BYTE*)(v11+404)&0x40)!=0&&actual_length_bytes<0x18u)*a3=25;break;}……if(actual_length_bytes){v31=actual_length_bytes+v9->CurrentMdlOffset;if(v31>=*(_DWORD*)(v9->Link.Region+0x28)){NdisAdvanceNetBufferDataStart(v9,actual_length_bytes,0,0i64);//<---actual_length_bytes=4*8=0x20}else{v9->DataOffset+=actual_length_bytes;v9->DataLength-=actual_length_bytes;v9->CurrentMdlOffset=v31;//更新CurrentMdlOffset}}v21+=actual_length_bytes;}……//循环2while(1){……if(*v75==0x18)//case0x18(ICMPv6NDOptRouteInfo){……v153=(unsigned__int8*)NdisGetDataBuffer(NetBuffer_1,actual_option,Storage_1,1u,0);//<---【3】v225=_mm_load_si128((const__m128i*)&_xmm);v174=v225.m128i_u32[((unsigned__int64)v153[3]>>3)&3];……}if(*v75==0x19)//xffffeaeaBUFFER41414141字节