PrintNightmare漏洞仍未终结
内容
在发布我的博客文章《2024年PrintNightmare实用指南》之后,一些人提醒我存在一种方法可以绕过文章末尾推荐的点对点打印(PnP)限制。因此,我决定深入研究,看看是否能找到更好的方法来防止PnP配置的利用,而不是仅仅用简短的说明更新那篇文章。
初始设置
让我们从设定起始条件开始,即初始的点对点打印配置。
- 策略“将打印机驱动程序安装限制为管理员”被禁用。这一更改是必需的,否则只有管理员可以安装打印机驱动程序(自KB5005652以来的默认设置),无论其他(包)点对点打印设置如何配置。
- 策略“仅使用包点对点打印”已启用。虽然并非严格必需,但此策略确保我们只能安装签名的包感知打印机驱动程序。
- 策略“包点对点打印 - 批准的服务器”已启用,且prt01.foundation.local是唯一授权的打印服务器。这是此场景中最重要的设置。
初始点对点打印配置
在这些条件下,尝试从其他服务器安装打印机驱动程序,如我在前一篇文章中解释的,会失败并出现错误代码0x800704ec,即ERROR_ACCESS_DISABLED_BY_POLICY,符合预期。
(不太)明显的缺陷
在文章KB5005652中,可以读到“没有等同于将RestrictDriverInstallationToAdministrators设置为1的缓解措施组合”。对我来说,这有点像在说“我们限制打印机驱动程序安装为管理员是有原因的;你可以忽略此警告,但风险自负”,而没有详细说明这些原因或解释这些风险是什么。
关于“RestrictDriverInstallationToAdministrators”设置的说明
尽管如此,我相当确信“包点对点打印 - 批准的服务器”策略将通过确保只有此设置中列出的服务器可用于安装打印机驱动程序来有效防止PnP配置的滥用。
我从未考虑过此策略可以通过简单地欺骗列表中某个批准服务器的名称来绕过。然而,DNS欺骗,最基本的网络攻击之一,就足以规避此保护。
你说DNS欺骗?
为了在实验室中更容易测试,我没有设置自定义DNS服务器。相反,我在我的“受害者”域加入机器的hosts文件中添加了一个条目。此条目强制将prt01.foundation.local解析为我的恶意打印服务器的IP地址,而不是域控制器提供的IP地址。
|
|
在重现前一篇文章中描述的利用步骤并用欺骗名称替换恶意打印服务器的IP地址后,我仍然得到一个错误,但状态码不同:0x80070709,即ERROR_INVALID_PRINTER_NAME。
打印机驱动程序安装失败,错误“无效打印机名称”
我已经对导致此错误的原因有了想法,但为了演示,我选择使用Wireshark以正确的方式调试问题。从恶意打印服务器的角度,我们观察到以下内容。
客户端和打印服务器之间的DCERPC通信分析
客户端/服务器交互完全通过DCE/RPC完成(至少在此阶段),并在AsyncOpenPrinter RPC调用处停止。然而,解析器仅显示加密数据。请注意,这是对CVE-2021-1678的补丁结果,该补丁在通过网络连接到打印后台处理程序服务时强制执行“数据包隐私”RPC身份验证级别,以防止NTLM中继攻击。
你可以在文章KB4599464和CrowdStrike发布的安全公告MSRPC Printer Spooler Relay (CVE-2021-1678)中阅读更多相关内容。
正如Clément Notin(@cnotin)在博客文章《在Wireshark中解密Kerberos/NTLM“加密存根数据”》中解释的,我们可以通过配置NTLMSSP协议并设置用于对打印服务器进行身份验证的明文NT密码来解决此问题。
在Wireshark中配置NTLM首选项
因此,Wireshark现在能够解码与NTLM相关的数据,从而检查RPC加密存根数据的内容。以下是最终结果,显示了RPC请求和响应的并排视图。
使用Wireshark分析“AsyncOpenPrinter”RPC请求
此输出非常清晰。客户端想要打开打印机\prt01.foundation.local\ACIDDAMAGE,而我们的服务器回复错误代码0x00000709(“无效打印机名称”)。看起来我们的(不太)恶意服务器对其实际身份有点过于诚实。在hosts文件中添加欺骗服务器名称的条目应该可以解决问题。
这样做之后,进行了另一次打印机安装尝试,但失败并出现另一个错误代码:0x80070006(ERROR_INVALID_HANDLE)。这个错误更让我困惑,因为我可以看到打印机驱动程序从我的打印服务器下载。我甚至尝试使用新安装的Windows机器重放攻击,但以相同的方式失败。
安装易受攻击的打印机驱动程序
无论如何,打印机安装只是达到目的的手段。我们真正关心的是安装易受攻击的打印机驱动程序。使用Get-PrinterDriver cmdlet的快速检查显示它确实已安装。我们成功绕过了 supposedly安全的PnP配置。
解决方案1:UNC加固访问
正如我们之前看到的,Windows使用DCE/RPC与远程打印服务器通信,但这并不是涉及的唯一通信。它还使用SMB通过print$共享下载驱动程序包。
通过SMB下载的打印机驱动程序包
因此,在Active Directory环境中,人们可能认为强制执行UNC路径加固足以防止此类攻击。让我们仔细看看……
UNC路径加固,也称为“UNC加固访问”,最初是作为安全功能添加的,以保护域控制器的NETLOGON和SYSVOL共享免受中间人攻击(参见MS15-011:组策略中的漏洞可能允许远程代码执行和MS15-011 & MS15-014:强化组策略),通过强制执行相互身份验证和完整性。这就是为什么Active Directory强化指南通常建议将\\SYSVOL和\\NETLOGON设置为加固的UNC路径(参见此处)。
以下屏幕截图显示了如何使用部署在客户端机器上的GPO来加固对路径\prt01.foundation.local*的访问。
配置加固的UNC路径
更新客户端的组策略并再次尝试攻击后,打印机安装现在失败,错误为0x800704ec,即ERROR_ACCESS_DISABLED_BY_POLICY。
由于加固的UNC路径导致打印机安装失败
快速查看Wireshark确认客户端未能建立SMB会话,并立即关闭连接。
客户端关闭与打印服务器的连接
然而,现在声称胜利还为时过早。要理解原因,我们需要考虑下载打印机驱动程序之前的RPC流量。
客户端请求打印机驱动程序包的路径
正如上面的屏幕截图所示,客户端实际上通过RPC过程RpcAsyncGetPrinterDriverPackagePath检索打印机驱动程序包的路径,该过程最终调用内部函数RouterGetPrinterDriverPackagePath。
调用树到“RouterGetPrinterDriverPackagePath”
如果此过程返回客户端用于下载包的UNC路径,我们应该能够用本地路径替换它以绕过UNC路径加固配置。为了测试这个理论,我选择使用Frida并挂钩函数PrvRouterGetPrinterDriverPackagePath。
函数RouterGetPrinterDriverPackagePath由spoolsv.exe导出,公共符号为PrvRouterGetPrinterDriverPackagePath。
检查用于检索打印机驱动程序包路径的RPC调用
不出所料,此函数确实返回了print$共享上打印机驱动程序包的UNC路径。因此,接下来,我将CAB文件复制到目标机器,并使用以下Frida脚本将打印服务器返回的UNC路径替换为此文件的本地路径。
|
|
它起作用了!尽管我们之前看到了错误代码0x80070006,但打印机驱动程序再次成功安装!
从本地CAB文件安装的易受攻击的打印机驱动程序
总之,UNC加固访问本身不足以在此场景中防止中间人攻击。
解决方案2:命名管道上的RPC + UNC加固访问
Windows打印服务器可以使用TCP上的RPC和SMB上的RPC(通过命名管道)访问。然而,在最近的更新中,Microsoft宣布从Windows 11 22H2开始这将改变。
由于此更新,使用命名管道上的RPC(即通过SMB)仍然可用,但默认禁用。因此,后台处理程序仅侦听通过TCP上的RPC的传入连接,且命名管道spoolss不可用。
我不知道是什么促使了这一变化,但不幸的是,我保护后台处理程序免受中间人攻击的下一个想法是强制执行SMB上的RPC,除了之前的UNC加固访问。然而,此更新还带来了新的设置来配置和修改此默认行为,因此让我们测试一下。
最值得注意的是,我们可以配置策略“RPC连接设置”并选择“命名管道上的RPC”作为传出RPC连接要使用的协议。
我的域控制器当前运行Windows Server 2022 21H2,因此新的管理模板不可用。我必须从此链接下载并安装最新的可用模板。
配置RPC连接设置
由于我的攻击机器运行Windows 11 23H2,它受到此更改的影响,因此我的打印后台处理程序仅期望通过TCP上的RPC连接。要重新启用SMB上的RPC连接,我们可以配置本地组策略或使用以下命令。
|
|
而且,它没有起作用。更准确地说,它没有按我预期的方式工作。客户端机器确实尝试使用SMB上的RPC进行通信,并且由于配置了UNC路径加固,这失败了,这是预期的行为。但随后,它回退到TCP上的RPC,从而使策略完全无用,至少对于我的想法来说。
从SMB上的RPC回退到TCP上的RPC
解决方案3:打印驱动程序排除列表
如果你读了标题并认为“这听起来像是个坏主意”,你完全正确,但我想快速提及一下。
在浏览与打印机相关的现有策略时,我找到了这个。我更喜欢像“允许列表”而不是“阻止列表”的东西,但我想总比没有好。
打印驱动程序排除列表策略
因此,我阅读了描述并看到:“排除列表中的条目由INF文件和/或驱动程序的主要DLL文件的SHA256哈希[…]和文件名组成”。
尽管从安全角度来看,此描述看起来很糟糕,但我还是尝试了一下。我将LMUD1o40.inf和UNIDRV.DLL的SHA256哈希添加到排除列表中,但它没有起作用。它没有阻止易受攻击的打印机驱动程序的安装。
配置的打印驱动程序排除列表策略
我不知道我做错了什么。描述确实提到了“文件哈希”,而不是Authenticode指纹。因此,这表明此策略容易出错,除了从安全角度无用之外,因为如果它是签名的可执行文件,人们可以轻松修改文件使其哈希更改而不使其Authenticode签名无效。尽管如此,我认为此策略从未 intended用于安全目的。相反,它可能旨在提供一种阻止不兼容驱动程序的方法。
而且,显然,即使此策略 intended作为安全功能,它在设计上也是有缺陷的,因为它基于“阻止列表”而不是“允许列表”。因此,与已知易受攻击的内核驱动程序类似,你将不得不维护此列表,而不是只允许你正在使用的那些,这对于打印机驱动程序来说似乎比典型的内核驱动程序更易管理。
结论
这就是本次更新的内容。我必须承认我已经没有想法了,并且我认为花更多时间搜索可能提供虚假安全感的潜在危险配置没有附加价值。
关键要点是,Microsoft知识库文章KB5005652 - 管理新的点对点打印默认驱动程序安装行为(CVE-2021-34481)中看似无害的陈述“没有等同于将Restrict Driver Installation To Administrators设置为1的缓解措施组合”实际上应该按字面意思理解。确实,如果你允许低权限用户以某种方式安装打印机驱动程序,你就无法保护点对点打印配置。
我好奇地想看看,Microsoft去年12月宣布的新Windows受保护打印(WPP)模式是否以及如何在大规模采用后解决此问题。与此同时,系统管理员应确保他们不禁用旨在防止CVE-2021-34481的新打印机驱动程序限制。尽管对于某些组织来说可能是一项艰巨的任务,但管理旧打印机的最安全方法似乎是在客户端工作站上预安装其驱动程序包,或者如果需要,使用GPO和安装脚本部署它们。
最后但并非最不重要的是,我要感谢与modzero合作的@parzel和与Synacktiv合作的@laxa,他们都在几周内提醒我注意此绕过,并参与了头脑风暴过程以帮助寻找和探索替代缓解措施。向他们致敬!