关于大火的Print Spooler漏洞的深度分析

  • Comments Off on 关于大火的Print Spooler漏洞的深度分析
  • 12 views
  • A+

本篇文章几天之前就整理好了,一直没有时间整理,往平台上发。

前言

前一段时间,Windows Print SpoolerCVE-2021-1675CVE-2021-34527两个洞被炒的沸沸扬扬。漏洞的利用姿势也是越来越多样,由刚开始的本地提权演变为后来的远程RCE。本篇文章是我在复现这两个漏洞时,引发的一些思考。

祸不单行,16日PrintNightmare系统出现了第3枚0day,属于本地提权漏洞。

wKg0C2D8AiaAB7fYAAB8uFYXoJQ631.png

意外发现

网上关于这两个漏洞的细节分析已经非常详尽,下面简单介绍一下这两个漏洞的成因以及时间线。2021年6月8日,微软官方修复了一个存在于打印机服务Windows Print Spooler中的高危漏洞(CVE-2021-1675,下文简称为1675)。1675的漏洞成因在于AddPrinterDriverEx()中,函数逻辑校验不严格,利用该漏洞,攻击者可以将普通用户权限提升至System权限。之后,微软紧急发布补丁对该漏洞进行修复。但CVE-2021-34527绕过了微软的这个修复,34527使用到了另一个打印服务的API:RpcAsyncAddPrinterDriver,该函数同样存在校验不严格的问题,是一个严重的远程代码执行漏洞。

在漏洞复现过程中,发现了一个有趣的现象。用Process Monitor工具对攻击payload行为进行分析。如下图所示,spoolsv进程将恶意的MyPigDLL.dll文件写入了C:WindowsSystem32spooldriversx643目录下。同时,spoolsv进程向”HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlPrintEnvi ronmentsWindows x64DriverslVersion-3”注册表路径下添加注册表项(打印机程序在安装新的驱动过程中会修改此注册表,实现驱动的注册安装)。

wKg0C2D8Aw6AcEhtAAAzSTm8UBE127.png

wKg0C2D8AxaAJQGoAAC3pFRpPwQ294.png

wKg0C2D8A4KAORqLAADZAWYh7WE950.png

在注册表编辑器中找到该项,可以看到普通用户只有读取权限,并没有写入权限。C:WindowsSystem32更是如此,普通用户没有权限向特权目录下拷贝文件。但是注册表确实被修改了,文件也拷贝成功了。这不由得引发了我的思考,当远程用户登录域控服务器时,调用spoolsv进程时,可能并没有没有模拟用户身份(token),用的是系统system权限。

wKg0C2D8ACAHXZgAABBOxPBYU123.png

为了验证我的想法,我在windows server2019上挂上windbg进行双机调试。用攻击机kali运行payload去攻击有漏洞的server 2019主机。

通过查看堆栈,找到创建注册表键值的函数,下断即可。

wKg0C2D8BMaAPtXgAACuxLHuvgk877.png

因为windbg是断在ring 0中,而spoolsv进程是ring 3的进程。所以我们还需要进行用户态进程切换。调试所用命令如下:

!process 0 0

.process /r /p addr

ba e1 addr(断点只能下内存断点,否则断不行)

!token查看token

需要注意的是,由于调试环境属于双机调试,而不是直接attach的spoolsv进程。在下断点时,需要下内存断点,否则函数断不下来。

真相大白

查看调用RegCreateKeyExW()函数时的令牌,可以看到当域内低权限用户使用域控上打印机设备时,spoolsv进程并没有使用模拟token,而且直接使用了process token。而spoolsv进程本身权限是非常高的,S-1-5-18是SYSTEM账户的SID。

wKg0C2D8BOCAVL7oAABymHkhSn8551.png

这也是为什么打印机容易爆出本地提权或者远程RCE的根本原因。spoolsv进程可以通过网络访问(域内普通账户即可访问),并且默认为system权限,如果不能正确处理client端发送过来的请求,很容易造成越权攻击,成为众矢之的。特别是在域内进行横向渗透时,简直不要太好用。

我们通过微软针对1675和34527打的补丁措施中也能印证这一点。说白了就是增加校验机制,来限制普通账户通过spoolsv进程进行特权操作。1675的补丁是在RpcAddPrinterDriverEx中,补丁增加了YIsInAdministratorGroup函数来判断当前用户是否在Administrator组中。34527补丁进一步增加了对于权限的校验,当YIsElevationReuqred函数返回True时,同样会清除flag中的APD_INSTALL_WARNED_DRIVER项。补丁详细分析可见https://blog.csdn.net/smellycat000/article/details/118561321

在1675和34527漏洞之前,spoolsv进程还出过一次糗事,以至于微软连续发布了三个补丁才将此漏洞进行修复。

前世今生

CVE-2020-1048

微软在2020年5月份发布补丁,用于修复存在于打印机中一个本地权限提升漏洞。之后的CVE-2020-1337和CVE-2020-17001都是对该漏洞补丁的绕过。该漏洞可以绕过在windows下添加打印机设备时,对port name检查,可以将任意内容输出到特权目录下,实现权限提升(例如dll劫持)。下面详细介绍一个这个漏洞成因。

微软为了方便低权限用户使用打印机服务,允许用户添加打印机驱动。添加完打印机驱动后,还需要设置打印机的端口。漏洞点就在此处,Windows支持多种类型的打印机端口:LPT1端口、USB端口、网络端口和文件等。若是设置端口为文件,则意味着打印机将数据打印到指定文件。我们可以把端口名设置为特权目录文件路径(如c:windowssystem32),造成任意目录文件写入。但是微软对此是有限制措施的,正常情况下,调用spoolsv进程时会校验用户权限(模拟token),如果低权限用户向特权目录写入时,会出错。

但是Printer Spooler服务程序在重启后,会以system权限去恢复未执行的打印作业,使得攻击者具有了System权限的任意文件写入能力。重启打印机服务可以通过两种渠道:1.直接重启打印机服务,但是需要高权限才能执行。2.重启主机即可。

wKg0C2D9BV6AUVdoAABoYKOjxvw640.png

下面进行攻击演示。演示所用POC链接均已放置在文末。

切换到低权限账户,执行CVE利用程序

wKg0C2D9BlmAaqK1AABDPIvBCk064.png

可以看到打印机队列出现一个错误。

wKg0C2D9BoeAasU1AAB5DuSYcwk092.png

我们可以重启打印机服务或者重启电脑来重启打印机服务,错误的任务被执行,dll被成功写入。

wKg0C2D9BrqAN9n5AAA0bPWhLk0876.png

CVE-2020-1337

之后微软对1048漏洞进行了修复,增加了对创建port时的判断逻辑。增添了IsValidNamedPipeOrCustomPortPortIsValid来进行判断,但仍可以进行绕过。

IsValidNamedPipeOrCustomPort检测该port是否为命名管道,且是否可以通过createfile打开,如果不是命名管道,则会检测port中是否包含/字符。PortIsValid则判断这个port是否合法,并通过创建port的文件句柄来检测是否拥有读写权限。两个函数只需有一个函数返回为ture,仍可成功创建port。我们以PortIsValid函数为突破点。我们通过创建junction(软链接)来进行绕过,在创建port时正常传入具有读写权限的路径,创建打印机后删除该目录,通过目录链接的方式,将此目录与system32目录进行链接。重启打印机后,仍会指向system32路径。

实际上,微软关于junction的漏洞非常多,如cve-2020-0787,cve-2019-1315等等。

下面进行攻击展示。攻击分为两步,第一步init阶段正常创建打印机设备,添加端口,并通过SetPrinter函数将打印机设置为PAUSE状态。

wKg0C2D9CluAT4guAAA0HclzvIk029.png

重启主机后,创建软链接,绑定system32目录。恢复Printer Spooler服务状态,进行漏洞利用。

wKg0C2D9CjOAVrMUAAA6zYqFA0I723.png

CVE-2020-17001

微软添加了IsPortAlink函数,其中通过GetFinalPathNameByHandleW返回文件的真实路径,与port路径进行对比,来检测junction。但是GetFinalPathNameByHandleW对UNC链接的路径处理时逻辑不严格,函数返回的真实路径只是简单的在其前面增加了?UNC的前缀,并不会将其真正对应的link链接返回。所以我们将port的路径进行精心构造如\localhostc$testgetshell.dll的形式即可进行绕过。

wKg0C2D9G3WAMvI6AAA2mhLXg8I845.png

此时,微软头疼不已,直接在重启打印机后,执行任务队列时增加了函数IsSpoolerImpersonating,检测当前进程权限是否正确合法。这才算上真正修复了这一系列漏洞。

如果从防御方角度来看的话,可以增加一个注册表回调,监控路径

HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionPorts,当写入的端口含有文件路径时,特别是.dll或者以.asp,.vbs这些可执行脚本文件后缀时,弹窗提醒。

wKg0C2D9H1SAFJ8MAABP7wZFFQ480.png

危害升级

前面对漏洞进行了分析,漏洞危害主要在于可以向任意特权目录写入文件,我们如何在实战中进行漏洞利用呢。最直接的方式就是进行dll劫持。在打印机spoolsv服务或者fax服务重启过程中,会加载c:\system32ualapi.dll。更准确的说是调用uapapi.dll的导出函数UalStart。我们可以通过替换该dll,实施恶意攻击。

wKg0C2D9IfSAKO7jAABpYj5pbhY978.png

github有一个开源的faxhell项目,是一个编译好的dll文件,用于fax服务的dll劫持(spoolsv服务同理)。功能是绑定一个正向的shell等待服务端进行连接,并通过替换RpcSs的token,达到提权的目的。强烈建议大家阅读dll的源代码,特别是对线程池的操作,叹为观止。

wKg0C2D9IeCAVIbNAADXGCCeNk120.png

wKg0C2D9If2AN3dKAABEjWvF8431.png

参考链接:

1.https://blog.csdn.net/smellycat000/article/details/118561321

2.https://www.anquanke.com/post/id/222730

3.https://www.cnblogs.com/goabout2/p/13971925.html

https://baijiahao.baidu.com/s?id=1674337103792495789&wfr=spider&for=pc

Poc

https://github.com/neofito/CVE-2020-1337

https://github.com/Ken-Abruzzi/CVE-2020-1048

https://github.com/ionescu007/faxhell

https://bbs.pediy.com/thread-261557.htm

相关推荐: java安全-java类加载器

前言 java类加载器是JVM加载类到内存并运行的过程,这个过程有点复杂,除了系统自定义的三类加载器外,java运行用户编写自定义加载器来完成类的加载过程。java安全中常常需要远程加载恶意类文件来完成漏洞的利用,所以学习类加载器的编写也是很重要的。 类加载器…