CVE-2020-16898漏洞复现及分析

  • A+
所属分类:安全文章

更多全球网络安全资讯尽在邑安全

CVE-2020-16898漏洞复现及分析

0x00 漏洞概述

2020年10月13日,微软发布了关于TCP/IP远程代码执行漏洞的通告。漏洞编号危CVE-2020-16898,漏洞等级:严重。漏洞评分:9.8(后更新为8.8)。

这个问题是由于Windows错误的处理了ICMPv6 Router Advertisement包,从而造成了堆栈溢出。攻击者可以构造特定的ICMPv6 Router Advertisement数据包,发送到远程主机,从而达到任意远程代码执行的效果。

 

0x01 漏洞影响版本

Windows 10 Version 1709 for 32-bit Systems

Windows 10 Version 1709 for ARM64-based Systems

Windows 10 Version 1709 for x64-based Systems

Windows 10 Version 1803 for 32-bit Systems

Windows 10 Version 1803 for ARM64-based Systems

Windows 10 Version 1803 for x64-based Systems

Windows 10 Version 1809 for 32-bit Systems

Windows 10 Version 1809 for ARM64-based Systems

Windows 10 Version 1809 for x64-based Systems

Windows 10 Version 1903 for 32-bit Systems

Windows 10 Version 1903 for ARM64-based Systems

Windows 10 Version 1903 for x64-based Systems

Windows 10 Version 1909 for 32-bit Systems

Windows 10 Version 1909 for ARM64-based Systems

Windows 10 Version 1909 for x64-based Systems

Windows 10 Version 2004 for 32-bit Systems

Windows 10 Version 2004 for ARM64-based Systems

Windows 10 Version 2004 for x64-based Systems

Windows Server 2019

Windows Server 2019 (Server Core installation)

Windows Server, version 1903 (Server Core installation)

Windows Server, version 1909 (Server Core installation)

Windows Server, version 2004 (Server Core installation)

 

0x02漏洞复现验证

复现环境:

靶机:

Windows10 1909

攻击机:

系统:Ubuntu 18.04

组件版本:Python3.6.9,scapy2.4.4

网络:攻击机和靶机需在同一内网下且数据包可以到达。

验证结果:

CVE-2020-16898漏洞复现及分析

 

0x03 漏洞分析

RDNSS中length字段是以组为单位显示的,默认情况下为奇数。当这个字段为偶数时,会导致tcpip.sys出现解析错误。

rfc5006中定义了RDNSS包的各字段作用、大小和偏移。

 0                   1                   2                   

 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|     Type      |     Length    |           Reserved            |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|                           Lifetime                            |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|                                                               |

:            Addresses of IPv6 Recursive DNS Servers            :

|                                                               |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Type:

8-bit,RDNSS类型为25

length:

8-bit无符号整数。主要代表option的长度,一组代表8个字节。RDNSS数据包头部为八字节,而IPv6为16字节。即最小为24字节,8字节一组,Length最小为3。如果有多个IPv6地址,则每次Length加2。所以Length默认情况下是奇数。

Reserved:

16-bit,保留字段。

Lifetime:

32-bit无符号整数。RDNSS地址用于解析的最长时间。当为0xffffffff时,表示无穷大。

先看一下正常的数据包,可以看到相关的一些字段信息,且Length为奇数

CVE-2020-16898漏洞复现及分析

之后看一下攻击的数据包,这里wireshark会根据Length的长度解析数据包,Length为4会认为第一个Option包为20byte,而IPv6地址为16字节,而x01x02x03x04x05x06x07x08只有八个字节,所以会把下一个Option的前八字节认为是IPv6地址的后八字节,也就是这里的102:304:506:708:1926:4242:4242:4242。而Option是根据Length解析的,是从x19x26这里开始,所以这里的数据就会被重复解析。

CVE-2020-16898漏洞复现及分析

接下来详细分析下漏洞

漏洞点存在于tcpip!Ipv6pHandleRouterAdvertisement,直接在该函数中下断点。

  while ( 1 )

  {

    v27 = *(v9 + 24);

    v192 = 0;

    if ( v27 < 2 )

      break;

    v28 = NdisGetDataBuffer(v9, 2i64, &v192, 1i64, 0);// 获取具体option字段内数据

    v27 = *(v9 + 24);

    length = 8 * v28[1];//实际长度,v28[1]为数据包中的length字段

    if ( length && length <= v27 )              // length bytes<=0x150

    {

      v25 = *v28;

      v30 = 1;

    }

    else

    {

      v30 = 0;

    }

    if ( !v30 )

      break;

    switch ( v25 )                              // type

    {

      case 1u:

        if ( (*(*(v11 + 40) + 36i64) & 0x210) == 16 )

        {

          if ( length != v177 + 2i64 )

          {

            *v7 = 21;

            goto LABEL_276;

          }

          v32 = *(v9 + 16) + 2;

          if ( v32 >= *(*(v9 + 8) + 40i64) )

          {

            NdisAdvanceNetBufferDataStart(v9, 2i64, 0i64, 0i64);

          }

          else

          {

            *(v9 + 40) += 2;

            *(v9 + 24) = v27 - 2;

            *(v9 + 16) = v32;

          }

          length -= 2;

          v21 += 2;

          v190 = NdisGetDataBuffer(v9, length, &v265, 1i64, 0);

        }

        break;

      case 3u:

        memset(&Dst, 0, 0x20ui64);

        if ( length != 32 || *(NdisGetDataBuffer(v9, 32i64, &Dst, 1i64, 0) + 2) > 0x80u )

        {

          *v7 = 23;

          goto LABEL_276;

        }

        break;

      case 5u:

        v206 = 0i64;

        if ( length != 8 )

        {

          *v7 = 22;

          goto LABEL_276;

        }

        v185 = _byteswap_ulong(*(NdisGetDataBuffer(v9, 8i64, &v206, 1i64, 0) + 4));

        break;

      case 0x18u:

        v253 = 0i64;

        v254 = 0i64;

        v255 = 0i64;

        if ( length > 0x18u

          || (v147 = *(NdisGetDataBuffer(v9, length, &v253, 1i64, 0) + 2), v147 > 0x80u)

          || v147 > 0x40u && length < 0x18u

          || v147 && length < 0x10u )

        {

          *v7 = 24;

          goto LABEL_276;

        }

        break;

      case 0x19u:

        if ( *(v11 + 404) & 0x40 && length < 0x18u )// length bytes

          *v7 = 25;

        break;

      default:

        if ( v25 == 0x1F && *(v11 + 404) & 0x40 && length < 0x10u )

        {

          *v7 = 26;

LABEL_276:

          v27 = *(v9 + 24);

          goto LABEL_33;

        }

        break;

    }

    if ( *v7 != 28 )

      goto LABEL_276;

    if ( length )

    {

      v31 = length + *(v9 + 16);

      if ( v31 >= *(*(v9 + 8) + 40i64) )

      {

        NdisAdvanceNetBufferDataStart(v9, length, 0i64, 0i64);

      }

      else

      {

        *(v9 + 40) += length;

        *(v9 + 24) -= length;

        *(v9 + 16) = v31;

      }

    }

    v21 += length;

  }

往下调试可以看到,这里有一个循环来处理数据包。而0x18选项这里是对长度有限制条件的。首先会获取每个option内数据的大小进行验证,读取第一个Option数据,获取Option中的Length字段为x04,4*8=0x20字节,从Option头相加0x20字节,会直接跳到下一个x19x26,从而跳过长度限制。

CVE-2020-16898漏洞复现及分析

while ( 1 )

{

  ...

  if ( *v78 == 0x18 )

  {

     v80 = 8 * v78[1];

     v256 = 0i64;

     v257 = 0i64;

     v258 = 0i64;

     v249 = 0i64;

     v250 = 0i64;

     v156 = NdisGetDataBuffer(v72, v79, &v256, 1i64, 0);

     _mm_storeu_si128(&v264, _mm_load_si128(&_xmm));

     v184 = *(&v264 + ((*(v156 + 3) >> 3) & 3));

     if ( v184 != -1 )

     {

        v157 = *(v156 + 2);

        v158 = _byteswap_ulong(*(v156 + 4));

        v159 = 2 * v158;

        if ( (2 * v158) >> 1 != v158 )

           v159 = -1;

        CopyPrefix(&v249, v156 + 8, *(v156 + 2), 16i64);

        v172 = v184;

        LOBYTE(v170) = v157;

        IppUpdateAutoConfiguredRoute(v11, Buf2, v68, &v249, v170);

        v76 = v179;

        if ( v67 <= v159 )

           v159 = v67;

        v67 = v159;

     }

     goto LABEL_115;

   }

   if ( *v78 == 0x19 )

   {

      if ( *(v11 + 404) & 0x40 )          // 可能是系统设置那里

      {

        Ipv6pUpdateRDNSS(v11, v72, Buf2, v199, &v180);

        goto LABEL_310;

      }

    }

...

}

这部分中Ipv6pUpdateRDNSS这个函数是最重要的部分。在这个函数中,会计算具体IPv6的个数,而计算IPv6的个数是通过(Length-1)/2来实现的。

CVE-2020-16898漏洞复现及分析

所以会导致错误的指向了之前的数据了,也就是x01x02这个部分。

CVE-2020-16898漏洞复现及分析

这里补充一下关于相关的一些结构体和函数的一些知识。

关于NdisGetDataBuffer 函数

PVOID NdisGetDataBuffer(

  PNET_BUFFER NetBuffer,

  ULONG       BytesNeeded,

  PVOID       Storage,

  UINT        AlignMultiple,

  UINT        AlignOffset

);

参数:

NetBuffer:

指向NET_BUFFER结构的指针。

BytesNeeded:

请求的数据的连续字节数。

Storage:

[可选]指向缓冲区的指针,如果调用者未提供缓冲区,则为NULL。缓冲区的大小必须大于或等于BytesNeeded中指定的字节数 。如果该值为非NULL,并且请求的数据不连续,则NDIS将请求的数据复制到Storage指示的区域 。

AlignMultiple:

对齐倍数,以2的幂表示。例如2、4、8、16等。如果 AlignMultiple为1,则没有对齐要求。

AlignOffset

与对齐倍数的偏移量(以字节为单位)。

用途:

NdisGetDataBuffer 函数通过 NET_BUFFER ->CurrentMdlOffset 字段来记录要访问数据起始地址相对于_MDL->MappedSystemVa 的偏移。

关于_NET_BUFFER

0: kd> dt ndis!_NET_BUFFER

   +0x000 Next             : Ptr64 _NET_BUFFER

   +0x008 CurrentMdl       : Ptr64 _MDL

   +0x010 CurrentMdlOffset : Uint4B

   +0x018 DataLength       : Uint4B

   +0x018 stDataLength     : Uint8B

   +0x020 MdlChain         : Ptr64 _MDL

   +0x028 DataOffset       : Uint4B

   +0x000 Link             : _SLIST_HEADER

   +0x000 NetBufferHeader  : _NET_BUFFER_HEADER

   +0x030 ChecksumBias     : Uint2B

   +0x032 Reserved         : Uint2B

   +0x038 NdisPoolHandle   : Ptr64 Void

   +0x040 NdisReserved     : [2] Ptr64 Void

   +0x050 ProtocolReserved : [6] Ptr64 Void

   +0x080 MiniportReserved : [4] Ptr64 Void

   +0x0a0 DataPhysicalAddress : _LARGE_INTEGER

   +0x0a8 SharedMemoryInfo : Ptr64 _NET_BUFFER_SHARED_MEMORY

   +0x0a8 ScatterGatherList : Ptr64 _SCATTER_GATHER_LIST

关于_MDL

0: kd> dt ndis!_MDL

   +0x000 Next             : Ptr64 _MDL

   +0x008 Size             : Int2B

   +0x00a MdlFlags         : Int2B

   +0x00c AllocationProcessorNumber : Uint2B

   +0x00e Reserved         : Uint2B

   +0x010 Process          : Ptr64 _EPROCESS

   +0x018 MappedSystemVa   : Ptr64 Void

   +0x020 StartVa          : Ptr64 Void

   +0x028 ByteCount        : Uint4B

   +0x02c ByteOffset       : Uint4B

第一次调用Ipv6pUpdateRDNSS函数之前:

0: kd> dt ndis!_NET_BUFFER @r14

   +0x000 Next             : (null

   +0x008 CurrentMdl       : 0xffff9a04`9ae4c350 _MDL

   +0x010 CurrentMdlOffset : 0x10

   +0x018 DataLength       : 0x150

   +0x018 stDataLength     : 0x150

   +0x020 MdlChain         : 0xffff9a04
`9c40a180 _MDL

   +0x028 DataOffset       : 0x70

   +0x000 Link             : _SLIST_HEADER

   +0x000 NetBufferHeader  : _NET_BUFFER_HEADER

   +0x030 ChecksumBias     : 0

   +0x032 Reserved         : 0

   +0x038 NdisPoolHandle   : 0xffff9a04`9aba28c0 Void

   +0x040 NdisReserved     : [2] (null

   +0x050 ProtocolReserved : [6] 0x00000160
`00000000 Void

   +0x080 MiniportReserved : [4] (null

   +0x0a0 DataPhysicalAddress : _LARGE_INTEGER 0x0

   +0x0a8 SharedMemoryInfo : (null

   +0x0a8 ScatterGatherList : (null

0: kd> dt ndis!_MDL 0xffff9a04`9ae4c350

   +0x000 Next             : 0xffff9a04
`9ae4c7d0 _MDL

   +0x008 Size             : 0n56

   +0x00a MdlFlags         : 0n4

   +0x00c AllocationProcessorNumber : 0x9a04

   +0x00e Reserved         : 0xffff

   +0x010 Process          : (null

   +0x018 MappedSystemVa   : 0xffff9a04`9ae4c390 Void

   +0x020 StartVa          : 0xffff9a04
`9ae4c000 Void

   +0x028 ByteCount        : 0x30

   +0x02c ByteOffset       : 0x390

0: kd> db 0xffff9a04`9ae4c390+0x10

ffff9a04
`9ae4c3a0  19 04 00 00 ff ff ff ff-5a 5a 5a 5a 5a 5a 5a 5a  ........ZZZZZZZZ

ffff9a04`9ae4c3b0  5a 5a 5a 5a 5a 5a 5a 5a-01 02 03 04 05 06 07 08  ZZZZZZZZ........

ffff9a04
`9ae4c3c0  00 d0 09 02 43 63 50 63-9a 74 0e 74 7b 4b cd b6  ....CcPc.t.t{K..

ffff9a04`9ae4c3d0  fe 02 04 00 ff ff 00 00-90 c3 88 a0 04 9a ff ff  ................

ffff9a04
`9ae4c3e0  60 09 80 02 00 00 00 00-60 09 c0 02 00 00 00 00  `.......`.......

ffff9a04`9ae4c3f0  60 09 c0 02 00 00 00 00-19 19 f3 02 00 00 00 00  `...............

ffff9a04`9ae4c400  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

ffff9a04
`9ae4c410  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

第一次调用Ipv6pUpdateRDNSS函数之后

0: kd> dt ndis!_NET_BUFFER @r14

   +0x000 Next             : (null)

   +0x008 CurrentMdl       : 0xffff9a04`9ae4c350 _MDL

   +0x010 CurrentMdlOffset : 0x28

   +0x018 DataLength       : 0x138

   +0x018 stDataLength     : 0x138

   +0x020 MdlChain         : 0xffff9a04
`9c40a180 _MDL

   +0x028 DataOffset       : 0x88

   +0x000 Link             : _SLIST_HEADER

   +0x000 NetBufferHeader  : _NET_BUFFER_HEADER

   +0x030 ChecksumBias     : 0

   +0x032 Reserved         : 0

   +0x038 NdisPoolHandle   : 0xffff9a04`9aba28c0 Void

   +0x040 NdisReserved     : [2] (null)

   +0x050 ProtocolReserved : [6] 0x00000160
`00000000 Void

   +0x080 MiniportReserved : [4] (null)

   +0x0a0 DataPhysicalAddress : _LARGE_INTEGER 0x0

   +0x0a8 SharedMemoryInfo : (null)

   +0x0a8 ScatterGatherList : (null)

0: kd> dt ndis!_MDL 0xffff9a04`9ae4c350

   +0x000 Next             : 0xffff9a04
`9ae4c7d0 _MDL

   +0x008 Size             : 0n56

   +0x00a MdlFlags         : 0n4

   +0x00c AllocationProcessorNumber : 0x9a04

   +0x00e Reserved         : 0xffff

   +0x010 Process          : (null)

   +0x018 MappedSystemVa   : 0xffff9a04`9ae4c390 Void

   +0x020 StartVa          : 0xffff9a04
`9ae4c000 Void

   +0x028 ByteCount        : 0x30

   +0x02c ByteOffset       : 0x390

0: kd> db 0xffff9a04`9ae4c390+0x28

ffff9a04
`9ae4c3b8  01 02 03 04 05 06 07 08-00 d0 09 02 43 63 50 63  ............CcPc

ffff9a04`9ae4c3c8  9a 74 0e 74 7b 4b cd b6-fe 02 04 00 ff ff 00 00  .t.t{K..........

ffff9a04
`9ae4c3d8  90 c3 88 a0 04 9a ff ff-60 09 80 02 00 00 00 00  ........`.......

ffff9a04
`9ae4c3e8  60 09 c0 02 00 00 00 00-60 09 c0 02 00 00 00 00  `.......`.......

ffff9a04`9ae4c3f8  19 19 f3 02 00 00 00 00-00 00 00 00 00 00 00 00  ................

ffff9a04
`9ae4c408  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

ffff9a04`9ae4c418  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

ffff9a04
`9ae4c428  00 00 00 00 00 00 00 00-20 77 00 9f 04 9a ff ff  ........ w....

可以看到现在已经将x01x02当做下一个Option的头部。而x02位于Length字段,x01无这个Type,所以会跳过0x10个字节。直接跳到下一个x19x04这部分。

CVE-2020-16898漏洞复现及分析

之后再一次调用了Ipv6pUpdateRDNSS。

调用前:

0: kd> dt ndis!_NET_BUFFER @r14

   +0x000 Next             : (null

   +0x008 CurrentMdl       : 0xffff9a04`9ae4c7d0 _MDL

   +0x010 CurrentMdlOffset : 8

   +0x018 DataLength       : 0x128

   +0x018 stDataLength     : 0x128

   +0x020 MdlChain         : 0xffff9a04
`9c40a180 _MDL

   +0x028 DataOffset       : 0x98

   +0x000 Link             : _SLIST_HEADER

   +0x000 NetBufferHeader  : _NET_BUFFER_HEADER

   +0x030 ChecksumBias     : 0

   +0x032 Reserved         : 0

   +0x038 NdisPoolHandle   : 0xffff9a04`9aba28c0 Void

   +0x040 NdisReserved     : [2] (null

   +0x050 ProtocolReserved : [6] 0x00000160
`00000000 Void

   +0x080 MiniportReserved : [4] (null

   +0x0a0 DataPhysicalAddress : _LARGE_INTEGER 0x0

   +0x0a8 SharedMemoryInfo : (null

   +0x0a8 ScatterGatherList : (null

0: kd> dt ndis!_MDL 0xffff9a04`9ae4c7d0

   +0x000 Next             : 0xffff9a04
`9ae4c8f0 _MDL

   +0x008 Size             : 0n56

   +0x00a MdlFlags         : 0n4

   +0x00c AllocationProcessorNumber : 0xffff

   +0x00e Reserved         : 0xffff

   +0x010 Process          : (null

   +0x018 MappedSystemVa   : 0xffff9a04`9ae4c810 Void

   +0x020 StartVa          : 0xffff9a04
`9ae4c000 Void

   +0x028 ByteCount        : 0x30

   +0x02c ByteOffset       : 0x810

0: kd> db 0xffff9a04`9ae4c810+0x8

ffff9a04
`9ae4c818  19 04 00 00 ff ff ff ff-5a 5a 5a 5a 5a 5a 5a 5a  ........ZZZZZZZZ

ffff9a04`9ae4c828  5a 5a 5a 5a 5a 5a 5a 5a-18 22 5a 5a 5a 5a 5a 5a  ZZZZZZZZ."ZZZZZZ

ffff9a04
`9ae4c838  5a 5a 5a 5a 5a 5a 5a 5a-00 19 09 02 41 6c 65 70  ZZZZZZZZ....Alep

ffff9a04`9ae4c848  9a fe 7b 74 7b 4b cd b6-d0 a1 c9 99 04 9a ff ff  ..{t{K..........

ffff9a04
`9ae4c858  20 01 22 01 00 00 00 00-70 d2 fe 9f 04 9a ff ff   .".....p.......

ffff9a04`9ae4c868  c0 08 65 9a 04 9a ff ff-a0 0f 00 00 00 00 00 00  ..e.............

ffff9a04`9ae4c878  00 00 00 00 00 00 00 00-fa ad db ba fa ad db ba  ................

ffff9a04`9ae4c888  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

调用之后。可以看到这部分执行之后已经指向了x18x22。

0: kd> dt ndis!_NET_BUFFER @r14

   +0x000 Next             : (null

   +0x008 CurrentMdl       : 0xffff9a04`9ae4c7d0 _MDL

   +0x010 CurrentMdlOffset : 0x20

   +0x018 DataLength       : 0x110

   +0x018 stDataLength     : 0x110

   +0x020 MdlChain         : 0xffff9a04
`9c40a180 _MDL

   +0x028 DataOffset       : 0xb0

   +0x000 Link             : _SLIST_HEADER

   +0x000 NetBufferHeader  : _NET_BUFFER_HEADER

   +0x030 ChecksumBias     : 0

   +0x032 Reserved         : 0

   +0x038 NdisPoolHandle   : 0xffff9a04`9aba28c0 Void

   +0x040 NdisReserved     : [2] (null

   +0x050 ProtocolReserved : [6] 0x00000160
`00000000 Void

   +0x080 MiniportReserved : [4] (null

   +0x0a0 DataPhysicalAddress : _LARGE_INTEGER 0x0

   +0x0a8 SharedMemoryInfo : (null

   +0x0a8 ScatterGatherList : (null

0: kd> dt ndis!_MDL 0xffff9a04`9ae4c7d0

   +0x000 Next             : 0xffff9a04
`9ae4c8f0 _MDL

   +0x008 Size             : 0n56

   +0x00a MdlFlags         : 0n4

   +0x00c AllocationProcessorNumber : 0xffff

   +0x00e Reserved         : 0xffff

   +0x010 Process          : (null

   +0x018 MappedSystemVa   : 0xffff9a04`9ae4c810 Void

   +0x020 StartVa          : 0xffff9a04
`9ae4c000 Void

   +0x028 ByteCount        : 0x30

   +0x02c ByteOffset       : 0x810

0: kd> db 0xffff9a04`9ae4c810+0x20

ffff9a04
`9ae4c830  18 22 5a 5a 5a 5a 5a 5a-5a 5a 5a 5a 5a 5a 5a 5a  ."ZZZZZZZZZZZZZZ

ffff9a04`9ae4c840  00 19 09 02 41 6c 65 70-9a fe 7b 74 7b 4b cd b6  ....Alep..{t{K..

ffff9a04`9ae4c850  d0 a1 c9 99 04 9a ff ff-20 01 22 01 00 00 00 00  ........ ."
.....

ffff9a04`9ae4c860  70 d2 fe 9f 04 9a ff ff-c0 08 65 9a 04 9a ff ff  p.........e.....

ffff9a04
`9ae4c870  a0 0f 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

ffff9a04`9ae4c880  fa ad db ba fa ad db ba-00 00 00 00 00 00 00 00  ................

ffff9a04
`9ae4c890  00 00 00 00 00 00 00 00-03 00 00 00 01 00 00 00  ................

ffff9a04`9ae4c8a0  50 c8 e4 9a 04 9a ff ff-10 e3 10 2d 00 f8 ff ff  P..........-....

Type为0x18时,会调用NdisGetDataBuffer函数,Length为0x22,也就是0x22*8=0x110个字节。对于NdisGetDataBuffer函数来说,当数据包是分片发送时,会被暂时存放到一个的栈空间内,也就是该函数的第三个参数。而当前的栈空间是不够的,所以导致了栈溢出,由于内核中存在GS保护,每次在函数结束时会验证函数初始阶段存放的Cookie值。如果Cookie值被修改则会报错,而BSOD正是这个原因。

 

0x04 漏洞危害

该漏洞基本可以稳定导致远程主机BSOD,条件受限于必须在同一内网下并且会对RDNSS包进行处理。对于远程代码执行,光靠这一个漏洞基本不可能达到代码执行的目的,内核中的保护很多,对于GS保护来说,需要与一个内存泄露的漏洞组合利用才能导致远程代码执行。

原文来自:安全客

原文链接:https://www.anquanke.com/post/id/220862

欢迎收藏并分享朋友圈,让五邑人网络更安全

CVE-2020-16898漏洞复现及分析

欢迎扫描关注我们,及时了解最新安全动态、学习最潮流的安全姿势!


推荐文章

1

新永恒之蓝?微软SMBv3高危漏洞(CVE-2020-0796)分析复现

2

重大漏洞预警:ubuntu最新版本存在本地提权漏洞(已有EXP) 



本文始发于微信公众号(邑安全):CVE-2020-16898漏洞复现及分析

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: