本篇文章几天之前就整理好了,一直没有时间整理,往平台上发。
前言
前一段时间,Windows Print Spooler
的CVE-2021-1675
和CVE-2021-34527
两个洞被炒的沸沸扬扬。漏洞的利用姿势也是越来越多样,由刚开始的本地提权演变为后来的远程RCE
。本篇文章是我在复现这两个漏洞时,引发的一些思考。
祸不单行,16日PrintNightmare
系统出现了第3枚0day
,属于本地提权漏洞。
意外发现
网上关于这两个漏洞的细节分析已经非常详尽,下面简单介绍一下这两个漏洞的成因以及时间线。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”
注册表路径下添加注册表项(打印机程序在安装新的驱动过程中会修改此注册表,实现驱动的注册安装)。
在注册表编辑器中找到该项,可以看到普通用户只有读取权限,并没有写入权限。C:WindowsSystem32
更是如此,普通用户没有权限向特权目录下拷贝文件。但是注册表确实被修改了,文件也拷贝成功了。这不由得引发了我的思考,当远程用户登录域控服务器时,调用spoolsv进程时,可能并没有没有模拟用户身份(token),用的是系统system
权限。
为了验证我的想法,我在windows server2019
上挂上windbg
进行双机调试。用攻击机kali运行payload去攻击有漏洞的server 2019主机。
通过查看堆栈,找到创建注册表键值的函数,下断即可。
因为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。
这也是为什么打印机容易爆出本地提权或者远程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.重启主机即可。
下面进行攻击演示。演示所用POC链接均已放置在文末。
切换到低权限账户,执行CVE利用程序
可以看到打印机队列出现一个错误。
我们可以重启打印机服务或者重启电脑来重启打印机服务,错误的任务被执行,dll被成功写入。
CVE-2020-1337
之后微软对1048漏洞进行了修复,增加了对创建port时的判断逻辑。增添了IsValidNamedPipeOrCustomPort
和PortIsValid
来进行判断,但仍可以进行绕过。
IsValidNamedPipeOrCustomPort
检测该port是否为命名管道,且是否可以通过createfile
打开,如果不是命名管道,则会检测port中是否包含和
/
字符。PortIsValid
则判断这个port
是否合法,并通过创建port
的文件句柄来检测是否拥有读写权限。两个函数只需有一个函数返回为ture,仍可成功创建port。我们以PortIsValid
函数为突破点。我们通过创建junction
(软链接)来进行绕过,在创建port时正常传入具有读写权限的路径,创建打印机后删除该目录,通过目录链接的方式,将此目录与system32目录进行链接。重启打印机后,仍会指向system32路径。
实际上,微软关于junction
的漏洞非常多,如cve-2020-0787
,cve-2019-1315
等等。
下面进行攻击展示。攻击分为两步,第一步init阶段正常创建打印机设备,添加端口,并通过SetPrinter函数将打印机设置为PAUSE
状态。
重启主机后,创建软链接,绑定system32目录。恢复Printer Spooler
服务状态,进行漏洞利用。
CVE-2020-17001
微软添加了IsPortAlink
函数,其中通过GetFinalPathNameByHandleW
返回文件的真实路径,与port路径进行对比,来检测junction
。但是GetFinalPathNameByHandleW
对UNC链接的路径处理时逻辑不严格,函数返回的真实路径只是简单的在其前面增加了?UNC的前缀,并不会将其真正对应的link链接返回。所以我们将port的路径进行精心构造如\localhostc$testgetshell.dll
的形式即可进行绕过。
此时,微软头疼不已,直接在重启打印机后,执行任务队列时增加了函数IsSpoolerImpersonating
,检测当前进程权限是否正确合法。这才算上真正修复了这一系列漏洞。
如果从防御方角度来看的话,可以增加一个注册表回调,监控路径
HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionPorts
,当写入的端口含有文件路径时,特别是.dll或者以.asp,.vbs这些可执行脚本文件后缀时,弹窗提醒。
危害升级
前面对漏洞进行了分析,漏洞危害主要在于可以向任意特权目录写入文件,我们如何在实战中进行漏洞利用呢。最直接的方式就是进行dll劫持。在打印机spoolsv服务或者fax服务重启过程中,会加载c:\system32ualapi.dll
。更准确的说是调用uapapi.dll的导出函数UalStart
。我们可以通过替换该dll,实施恶意攻击。
github有一个开源的faxhell项目,是一个编译好的dll文件,用于fax服务的dll劫持(spoolsv服务同理)。功能是绑定一个正向的shell等待服务端进行连接,并通过替换RpcSs
的token,达到提权的目的。强烈建议大家阅读dll的源代码,特别是对线程池的操作,叹为观止。
参考链接:
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类加载器是JVM加载类到内存并运行的过程,这个过程有点复杂,除了系统自定义的三类加载器外,java运行用户编写自定义加载器来完成类的加载过程。java安全中常常需要远程加载恶意类文件来完成漏洞的利用,所以学习类加载器的编写也是很重要的。 类加载器…
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论