CVE-2020-1206: SMBleed漏洞分析

  • A+

概述

SMBGhost (CVE-2020-0796) 是SMBv3.1.1中的压缩函数中的一个安全漏洞,攻击者利用该漏洞可以实现本地权限提升,更多参见
https://blog.zecops.com/vulnerabilities/exploiting-smbghost-cve-2020-0796-for-a-local-privilege-escalation-writeup-and-poc/

近期,研究人员又在同一压缩函数中发现了一个安全漏洞——SMBleed (CVE-2020-1206)。攻击者利用该漏洞可以远程从窃取kernel 内存信息。与SMBGhost漏洞结合形成利用链后,就可以实现远程代码执行攻击。

漏洞分析

SMBleed (CVE-2020-1206)漏洞

SMBleed 漏洞位于srv2.sys SMB服务器驱动的Srv2DecompressData函数中,下面是该函数中有漏洞部分的简化版本:
```
typedef struct _COMPRESSION_TRANSFORM_HEADER
{
ULONG ProtocolId;
ULONG OriginalCompressedSegmentSize;
USHORT CompressionAlgorithm;
USHORT Flags;
ULONG Offset;
} COMPRESSION_TRANSFORM_HEADER, *PCOMPRESSION_TRANSFORM_HEADER;

typedef struct _ALLOCATION_HEADER
{
// ...
PVOID UserBuffer;
// ...
} ALLOCATION_HEADER, *PALLOCATION_HEADER;

NTSTATUS Srv2DecompressData(PCOMPRESSION_TRANSFORM_HEADER Header, SIZE_T TotalSize)
{
PALLOCATION_HEADER Alloc = SrvNetAllocateBuffer(
(ULONG)(Header->OriginalCompressedSegmentSize + Header->Offset),
NULL);
If (!Alloc) {
return STATUS_INSUFFICIENT_RESOURCES;
}

ULONG FinalCompressedSize = 0;


NTSTATUS Status = SmbCompressionDecompress(
    Header->CompressionAlgorithm,
    (PUCHAR)Header + sizeof(COMPRESSION_TRANSFORM_HEADER) + Header->Offset,
    (ULONG)(TotalSize - sizeof(COMPRESSION_TRANSFORM_HEADER) - Header->Offset),
    (PUCHAR)Alloc->UserBuffer + Header->Offset,
    Header->OriginalCompressedSegmentSize,
    &FinalCompressedSize);
if (Status < 0 || FinalCompressedSize != Header->OriginalCompressedSegmentSize) {
    SrvNetFreeBuffer(Alloc);
    return STATUS_BAD_DATA;
}


if (Header->Offset > 0) {
    memcpy(
        Alloc->UserBuffer,
        (PUCHAR)Header + sizeof(COMPRESSION_TRANSFORM_HEADER),
        Header->Offset);
}


Srv2ReplaceReceiveBuffer(some_session_handle, Alloc);
return STATUS_SUCCESS;

}
```

Srv2DecompressData函数会接受客户端发送的压缩消息,分配必要数量的内存,然后将数据解压缩。如果Offset 域不等于0,就复制位于压缩数据之前部分的数据到分配的缓存的开始位置。

image.png

SMBGhost漏洞产生的原因是由于缺乏整数溢出检查。微软已经发布了安全补丁来修复该漏洞。

假的OriginalCompressedSegmentSize

之前,研究人员就通过设置OriginalCompressedSegmentSize 域为一个很大的数导致越界写后整数溢出来利用SMBGhost漏洞。如果将该值设置的笔真实的解压缩数据大一点会怎么样呢?如果,压缩数据解压缩后的大小为x,那么就把OriginalCompressedSegmentSize 设置为x + 0x1000,会发现:

image.png

未初始化的kernel数据会被认为是发送的消息的与部分。
if (Status < 0 || FinalCompressedSize != Header->OriginalCompressedSegmentSize) {
SrvNetFreeBuffer(Alloc);
return STATUS_BAD_DATA;
}

在本例中,假设OriginalCompressedSegmentSize域的值为x + 0x1000FinalCompressedSize就是x。事实上,由于SmbCompressionDecompress函数会导致FinalCompressedSize的值为x + 0x1000
```
NTSTATUS SmbCompressionDecompress(
USHORT CompressionAlgorithm,
PUCHAR UncompressedBuffer,
ULONG UncompressedBufferSize,
PUCHAR CompressedBuffer,
ULONG CompressedBufferSize,
PULONG FinalCompressedSize)
{
// ...

NTSTATUS Status = RtlDecompressBufferEx2(
    ...,
    FinalUncompressedSize,
    ...);
if (status >= 0) {
    *FinalCompressedSize = CompressedBufferSize;
}

// ...

return Status;

}
``
成功解压缩后,
FinalCompressedSize就会更新为CompressedBufferSize `的值,也就是缓存的大小。

漏洞利用

研究人员用来证明该漏洞的SMB消息是SMB2 WRITE消息。消息结构中含有要写入的字节、flag和可变长度缓存等域。要利用该漏洞,研究人员首先伪造了一个可以指定header的消息,可变长度缓存中含有未初始化的数据:
// HACK: fake size
if (((Smb2SinglePacket)packet).Header.Command == Smb2Command.WRITE)
{
((Smb2WriteRequestPacket)packet).PayLoad.Length += 0x1000;
compressedPacket.Header.OriginalCompressedSegmentSize += 0x1000;
}

注:研究人员给出的POC需要凭证和可写的共享,但该漏洞可以应用于每个消息,所有可能会在未经认证的情况下被利用。而且泄露的内存是在NonPagedPoolNx pool中分配的,因为可以控制分配的大小,所以也就可以控制泄露的数据程度。

SMBleed POC源码参见:

https://github.com/ZecOps/CVE-2020-1206-POC

受影响的系统

Windows 10 v1903、1909、2004 都受到该漏洞的影响。在测试过程中,PoC使其中一个Windows 10 1903机器奔溃了。研究人员在分析奔溃的原因时发现,早期的Windows 10 1903 补丁在处理有效的压缩的SMB包时存在空指针引用的问题。
未修复的系统中,存在空指针引用的问题:

image.png

修复后,加入了空指针检查:

image.png

受影响的系统汇总表如下所示:

image.png

SMBleedingGhost

攻击者利用SMBleed漏洞和SMBGhost漏洞可以实现远程代码执行。SMBGhost + SMBleed RCE POC源码参见:https://github.com/ZecOps/CVE-2020-1206-POC

https://blog.zecops.com/vulnerabilities/smbleedingghost-writeup-chaining-smbleed-cve-2020-1206-with-smbghost/

相关推荐: CBC字节翻转攻击

前言 bash 1、在ECB模式的基础上,增强了块与块之间的联系。 2、明文块先与IV XOR运算后,在进行加密,得到的密文充当下一个明文区块的IV... 3、明文块填充方式,如果明文为abcd,长度为4,则需要填充12位,12的十六进制为x0C,在最后加密的…