CVE-2022-24481是发生在CLFS驱动中的一个类型混淆漏洞,通过精巧的对blf文件的部分数据进行构造,可使LogBlockHeader中的ClientContextOffset指向ContainContext,从而造成类型混淆。
-
POC:4c1579c6a14bb8f3985be8a1a83c731c
-
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
CLFS即通用日志文件系统是在 Windows
Vista 和 Windows Server 2003 R2 中为实现高性能而引入的日志框架,它负责提供一个高性能、通用的日志文件子系统,供专用客户端应用程序使用,提供 API 函数来创建、存储和读取日志数据。并且多个客户端可以共享以优化日志访问。CLFS驱动本质上的作用就是对BLF 日志进行格式解析及处理。
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
BLF日志的格式如上图所示,每个日志块都以一个名为_CLFS_LOG_BLOCK_HEADER的结构开始:
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
Checksum(0xC)字段是该Log文件的CRC校验和,在对Log文件进行编码/解码操作时都需要对文件进行校验,通常在CLFS漏洞利用实现过程中都需要绕过CRC校验。
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
RecordOffsets(0x28)是日志块内记录的偏移量数组。
CLFS
只处理指向 _CLFS_LOG_BLOCK_HEADER末尾的第一个记录偏移量 (0x70)。当基本日志文件存储在磁盘上时,必须对其日志块进行编码。
基本日志记录存储用于将基本日志文件与容器相关联的元数据。其结构如下:
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
rgClients(0x1a8)和rgContainers(0x398)字段分别是存储着ClientContext和ContainerContex偏移值的数组。
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
pContainer(0x18) 实际上包含一个内核指针, 指向在运行时描述容器的类CClfsContainer。当Log文件在磁盘上时,该字段必须设置为零
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
获取ClientContext/ContainerContext的函数分别是CClfsBaseFile::AcquireClientContext及CClfsBaseFile::AcquireContainerContext,大致流程均是先通过CClfsBaseFile::GetBaseLogRecord获取基本日志块的地址,然后通过GetSymbol函数通过偏移找到对应的Context结构
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
CVE-2022-24481漏洞原因在于CClfsBaseFile::GetSymbol获取ClientContext时对其字段的校验不够严格,攻击者进行精巧的数据布局后使rgClients的偏移指向ContainerContext
-
为Log文件添加容器,以便 BaseLogRecord中拥有ContainerContext。
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
-
成功创建Log文件并为其添加容器后,BaseLogRecord 0x1368和0x1528的偏移处分别存储着ClientContext和ContainerContext
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
数据构造的目的是为了绕过CLFS在解析Log文件对context的校验。
第一部分绕过Log文件的crc校验。Log文件的BaseLogRecord在进行编码和解码都会进行CRC校验。
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
在触发过程中,为绕过CLFS对Checksum字段的检查,需要自己实现一次CRC校验并将结果填充至Checksum(0xc)
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
第二部分,对ClientCotext的数据进行修改,使其能够成功的绕过CLFS的检查最后指向ContainerContext。
首先,更新_CLFS_LOG_BLOCK_HEADER中 rgClients(0x1a8)字段,使rgClients存储的偏移值变为0x1520(ContainerContext offset为0x1528)
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
然后在0x1510及0x1514偏移处分别存储ClientContext新的起始偏移地址(0x1520)以及ClientContext的结尾偏移地址(0x1520+size(0x88)。
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
构造这两处值是为了绕过在CClfsBaseFile::GetSymbol函数中的相关检查,以使CLFS在调用
CClfsBaseFile::AcquireClientContext能够成功获取ClientContext。
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
完成以上步骤之后,rgClients已成功指向ContainerContext。
漏洞成功触发之后,下一步就是要实现提权利用,对于此漏洞我们需要重点关注以下两个点:
-
借助ClientContext对ContainerContext的修改能力
-
ContainerContext中pContainer(可将其指向R3内存)
-
成功利用该漏洞前提就是能够控制pContainer指向的值,第一步就是通过ClientContext修改ContainerContext->pContainer的值。由于为Log文件添加容器之后,需要再次调用CreateLogFile对BaseLogRecord进行一次初始化更新
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
将ClientContext中的数据保存到CclfsLogFcbPhysical类中,此处重点关注rcx+20h处的值,现存储着我们pContainer的目标值(r3可控地址0x40000000)
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
随后会调用CClfsBaseFilePersisted::LoadContainerQ函数加载Container并更新pContainer,让其指向在运行时描述容器的类CclfsContainer
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
CclfsContainer类的前8个字节指向虚表
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
此时pContainer还是指向内核的CclfsContainer类,我们的可控地址0x40000000被保存到了CclfsLogFcbPhysical类的0x1a0处,经过分析发现,在close Log文件句柄过程中,CLFS会调用CClfsLogFcbPhysical::FlushMetadata对ClientContext进行更新
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
实际上就是将存储在CclfsLogFcbPhysical类中的数据重新写回到ClientContext
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
由于ClientContext指向ContainerContext-0x8,这里将0x40000000赋给ClientContext+0x20就是修改ContainerContext+0x18(pContainer)为0x0x40000000
-
执行CloseHandle时,内核中首先会将当前线程的previousMode修改为内核态(0)
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
待到成功执行完返回R3前,又会将当前线程的previousMode修改为用户态(1)
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
此漏洞的提权原理就是在返回R3前,修改当前线程的previousMode为0,下图为我们自定义构造由pContainer指向的” CclfsContainer”
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
0x0为“虚表指针“,0x20为文件句柄,0x30为previousMode+0x30 address
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
漏洞利用是发生在CClfsLogFcbPhysical::CloseContainers函数中
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
在CClfsLogFcbPhysical::CloseContainers首先通过ContainerContext获取到pContainer,然后对CclfsContainer类进行一个清理释放。这里我们拥有一个可控函数的执行!
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
随后调用ObfDereferenceObjectWithTag传入的参数为previousMode+0x30,并利用该函数的减数机制,将previousMode修改为0(内核态)
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
最后,调用可控函数ClfsSetEndOfLog返回错误码到R3
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
在提权样本中,利用当前线程的内核执行能力将当前线程的token替换为system token
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
Token替换之后,在将previousMode改回1(目的是混淆)
![原创 | CVE-2022-24481 原创 | CVE-2022-24481]()
原文始发于微信公众号(SecIN技术平台):原创 | CVE-2022-24481
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
点赞
http://cn-sec.com/archives/1890940.html
复制链接
复制链接
-
左青龙
- 微信扫一扫
-
-
右白虎
- 微信扫一扫
-
评论