标题 | 简介 | 类型 | 公开时间 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
详情 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[SAFE-ID: JIWO-2025-2876] 作者: 闲云野鸡 发表于: [2021-04-30]
本文共 [407] 位读者顶过
0x01 背景随着Windows平台的几大主流浏览器(Chrome, Edge, IE)和文字处理软件(Office, Adobe Reader)相继引入沙箱机制,Windows内核提权漏洞的需求也随之上升。在这个背景下,近几年披露的Windows内核提权0day攻击事件也居于高位。下表展示了2017年-2021年(至今)全球范围内披露的Windows内核提权在野0day编号及对应的披露厂商,从表中可以直观地感受到上述现象。 [出自:jiwo.org]
这些Windows内核提权零日漏洞成本高昂,因此其背后一般都是水平高超或实力雄厚的APT组织。对威胁情报部门来说,如何有效狩猎这些在野的Windows内核提权漏洞样本已经变为一个需要深入思考的问题。 关于这个问题,Kaspersky作为Windows内核提权0day狩猎方面的先行者,已经公开分享过一些他们在这方面的经验;CheckPoint在最近半年也分享了3篇关于内核提权样本狩猎的研究文章,非常值得学习(对这些资料的引用将会列举在本文的最后,供读者参考)。 本文将分享安恒威胁情报中心猎影实验室在这方面的一些思考,讨论侧重点为内存破坏类内核提权漏洞,这一块我们尚处在摸索阶段,不足之处敬请斧正。
0x02 内存破坏类内核提权漏洞内存破坏类内核提权漏洞一般由C/C++语言的不安全操作引发,最为常见的是win32k组件中由于Callback机制导致的UAF漏洞。 为什么win32k组件容易出问题?为什么win32k组件中的UAF漏洞这么多?这要从Windows NT的设计历史说起。在Windows操作系统设计初期,win32k子系统是在用户态的(实线的上半部分),如下: 但从Windows NT4开始,这部分代码被移到了内核态(实线的下半部分),内核态新增了一个win32k.sys模块: 上述重新设计引入了如下3个不安全因素:
重新设计后,上述3点都可能引发新的安全漏洞,Windows内核团队也意识到了这几点,所以针对性地进行了加固,但安全研究人员还是不断从中找出安全漏洞。 在2011年Blackhat USA大会上,Tarjei Mandt公开了他对Win32k User-Mode Callback机制的研究成果,从此大量研究人员开始关注win32k模块中的User-Mode Callback攻击面,并发现了许多新的win32k模块UAF漏洞。
0x03 如何狩猎内核提权利用样本有过漏洞研究基础的同学都知道,一个典型的漏洞利用过程大概有这几个环节:
我们可以从上述每一个阶段入手,分别思考一下每一阶段潜在的一些狩猎点。 触发漏洞阶段静态层面,首先,我们可以检查PE文件的导入表中是否导入了user32.dll中的下面几个函数,因为大部分win32k漏洞利用都需要创建窗口或菜单:
其次,Win32k User-Mode Callback漏洞一定存在Hook回调表的操作,这是一个可疑行为(64位样本会存在和下面很像的一个代码片段): mov rax, gs:[60h] lea rax, [rax+58h] mov rax, [rax] ret 动态层面,对于UAF漏洞和部分越界读写漏洞,可以通过开启Driver Virifier进行检测,UAF漏洞样本在开启Driver Virifier的环境中会触发蓝屏异常,判定0day最简单的标准就是:
当然,有一些内存破坏类内核提权漏洞无法通过Driver Virifier检测到,一个典型例子就是我们捕获的CVE-2021-1732。 堆喷射阶段(非必须)堆喷射阶段变化比较多,可以创建多个Windows或多个Bitmaps,例如CVE-2018-8453的在野利用;也可以创建多个加速表(CreateAcceleratorTable),例如CVE-2017-8465的开源利用代码;也可以创建多个tagCLS结构,比如《LPE vulnerabilities exploitation on Windows 10 Anniversary Update》这个PPT第36页提出的方法。 信息泄露阶段关于Windows内核信息泄露技巧,Github上有一个项目(项目地址列举在文末)总结得较为完整。项目中有一张表格,该表格详细列出了Windows内核信息泄露的各种技巧,并且通过不同的图标展示了这些技巧在各版本Windows操作系统中的可用性。 这张表格只将操作系统写到Windows 1703(Redstone 2),但仅根据表格内信息我们也可发现:只有HMValidateHandle这一技巧一直稳定存在(从1803开始也进行了缓解)。 静态层面,我们可以通过查找HMValidateHandle的代码特征来发现内核信息泄露的线索。以下是一段查找HMValidateHandle的典型代码,如果在静态分析时遇到类似代码片段,就应值得留意: PVOID find_HMValidateHandle(PVOID pIsMenu)
{ ULONG HMValidateHandleAddr = 0; while (TRUE)
{ if (*(BYTE*)pIsMenu == 0xE8)
{ HMValidateHandleAddr = *(DWORD*)((ULONG)pIsMenu + 1); HMValidateHandleAddr += (ULONG)pIsMenu + 0x05 - 0x100000000; return (PVOID)HMValidateHandleAddr;
} pIsMenu = (BYTE*)pIsMenu + 1;
} return 0;
}
动态分析层面,由于HMValidateHandle是一个未导出函数,系统在正常调用这个函数时,对其调用的地址来自user32.dll内部;但当这个函数被用于信息泄露时,对其调用的地址位于漏洞利用模块,这个地址并不位于user32.dll模块。我们可以借助这一原理进行运行时检测:将来自user32.dll外的对HMValidateHandle的调用标记为可疑行为并记录。这方面已经有国外的研究员做了样例,一并列举在文末。 构造读写原语阶段在Windows内核利用的历史中,相继有操作tagWND,Bitmap,Palette,Menu等相关结构体的API登场,发展到现在,已经公开且还没有被完全缓解的任意地址读写原语辅助函数已经只剩SetWindowLong*系列函数和Menu相关函数,所以查看导入表中是否有user32.dll中的下面几个函数是一种思路:
除了上述API,早期版本的一些利用代码还可以包括下面这些导入函数:
代码执行阶段对于Windows内核提权漏洞而言,其主要目的是为了提升权限,而提升权限的主要手法就是进行Token替换,因此可以通过以下几个特征点进行检查:
0x04 Windows内核漏洞利用攻防史Windows内核团队和漏洞缓解团队一直致力于减少Windows内核的漏洞&利用攻击面,简单了解Windows系统中的内核安全攻防时间线有助于我们对Windows内核利用历史的了解和对Windows内核利用趋势的预测,这些对狩猎都有帮助。 Windows 7
Windows 8.1
Windows 10 1607 (Redstone 1)
Windows 10 1703 (Redstone 2)
Windows 10 1709 (Redstone 3)
Windows 10 1803 (Redstone 4)
Windows 10 1809 (Redstone 5)
Windows 10 1903
0x05 主流浏览器与win32k漏洞的攻防史Chrome/Edge(Chromium-based)
Edge(Chakra)
0x06 Windows内核提权漏洞趋势预测
|