首页 网络安全 漏洞挖掘 查看内容

Windows TCP/IP远程执行代码漏洞分析

2020-10-23 09:41 |来自: 互联网 3223 0

摘要: 报告编号:B6-2020-101901报告来源:360-CERT报告作者:360-CERT更新日期:2020-10-190x01 前言1.1 环境搭建(1)攻击机环境:Ubuntu 20.04安装scapysudo apt install python-pip3 sudo pip3 install scapy (2)受 ...
关键词: length xffffe 00000000 aea Option BUFFER NULL 41414141 00 字节

报告编号:B6-2020-101901

报告来源:360-CERT

报告作者:360-CERT

更新日期:2020-10-19

0x01 前言

1.1 环境搭建

(1)攻击机环境:Ubuntu 20.04

安装scapy

sudo apt install python-pip3
sudo pip3 install scapy

(2)受害机环境:Windows 10 1909 x64

tcpip.sys 驱动版本:10.0.18362.476

(3)双机调试Windows 驱动:

https://blog.csdn.net/qq_21000273/article/details/52027708

断点:

bp tcpip!Ipv6pUpdateRDNSS
bp tcpip!Ipv6pHandleRouterAdvertisement
bp tcpip!Ipv6pHandleRouterAdvertisement+0xae4cc
bp tcpip!Ipv6pHandleRouterAdvertisement+0xae4db
bp tcpip!Ipv6pUpdateRDNSS+0x99
bp tcpip!Ipv6pUpdateRDNSS+0xca

1.2 背景知识

涉及的包类型:

type:24   Route Information Option
type:25   Recursive DNS Server Option
type: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 结构

typedef struct _NET_BUFFER {
  union {
    struct {
      PNET_BUFFER Next;
      PMDL        CurrentMdl;
      ULONG       CurrentMdlOffset;
      union {
        ULONG  DataLength;
        SIZE_T stDataLength;
      };
      PMDL        MdlChain;
      ULONG       DataOffset;
    };
    SLIST_HEADER      Link;
    NET_BUFFER_HEADER NetBufferHeader;
  };
  USHORT                ChecksumBias;
  USHORT                Reserved;
  NDIS_HANDLE           NdisPoolHandle;
  PVOID                 NdisReserved[2];
  PVOID                 ProtocolReserved[6];
  PVOID                 MiniportReserved[4];
  NDIS_PHYSICAL_ADDRESS DataPhysicalAddress;
  union {
    PNET_BUFFER_SHARED_MEMORY SharedMemoryInfo;
    PSCATTER_GATHER_LIST      ScatterGatherList;
  };
} NET_BUFFER, *PNET_BUFFER;

相关函数:

NdisGetDataBuffer 函数

PVOID NdisGetDataBuffer(
  PNET_BUFFER NetBuffer,
  ULONG       BytesNeeded,
  PVOID       Storage,
  UINT        AlignMultiple,
  UINT        AlignOffset
);

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的大小,第二个循环用于处理包,并且该阶段不再验证,两个循环的伪代码如下:

// 循环1

while ( 1 )
  {
        ……
    v28 = (KIRQL *)NdisGetDataBuffer(v9, 2u, v182, 1u, 0);
    v27 = v9->DataLength;
    actual_length_bytes = 8 * v28[1];
        ……
    switch ( v25 )
    {
      case 0x18u:       // case 0x18 (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;
          goto LABEL_275;
        }
        break;
      case 0x19u:  // case 0x19 (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;
  }

    ……

// 循环2 
while ( 1 )
{
    ……
     if ( *v75 == 0x18 )                   // case 0x18 (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 ( 
                    本文出处: https://www.toutiao.com/i6885187554979611148/
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部