引言
当今许多漏洞分析文章都聚焦于软件漏洞的利用过程。“漏洞利用开发者"一词仍与漏洞研究同义使用,这可能源于2000年代初期,当时漏洞易于发现,社区刚开始探索利用艺术。然而如今随着SDL和持续模糊测试的普及,在关键系统中发现未知漏洞变得越来越重要,甚至可以说比利用过程更为关键。
起点
2024年初加入STAR Labs时,我们的老板就让我们专注于准备Pwn2Own 2024。在众多潜在目标中,cimfs.sys(复合映像文件系统驱动)脱颖而出。这个驱动是Windows 11默认安装的一部分,当时没有任何已知漏洞,这使其成为一个有趣但高风险的研究目标。
认证绕过
该控制设备对象的安全描述符限制仅管理员可访问:
|
|
然而设备创建时未设置FILE_DEVICE_SECURE_OPEN标志,允许非特权用户通过将其视为文件系统驱动器来打开句柄并向控制设备发送IOCTL。
挂载操作
通过逆向分析配套DLL cimfs.dll,我们恢复了手动调用挂载的参数:
|
|
挂载期间,cimfs.sys:
- 使用Cim::ImageReader::*函数从区域文件提取元数据
- 在\Device\cimfs\下创建新磁盘设备
- 创建新卷设备
- 在每个设备的DeviceExtension中存储元数据
攻击计划
区域文件是存储在单个文件中的复杂文件系统,支持许多NTFS操作,如交替数据流(ADS)、硬链接、安全描述符、属性、重解析数据、扩展属性(EA)等。
我们编写了自定义模糊测试器向驱动投递测试用例,使用挂载操作作为验证器,任何导致挂载失败的突变都会被丢弃。成功挂载后,通过调用Win32 API来执行解析代码。
模糊测试结果
简单的模糊测试在几小时内就产生了许多崩溃,后来我们将其分组为7个独特漏洞,影响范围从拒绝服务到信息泄露再到代码执行。
漏洞分析
我们最终利用的漏洞是OOBR1,一个越界读取漏洞。崩溃上下文显示该漏洞通过ReadFile()调用触发,目标是隐藏存档文件的硬链接的交替数据流。
在Cim::FileSystem::GetDataSegment()函数中,当(*((_BYTE *)a2 + 0x77) & 1) != 0时,函数会立即返回成功,而不对偏移进行任何检查。这个字节同样源自区域文件,通过此检查,我们可以让函数返回完全受用户控制的未验证偏移。
漏洞利用
通过控制IoGetRelatedDeviceObject()在分页池中对相邻分配进行操作,我们可以伪造内核内存中的文件对象,然后将其地址喷洒到分页池中。当IoGetRelatedDeviceObject()对此地址操作时,将操作我们的伪造文件对象,返回伪造设备对象供IofCallDriver()调用。
我们使用_WNF_STATE_DATA对象来容纳伪造文件对象,并喷洒文件对象地址。通过NtUpdateWnfStateData(),我们可以在分配块后修改其内容,这对于利用至关重要。
最终,我们获得了任意调用原语,通过调用解引用函数如DirectComposition::CSharedResourceMarshaler::ReleaseAllReferences()来获得任意零原语,通过清零线程的PreviousMode字段获得完全任意读写能力。
结论
在漏洞挖掘领域,找到好目标(新攻击面)总是比盲目跳入目标更有效。不要害怕研究之前没有已知漏洞的目标。在手动审计时,考虑在后台运行简单的模糊测试会话。结合手动和自动化测试以达到最佳效果。