作者:红雨滴团队
原文链接:https://mp.weixin.qq.com/s/6mT0O9eur5-VEs0rbV0-mg

概述

APT 攻击(Advanced Persistend Thread,高级持续性威胁)是利用先进的攻击手段对特定的目标进行长期持续性网络攻击的攻击形式。APT 攻击形式相对于其他攻击形式更为高级和先进,其高级性主要体现在精准的信息收集、高度的隐蔽性以及针对于各种复杂系统或应用程序的漏洞利用等方面。

为了更加全面的理解漏洞在APT 攻击中所扮演的角色。奇安信威胁情报中心红雨滴团队聚焦于部分真实APT 攻击活动中所使用的各类Windows系统本地提权漏洞,简要分析这些漏洞原理、利用方式。

在本报告中,奇安信威胁情报中心会以Windows权限提升漏洞作为论述主体,通过研究这些提权漏洞在APT 攻击活动中所扮演的角色并对漏洞威胁性做出简单评定。

最后,基于之前章节的分析和阐述,我们针对APT 组织使用漏洞发展趋势进行总结并提出一些预防建议。由于所涉及到的APT 攻击活动数量较多,且所涉及的APT 活动中使用的提权漏洞也存在一定的重复性,所以本报告以其中影响较大、知名度较高的几次攻击事件为例进行分析介绍。

漏洞、CVE以及本地提权漏洞(LPE)

漏洞通常指计算机系统安全方面的缺陷,使得系统或其他应用数据的保密性、完整性、可用性、访问控制等方面面临威胁。这里的计算机系统既包括软件系统如操作系统、应用软件,又包括硬件。本文所指系统特指Windows 操作系统。

CVE 是通用漏洞披露(Common Vulnerabilities and Exposures)的简写,是指代已经公开披露的各种计算机安全漏洞,由 MITRE corporation 监管。我们通常谈论的CVE 指的是分配给每个安全漏洞的CVE ID 编号,该变化由CAN(CVE 编号管理机构分配)。本文提及漏洞皆存在对应的CVE 记录。

而计算机安全漏洞主要分为拒绝服务、代码执行、内存溢出、特权获取、信息泄露、SQL 注入等等,本文着重描述Windows权限提升漏洞,也即本地提权漏洞(Local privilege escalation,简称LPE)。

01

摩诃草APT组织以巴基斯坦空军演习为诱饵展开攻击活动

相关活动概要

摩诃草APT组织(APT-C-09)在2021年1月左右以巴基斯坦空军演习为诱饵文档发起的攻击活动中,通过恶意文档释放FakeJLI后门,尝试在特殊目录下创建文件并删除以检查是否处于office沙箱保护模式下,并根据判断结果选择是否进行提权操作。

如果当前恶意进程属于WOW64进程,则使用CVE-2016-7255进行提权,反之则使用CVE-2019-0808 进行提权。以下是对两个漏洞的技术细节分析介绍。

CVE-2016-7255

漏洞概述

2016年12月2日,谷歌研究员在对Pawn Storm 间谍组织实施的攻击活动研究中发现了一个内核提权漏洞,并在披露漏洞后的短时间内微软发布系统安全更新。该漏洞被多个APT 组织在攻击活动中使用。

CVE-2016-7255 是由于win32k!xxxNextWindow 函数未对win32k!tagWND对象内成员有效性就行检测,导致可以构造内核空间任意地址写,最终实现本地提权。

漏洞原理

CVE-2016-7255 漏洞是由于内核函数win32k!xxxNextWindow 函数对win32k!tagWND 对象内成员有效性未做判断,导致攻击者可以利用恶意构造的对象实现对内核任意地址写入数据。

通过对比补丁前后的代码变化,可以发现在win32k!xxxNextWindow 函数的流程中,出现了一处对比代码的变化。

图片

通过对比补丁前后win32k.sys 文件的反编译版本可以发现这里主要增加了对于(_BYTE )(pwndActivateNext + 0x37) & 0xC0) != 0x40的参数验证。

图片

通过分析得知,此处的pwndActivateNext 是通过GetNextQueueWindow 函数返回,该函数原型如下。

图片

函数返回应该PWND 值,该值为tagWND 结构指针,通过前文中补丁对比可知,在函数win32k!xxxNextWindow 内会对该对象+0xC0 处的值进行校验,通过windbg 可知该处的成员为spmenu,是一个tagMENU 结构对象。由于未对该处的值有效性进行检测,导致此处的值可以通过SetWindowLongPtr 函数进行控制。

图片

漏洞利用

通过分析发现,该漏洞只能修改一位,而不能实现任意地址写入,所以利用对PML4的自引用地址的值进行与0x4 异或修改访问权限实现用户层对内核层的读写,之后通过覆盖haldispatchtable+offset处的代码为shellcode以实现劫持,最后调用NtQueryIntervalProfile 方法实现内核态shellcode 执行以替换当前进程TOKEN 为SYSTEM TOKEN 值实现提权。

CVE-2019-0808

漏洞概述

2019年3月7日,谷歌威胁分析小组披露了两个0-day 漏洞,其中包括CVE-2019-0808。据微软称,CVE-2019-0808 漏洞允许攻击者提升本地权限并在内核模式下执行任意代码。谷歌表示该漏洞只影响Windows 7 和Windows Server 2008 系统版本,同时该漏洞结合Chrome RCE(CVE-2019-5786)已经被应用于真实的APT攻击中。

CVE-2019-0808 产生的原因是在函数win32k!xxxMNFindWindowFromPoint 接收到窗口过程函数返回的菜单窗口对象后,对于win32!tagPOPUPMENU 对象成员未做有效性检测,导致可能存在对象成员为空的情况,进而导致在win32k!xxxMNUpdateDraggingInfo 函数内触发零指针解引用异常。

漏洞原理

通过目前网络上的资料不难知道,该漏洞产生的原因是win32k.sys 内部函数xxxMNFindWindowFromPoint对tagPOPUPMENU 对象成员有效性判断不足导致后续代码出现空指针解引用异常触发漏洞。通过在测试主机(windows 7 sp1)执行POC 文件触发Crash 并查看调用堆栈如下:

图片

不难看出当执行到win32k!xxxMNUpdateDraggingInfo+0x9e 处时,产生了异常,定位此处,发现是对rdx+0x34 处地址访问时产生。

图片

通过查看堆栈调用,触发漏洞的大致函数执行流程如下:

图片

通过以上的调试,基本知晓了POC 的编写逻辑及基本的漏洞成因。此处使用的POC 代码由ze0r 编写并开源于github。

通过分析POC 源码,可知漏洞触发流程大致如下:

第一步:创建两个菜单对象hMenuRoot 和hMenuSub 并将其设置为无模式,即当菜单处于活动状态时,无菜单模式消息循环。并且将hMenuRoot 设置为主下拉菜单,hMenuSub 设置为其子菜单。

第二步:设置上述菜单信息使之具有拖拽功能。

第三步:设置全局钩子消息以拦截WM_MN_FINDMENUWINDOWFROMPOINT 消息,该消息由xxxMNFindWindowFromPoint 函数发出。

第四步:通过调用NtUserMNDragOver 函数进入漏洞触发流程。

第五步:当进入到NtUserMNDragOver 函数内后,就开始上面图示的流程执行,程序流执行到win32k!xxxMNMouseMove 函数内,会调用win32k!xxxMNFindWindowsFromPoint 函数用于确定鼠标位于哪个窗口,在该函数内会发送MN_FINDMENUWINDOWFROMPOINT 消息事件,由于在第三步设置了全局钩子拦截该消息事件,所以程序流回到用户层代码会进入到HOOK 函数POC!WindowHookProc() 内,通过SetWindowsLongPtr 函数为菜单窗口设置一个新的窗口过程函数,并在函数内部返回我们构造的hWndFakeMenu。

第六步:在第五步执行完成后,xxxMNFindWindowFromPoint 函数获取窗口句柄并传入窗口对象xxxMNUpdateDraggingInfo内,但是此时的对象已经是我们伪造的hWndFakeMenu 对象,并且该对象多数成员值为0,造成代码异常。

通过上述对POC 的分析,可以将上面漏洞触发流程进一步细化为下图:

图片

漏洞利用

通过上述对漏洞产生原因及触发的调试,我们来看看该漏洞是如何进行利用的。由上述可知,该漏洞产生的原因是空指针解引用,所以利用该漏洞首先是解决空指针异常。在Windows 7 系统版本的计算机上,解决空指针异常可以使用NtAllocateVirtualMemory 函数来分配零页内存。

之后需要让程序执行流程进入到if 分支中,需要对零页地址数据进行构造。

图片

此处代码实际上是MNGetpItem 方法,该方法传入两个参数,分别是tagPOPUPMENU 结构指针和UINT 类型的索引值,该值为uDraggingIndex,表示当前正在拖动的项的索引值。通过资料查询,该值可以从tagMSG 的wParam 获取,所以我们可以在用户层设置此处的值。

将此处的值进行修改并进入到if 分支,通过分析后续流程,我们定位到xxxMNSetGapState 函数,在改函数内调用了类似于MNGetpItem 函数,在上述分析中可以知道该函数的返回值是可以由用户层控制的,所以利用这一点可以实现任意地址与下面的0x40000000 的值进行或运算。

图片

有了上述的基础,我们可以利用内核地址泄露和窗口对象喷射技术通过寻找两个内存位置相邻的对象,修改窗口对象附加长度的值为0x400000000,并再次修改第二个窗口对象的strName.Buffer 指针,最后设置strName 的方式实现任意地址写。

写入shellcode 后利用tagWND. bServerSideWindowProc字段置位实现窗口过程函数在内核模式下执行,实现提权。

https://msrc.microsoft.com/update-guide/vulnerability/CVE-2019-0808

https://paper.seebug.org/856/

https://ti.qianxin.com/blog/articles/Summary-and-analysis-of-APT-attack-activities-in-South-Asia-in-January-2021/

02

蔓灵花APT组织在针对国内攻击活动中使用Windoows内核提权0 day漏洞

相关活动概要

2020年12月中旬国内某安全厂商披露了蔓灵花(又名Bitter)针对国内科研机构、政府部门发起的APT 活动,并在此次分析中发现了一个使用未知Windows 内核提权漏洞进行本地提权的恶意组件。以下是对该漏洞的技术细节分析介绍。

CVE-2021-1732

漏洞概述

CVE-2021-1732于2021年2月蔓灵花针对国内科研机构及政府部门的攻击活动中首次被发现,该漏洞利用Windows 操作系统win32k 内核模块一处用户态回调干扰函数正常执行流程,并在可控流程内篡改窗口对象数据造成后续代码执行异常,从而触发漏洞。

漏洞原理

CVE-2021-1732 漏洞位于win32kfull.sys 内,当win32kfull! xxxCreateWindowEx 函数回调xxxClientAllocWindowsClassExtraBytes时进行干预,通过混淆console 窗口和普通窗口,使得回调函数返回内核态执行时触发内核对象越界访问。

正常情况下,窗口的创建过程如图所示:

图片

用户调用CreateWindowsEx 函数并逐步向下执行,通过系统调用机制由用户态进入内核态,并逐层向下,当窗口对象(atgWND)的扩展数据大小值为0时,win32kfull!xxxCreateWindowsEx 函数执行用户回调xxxClientAllocWindowsClassExtraBytes 函数为窗口对象扩展数据申请所需内存。

在完成回调后,返回值将传递给窗口对象的tagWND.pWxtraBytes 属性。但是由于对该值未作有效判定,导致攻击者可以通过特定函数(NtCallbackReturn)修改tagWND. pWxtraBytes 的值为可控的offset,并且在这之前通过调用NtUserConsoleControl 函数修改tagWND 的扩展数据保存方式为桌面堆,最终实现基于内核态桌面堆起始地址可控offset 的越界读写。

图片

通过上述描述,最终窗口创建的流程如下:

图片

漏洞利用

根据POC 可知,利用该漏洞可以实现将tagWND 对象的扩展数据设置为任意可控offset,从而获取指定的内核地址,通过SetWindowLong 函数实现对这些地址的数据修改;通过构建虚假的spmenu 对象配合SetWindowLong 修改指定tagWND 对象的spmenu 为虚假的spmenu再借助函数GetMenuBarInfo 实现任意地址读;最后通过内核地址泄露定位到EPROCESS 结构地址,并使用EPROCESS 链查找system 进程,获取system 进程token 并实现替换从而实现提权。

03

在针对中东地区的攻击活动中使用Windows内核提权漏洞

相关活动概要

CVE-2018-8453是卡巴斯基实验室于2018年8月份在一系列针对中东地区进行APT攻击的活动中捕获到的Windows提权0day漏洞,该漏洞与Windows窗口管理和图形设备接口相关(win32kfull.sys)。

通过控制窗口对象销毁时在xxxFreeWindow函数中回调fnDWORD的hook函数,可以在win32kfull!xxxSBTrackInit中实现对pSBTrack的UseAfterFree,从而进行提权。以下是对该漏洞的技术细节分析介绍。

CVE-2018-8453

漏洞概述

该漏洞产生的原因是win32kfull!NtUserSetWindowFNID函数存在缺陷:在对窗口对象设置FNID时没有检查窗口对象是否已经被释放,导致可以对一个已经被释放了的窗口(FNID_FREED:0x8000)设置一个新的FNID,通过利用win32kfull!NtUserSetWindowFNID的这一缺陷,从而可以达到UAF,导致漏洞的利用。

漏洞原理

POC流程如下:

图片

Hook KernelCallbackTable中的回调后,通过向滚动条发送WM_LBUTTONDOWN消息触发调用xxxSBTraackInit函数,因为对一个滚动条进行鼠标左击时,会触发调用win32kfull!xxxSBTrackInit函数,这里会调用xxxSBTrackLoop循环获取鼠标消息,直到释放鼠标左键或者收到其它消息,才会退出xxxSBTrackLoop函数。

xxxSBTrackInit中调用xxxSBTrackLoop回调fnDWORD_hook时,调用DestoryWindow(g_hMAINWND), 这样会导致调用win32kfull!xxxFreeWindow,因为我们在注册主窗口类的时候设置了主窗口类的cbWndExtra不为0,那么在win32kfull!xxxFreeWindow中会调用xxxClientFreeWindowClassExtraBytes函数来释放主窗口类的额外数据。

图片

上图这个函数会回调KernelCallbackTable[126],就会进入我们的第二个hook函数中去。

在进入第二个hook函数fnClientFreeWindowClassExtraBytesCallBack_hook后我们必须手动调用NtUserSetWindowFNID(g_hMAINWND,spec_fnid)设置主窗口的FNID(spec_fnid的取值范围从0x2A1到0x2AA,这里我们将spec_find设置为0x2A2即可)。同时申请一个新的滚动条:g_hSBWNDNew,并调用SetCapture(g_hSBWNDNew)设置当前线程捕获鼠标消息的窗口是g_hSBWNDNew。

图片

由于主窗口被Destory,那么xxxSBTrackLoop会返回,继续执行HMAssignmentUnLock(&pSBTrack->spwndNotify)解除对主窗口的引用。从而导致主窗口被彻底释放,这会导致再一次的调用xxxFreeWindow,当调用了xxxFreeWindow之后,窗口的FNID就会打上0x8000标记。

图片

当再次进入fnDWORD_hook函数时就是我们最后一次回到R3的时机了,这个时候如果调用SendMessage(g_hSBWNDNew,WM_CANCLEMODE) 就会调用xxxEndScroll来释放pSBTrack。

图片

由于POC程序是单线程,而每个线程信息是属于线程的,所以线程创建的所有窗口也都指向同一线程信息结构。即使SBTrack隶属的Scrollbar窗口已经释放了,只要还是同一线程创建的新窗口,pSBTrack也还是原来的。

由于我们是向新创建滚动条g_hSBWNDNew发送的WM_CANCLEMODE消息,且之前就调用SetCaputure(g_hSBWNDNew)设置当前线程捕获鼠标消息的窗口为g_hSBTWNDNew,所以qp->spwndCapture==pwnd也会满足。

因此上图中的if判断会通过,并最终执行UserFreePool(pSBTrack)将pSBTrack给释放掉,从而造成返回执行HMAssignmentUnLock(&pSBTrack->spwndSB)时,pSBTrack就已经被释放掉了。最终造成了对pSBTrack的Use After Free。

漏洞利用

由于我们可以通过hook KernelCallbackTable中的回调函数来控制win32kfull!xxxSBTrackInit中的pSBTrack被提前释放,造成对pSBTrack的Use After Free。之后则可以通过池风水喷射技术占用被提前释放掉的pSBTrack实现有限次的任意内存减1或减2。这个有限次的任意内存减1或减2配合桌面堆泄露技术和GDI Palette Abuse技术就可以实现任意内存读写。

总结

APT 攻击事件随着技术的发展也逐渐由早期单一化逐渐演变为目前的复杂化,而同时随着计算机软件系统安全防护技术的提升,软件漏洞开始成为APT 组织攻击活动中重要组成部分,在整个攻击活动中扮演着“突破者”的角色。之所以形容其为“突破者”,在于漏洞利用模块多为突破系统防护或沙箱最终实现对目标系统的攻击。

奇安信威胁情报中心收集整理了众多APT 攻击活动并从中例举了如“摩诃草”、“蔓灵花”等组织曾发起的攻击活动,分析这些攻击活动中所使用到的系统(Windows 系统)漏洞并简述其原理及利用,以求从另一个视角看待这些攻击:若漏洞不存在,攻击是否达成?

通过文章简述分析,我们清楚的看到这些漏洞在整个攻击事件中所扮演的重要角色,同时我们也应该认识到,及时的抹除这些漏洞即安装系统补丁对于避免这些攻击事件的重要性。

奇安信红雨滴团队呼吁相关用户,及时安装系统更新,并定期更新安全防护系统,能有效防止遭受此类攻击。

APT活动相关Windows提权漏洞附表

攻击活动 相关APT组织 涉及漏洞
“摩诃草”APT组织以巴基斯坦空军演习为诱饵展开攻击活动 摩诃草 CVE-2016-7255CVE-2019-0808
“蔓灵花”APT组织在针对国内攻击活动中使用Windoows内核提权0 day漏洞 蔓灵花 CVE-2021-1732
SandCat APT组织在实际攻击中使用最新Windows在野提权漏洞 SandCat CVE-2018-8589CVE-2019-0797
针对中东地区的Windows内核提权漏洞利用分析 CVE-2018-8453
APT31组织在实际攻击中使用CVE-2017-0005漏洞进行提权 APT31 CVE-2017-0005
APT28组织在实际攻击中使用CVE-2016-7255,CVE-2017-0263漏洞进行提权 APT28 CVE-2016-7255CVE-2017-0263
Turla组织在实际攻击中使用CVE-2017-0001漏洞进行提权 Turla CVE-2017-0001

参考链接

[1] https://nvd.nist.gov/vuln/detail/CVE-2016-7255

[2] https://doxygen.reactos.org/d8/d33/arch_2amd64_2winldr_8c.html

[3] https://ti.qianxin.com/blog/articles/Summary-and-analysis-of-APT-attack-activities-in-South-Asia-in-January-2021/

[4] https://www.mcafee.com/blogs/other-blogs/mcafee-labs/digging-windows-kernel-privilege-escalation-vulnerability-cve-2016-7255/

[5] https://www.sohu.com/a/211497788_764248

[6] https://ti.qianxin.com/blog/articles/cve-2018-8453-win32k-elevation-of-privilege-vulnerability-targeting-the-middle-east/


Paper 本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1753/