CVE-2021-1675漏洞及利用分析

robots

 

一 漏洞简介

前段时间,微软公布Windows PrintNightmare两个安全漏洞,分别为CVE-2021-1675CVE-2021-34527。公布几天后,minikatz率先工具化集成了CVE-2021-1675和CVE-2021-34527的EXP。通过查看minikatz源码,在CVE-2021-1675的EXP中,调用的RPC函数为RpcAddPrinterDriverEx;在CVE-2021-34527的EXP中,调用的RPC函数为RpcAsyncAddPrinterDriver。系统处理这两个RPC函数后,都调用了YAddPrinterDriverEx函数,但是没有对参数dwFileCopyFlags进行条件判断。由此可设置APD_INSTALL_WARNED_DRIVER标志,使添加打印机驱动时,以高权限加载DLL。

(补丁前后对比:Windows PrintNightmare漏洞和补丁分析)

本文复现和分析的环境为 Windos Server 2016 Standard。通过afwu发布的EXP进行修改修改,复现CVE-2021-1675。复现文章也挺多,这里推荐一篇,不复现了。值得一提的是,在复现时,除了修改UNIDRV.DLL文件路径以外,还需要修改pConfigFile赋值的路径。如果采用1方式的路径,由于在打开文件句柄之后执行驱动文件的更新,Old目录还未生成,所以打开句柄时,找不到文件。采用2方式的路径,文件句柄打开后,并未释放处于占用状态,导致后面加载DLL的时候,加载失败。

 

二 漏洞分析

2.1 动态查看CVE调用

1)CVE-2021-1675

通过Process Moniter抓取到EXP加载DLL时,执行过程中的堆栈调用。

该漏洞点在于,调用YAddPrinterDriverEx函数时,没有对参数dwFileCopyFlags做校验,能够使用APD_INSTALL_WARNED_DRIVER标志,导致后面对驱动合法性校验失效,可以任意的加载DLL,并且为system权限。

2)CVE-2021-34527

同样通过process moniter抓取mimikatz中CVE-2021-34527的EXP执行数据,加载DLL的堆栈调用。

通过地址可以找到,spoolsv.exe的调用的处理函数为NThreadingLibrary::TWorkCrew::tpSimpleCallback。

继续调用TFunction4<unsigned short *,_DRIVER_CONTAINER *,unsigned long,enum Call_Route>::Run(__int64 a1)函数,最后调用YAddPrinterDriverEx。由此可知CVE-2021-34527和CVE-2021-1675,最终都是调用YAddPrinterDriverEx函数,只是RPC调用不同,所以可以说这个漏洞是CVE-2021-1675的补丁绕过。引发思考,如果再有不同RPC调用了YAddPrinterDriverEx函数,也是能绕过CVE-2021-1675补丁的。

2.2 功能分析

EXP会通过RpcBindingSetAuthInfoExW函数,绑定句柄的认证,授权和安全质量的服务信息。当函数执行成功时,identity.User设置用户名,代表了权限。如果是低权限用户,执行ValidateObjectAccess函数后结果为0,administrator用户的权限执行ValidateObjectAccess函数后结果为1。

1)绕过ValidateObjectAccess检测

CVE-2021-1675是逻辑漏洞,通过RPC添加打印机驱动程序的时候,参数dwFileCopyFlags(v7)的标志位APD_INSTALL_WARNED_DRIVER(0x8000)为1时,_bittest函数的结果为1,则v12被赋值为0,从而不执行ValidateObjectAccess的检查。

但在Server 12的中,a7的值是固定为1,一定会执行ValidateObjectAccess检测。

2)检查驱动基本信息

MyName:检查驱动名称是否合法,ValidateDriverInfo的执行流程。

  • 检查是否为本地文件
  • 核对初始化key
  • 校验驱动文件的合法性

但是当dwFileCopyFlags含有 APD_INSTALL_WARNED_DRIVER(0x8000)标志位时,dwFileCopyFlags & 0x8000的结果为0x8000,0x8000取非后值为0,将会跳过驱动进一步的校验。

3)获取文件句柄

v13的值是由dwFileCopyFlags的低8位取反后,右移4位,再跟1做与运算得出。v13的值决定CreateInternalDriverFileArray函数的第5个参数(a5)。经过计算,当dwFileCopyFlags低8位的值为0x1X时(X可为0-F中任意值),可以使a5为0。当a5的值为0,可以规避对驱动文件的合法性检查。

通过CreateFile打开文件,得到3个文件句柄,并保存到DllAllocSplMem申请的空间中,用于后面文件更新使用。

4)拷贝文件到驱动空间

dwFileCopyFlags的成员pConfigFile、pDataFile、pDriverPath分别保存了配置文件、数据文件、驱动文件的文件路径。将上述成员中的文件路径下的文件,移动到C:\Windows\System32\spool\drivers\x64\3下时,需要经过以下操作:

  • 文件句柄的文件信息进行核对
  • 将文件拷贝到C:\Windows\System32\spool\drivers\x64\3\new
  • 通过WaitRequiredForDriverUnload函数下的MoveNewDriverRelatedFiles函数,将spool\drivers\x64\3下的同名文件移动到spool\drivers\x64\3\old\x (x∈[1,3] ) 目录下,再把spool\drivers\x64\3\new目录文件,移动到spool\drivers\x64\3下,从而实现更新文件。

5)更新驱动文件

通过更新Config文件,将spool\drivers\x64\3下新的配置文件加载起来。

 

三 总结

CVE-2021-1675绕过用户权限检查,可以低用户的权限添加打印机驱动,由于是RPC执行打印机添加驱动,所以也能称为RCE漏洞。不过实现RCE条件是比较苛刻的,至少需要有域控的普通用户,且还需要有共享目录。个人认为该漏洞可用于持久化的操作,得到域控的administrator的账号和密码时,在有共享目录、能访问到域控的情况下,打上6月份的补丁,也能远程的加载共享目录下的DLL。

作者:无明@天玄安全实验室
更多内容请前往微信公众号:天玄安全实验室

 

四 参考链接

[1]https://www.freebuf.com/vuls/279876.html

[2]https://422926799.github.io/posts/c257aa46.html

[3]https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/b96cc497-59e5-4510-ab04-5484993b259b

[4] https://github.com/afwu/PrintNightmare

(完)