使用WinDBG调试分析CVE-2020-1206:SMBleed信息泄露漏洞

robots

 

目录

使用WinDBG调试分析CVE-2020-1206:SMBleed信息泄露漏洞

一、简介

1.1 漏洞实例简介

1.2 漏洞基本原理

二、环境说明

2.1 工具

2.2 环境

三、分析过程

3.1 漏洞复现

3.2 逆向分析

3.3 POC代码及验证

四、 一些问题

 

一、 简介

1.1 漏洞实例简介

CVE-2020-1206。该漏洞是由ZecOps安全研究人员在SMBGhost同一漏洞函数中发现的,又被称为SMBleed,是SMBv3协议中的一个信息泄露漏洞。类似于心脏滴血漏洞,此类漏洞可以泄露用户隐私敏感信息,造成很大的安全隐患。

该漏洞被ZecOps安全研究人员发现后,微软官方及时更新了补丁,尚未有漏洞利用的安全实例被曝光。

1.2 漏洞基本原理

在SMB协议工作过程中,引发漏洞的函数是srv2.sys中的Srv2DecompressData函数,该函数用于还原(解压)SMB数据。首先根据原始压缩数据中的OriginalCompressedSegmentSize和Offset计算出解压后结构的大小,然后通过SrvNetAllocateBuffer函数获取SRVNET BUFFER HDR结构(该结构中指明了可存放无需解压的Offset长度的数据和解压数据的缓冲区的User Buffer),然后调用SmbCompressionDecompress函数向User Buffer的Offset偏移处写入数据。

图1 数据包PCOMPRESSION_TRANSFORM_HEADER结构(上)

SRVNET BUFFER HDR结构(下)

在SmbCompressionDecompress函数中有一个错误的操作,如下所示,如果nt!RtlDecompressBufferEx2返回值非负(解压成功),则将FinalCompressedSize赋值为OriginalCompressedSegmentSize。因而,只要数据解压成功,就不会进入SrvNetFreeBuffer等流程,即使解压操作后会判断FinalCompressedSize和OriginalCompressedSegmentSize是否相等。

这使得对FinalCompressedSize和OriginalCompressedSegmentSize是否相等的检查变得无效,只要解压成功就会将解压的数据写入User buffer缓冲区,最后把整个SRVNET BUFFER HDR结构返回。

这就是CVE-2020-1206的成因,攻击者可以利用这一点构造出特制的数据包将OriginalCompressedSegmentSize设置为比实际压缩的数据长度大的数,让系统认为解压后的数据长度就是OriginalCompressedSegmentSize大小。那么实际解压缩的数据并不需要这么大的空间,从而泄露了内存中分配出来但又没用上的后半部分内核未初始化的数据。

如下所示,POC中将OriginalCompressedSegmentSize设置为x + 0x1000,offset设置为0,最终得到解压后的数据 (长度为x),其后面跟有未初始化的内核数据 ,然后利用解压后的SMB2 WRITE 消息泄露后面紧跟着的长度为0x1000的未初始化数据。

图2 POC利用造成的内核数据泄露示意图

 

二、环境说明

2.1 工具

  1. IDA(主机)
  2. WinDbg Preview(主机)
  3. Vmware(主机)
  4. Wireshark(攻击机)

2.2 环境

  1. 主机:win10
  2. 虚拟机

攻击机:win10 1903 (192.168.238.130)

靶机:win10 1909 (192.168.238.131)

 

三、分析过程

3.1 漏洞复现

在win10 1903上使用公开的SMBleed.exe进行测试,攻击win10 1909。步骤如下:

根据SMB协议的工作机制,首先在win10 1909上共享C盘,确保允许Everyone进行更改(或添加其他用户并赋予其读取和更改权限),然后在C盘下创建share目录,以便对文件写入和读取。

图3 设置C盘共享

设置完共享属性后,同一网络下的其他用户便可以对c盘下的文件进行访问。

图4 其他用户可在网络下访问

在攻击机上利用扫描程序分析靶机是否存在SMBGhost或SMBleed漏洞

图5 漏洞扫描程序

按照提示运行SMBleed.exe程序,例:SMBleed.exe win10 192.168.238.131 DESKTOP-B0180QH xiao_han 123123 C share\hello.txt leak.bin

图6 POC利用

然后可以看到,当前文件夹下生成了一个leak.bin文件。其内容是Userbuffer后面跟着的0x1000字节的未初始化内核数据。

图7 生成leak.bin文件

抓包分析,在复现的同时可以抓包。根据数据包可判断POC流程大概是这样的:SMB协商->用户认证->创建文件->利用漏洞泄露内存信息并写入文件->将文件读取到本地->结束连接。

注意到一个来自服务端的Write Response数据包,其status为STATUS_SUCCESS,说明写入操作成功。ZecOps在文章中提到过他们利用SMB2 WRITE消息来演示此漏洞,因而我们需要关注一下其对应的请求包,也就是下图中id为239的那个数据包。

图8 POC构造的恶意请求包

可以看到,在该请求包中,实际压缩前的数据CompressedData字段只有0x70个字节的内容,而POC将OriginalSize字段设置为了0x1070的大小,从而可借助 SMB2 WRITE 将未初始化的内存泄露出来。

3.2 逆向分析

使用IDA打开系统文件srv2.sys,找到Srv2DecompressData函数

图9 Srv2DecompressData函数

Srv2DecompressData的参数a1就是请求包的Header指针,可以通过该指针获取OriginalCompressedSegmentSize,Offset和压缩算法CompressionAlgo等字段。

图10 请求包头结构

首先SrvNetAllocateBuffer函数会根据参数Header->OriginalCompressed SegmentSize +和Header->Offset计算出Userbuffer的大小,去LookAside中寻找大小合适的缓冲区,并返回其后面的SRVNET BUFFER HDR结构,该结构偏移0x18处指向该缓冲区User Buffer。

图11 SRVNET BUFFER结构

然后在SmbCompressionDecompress函数中,把数据解压到Userbuffer缓冲区,由于其中对FinalCompressedSize的错误赋值,使对FinalCompressedSize和OriginalCompressedSegmentSize是否相等的判断失效。

图12 SmbCompressionDecompress函数

最后由memmove写入offset大小的RawData字段。

图13 memmove

3.3 POC代码及验证

最后我们使用Windbg Preview对POC利用的细节进行双机调试

首先设置调试环境

图14 设置调试机串行端口命名管道

图15 设置内核调试模式

图16 设置符号表路径

图17 调试机上的windbg设置

环境配置好后,开始连接调试机进行双机调试

图18 连接成功

KD> lml查看已载入的模块,缺少srv2.sys所需要的符号表

KD> .reload 重载符号表

图19 找到srv2.sys

KD> .reload /f srv2.sys

KD> !sym noisy

加载srv2.pdb

图20 载入srv2.pdb

KD> Bp srv2!Srv2DecompressData 设置断点

图21 设置断点

启用断点后,攻击机运行SMBleed.exe触发断点,然后kd就会停在断点处,即srv2!Srv2DecompressData的函数入口处。

图22 触发断点

KD> r 此时查看寄存器的值。可以看到Srv2DecompressData的参数此时在rdi中,即请求包头header指针的地址为0xffffdb8cdffce8e0

图22 查看header指针地址

然后查看header报文结构,可以看到在协议号(FC 53 4D 42 SMB)后面紧跟着的就是originalSize字段,为0x1070。但是可以看到Compressed Data只有数据包底部的0x70个字节,此即POC伪造的恶意数据包。

图23 查看header结构

然后执行到SrvNetAllocateBuffer函数,查看其返回值。可以看到rax= 0xffffdb8cdff8d150,即SRVNET BUFFER指针的地址

图24 查看ALLOC指针地址

图25 恶意数据包

图26 泄露的0x1000个字节的内核数据

到这里,漏洞的POC利用和动态调试就算完成了。

 

四、 一些问题

  1. 该漏洞影响到的windows版本包括win10 1903和win10 1909。最开始是尝试用的1909,但是这一版本存在一个空指针引用的问题,导致SMB工作的时候会导致系统蓝屏,无法进行后续调试。
  2. 在双机调试的时候,一开始下的断点确实也在漏洞点上,但是实际上POC利用过程会在服务端和客户端之间发送很多SMB数据包,于是调试会停在第一次触发断点的时候,而在攻击机那一方,超时会返回错误。经过多次调试以及抓包分析最终确定了恶意数据包的具体触发次数,从而设置条件断点,成功跟踪到恶意数据包的decompressdata函数。
  3. 由于自身的水平原因,希望能够抛砖引玉,大佬们不吝赐教。
(完)