Cache Me If You Can: Zscaler Client Connector中的本地权限提升(CVE-2023-41973)
几个月前,我与同事Winston Ho将一系列漏洞串联起来,在Zscaler Client Connector中实现了零交互的本地权限提升。这是一次深入Windows RPC调用者验证、绕过多项检查(包括Authenticode验证)的有趣探索。查看Winston关于ZSATrayManager任意文件删除(CVE-2023-41969)的原始Medium博客文章!
- 恢复密码检查类型验证错误(CVE-2023-41972)
- Zscaler Client Connector输入清理缺失导致任意代码执行(CVE-2023-41973)
- ZSATrayManager任意文件删除(CVE-2023-41969)
通过串联多个低级漏洞和绕过措施,我们能够将标准用户权限提升至以Windows高权限NT AUTHORITY\SYSTEM服务账户执行任意命令。
本文将分享我们从漏洞发现到开发概念验证利用的方法论。
Zscaler Client Connector及生态系统概述
Zscaler是一家“企业云安全”公司,以其VPN和“零信任”网络产品闻名。Zscaler Client Connector是连接Zscaler各种网络隧道的本地桌面客户端。
ZScaler Client Connector应用程序包含两个主要进程:ZSATray和ZSATrayManager。ZSATrayManager是以NT AUTHORITY\SYSTEM用户运行的服务,处理所需的高权限操作,如网络管理、配置执行和更新。ZSATray则是基于.NET Framework构建的用户前端应用程序。
与Windows上大多数客户端-服务器软件一样,ZSATray和ZSATrayManager使用Microsoft远程过程调用(RPC)进行通信。例如,当用户从界面请求转储日志时,ZSATray使用ZSATrayHelper.dll中的原生sendZSATrayManagerCommand方法进行RPC调用,并传入序列化输入。
|
|
接受来自任何进程的RPC调用而不进行验证是一个重大的安全风险,尤其是当ZSATrayManager支持的某些RPC调用涉及执行高权限操作时。
大多数软件(包括ZScaler Client Connector)会实施检查以确保RPC调用源自受信任进程。因此,我们开始了绕过这些检查的探索。
通过缓存修饰和碰撞绕过RPC连接检查
自CVE-2020-11635¹以来,ZScaler Client Connect增加了对ZSATrayManager的RPC连接的额外验证检查。检查在IfCallbackFn函数中执行,包括以下内容:
- 进程ID(PID验证):调用者的PID必须匹配其映像路径名属于由Zscaler签名的可执行文件的进程(Authenticode检查)。
- 调用者进程验证:调用者进程必须是:
a. 高权限SYSTEM拥有的进程;或
b.
ZSATray.exe
ZSATrayManager通过检查内存中的缓存来确定PID是否属于ZSATray。它使用Fowler-Noll-Vo哈希函数(FNV-1a)键控此缓存,并存储进程名称、允许状态和最后访问时间戳。
|
|
当ZSATrayManager首次启动ZSATray时,它会将其PID存储在ZSATrayManager的缓存中。此外,每次ZSATrayManager成功验证RPC连接时,它都会将调用进程的哈希PID存储在此缓存中。在未来的请求中,如果哈希的调用者PID存在于缓存中,它可以跳过Authenticode和调用者进程检查。
不幸的是,由于ZSATrayManager没有定期清理此缓存,并且PID是非随机的,攻击者可以暴力破解缓存的PID。攻击者可以通过重复终止ZSATray进程并触发ZSATrayManager启动新的ZSATray进程来缓存多个允许的PID,该进程在成功连接到ZSATrayManager后向缓存添加新的PID。这创建了多个允许的PID,攻击者可以暴力破解。通过重复启动和终止利用二进制文件,攻击者可以在Windows分配存在于缓存中的重用PID时导致缓存碰撞。
因此,攻击者控制的二进制文件可以绕过验证检查,向ZSATrayManager发起任意RPC连接。由于ZSATray已经在sendZSATrayManagerCommandHelper中包含了RPC连接客户端的实现,我们可以重用它从自定义.NET二进制文件进行调用以进行利用。
进程注入
绕过此检查的另一种方法是通过注入用户拥有的ZSATray.exe进程来运行任意代码。该进程将通过所有必要的检查,但由于ZSATray是带有托管代码的.NET程序集,因此稍微复杂一些。如果启用了ZScaler Client Connector的反篡改功能,注入也可能失败。
利用恢复密码检查类型验证错误(CVE-2023-41972)
获得了向ZSATrayManager发起任意RPC调用的能力后,我们的下一步是探索哪些支持的RPC函数可以被利用以实现权限提升。
有趣的是,ZScaler为其中一些函数添加了额外的身份验证,例如PERFORM_APP_REVERT。顾名思义,该函数通过执行旧版本的安装程序将ZScaler Client Connector还原到先前版本。该函数接受previousInstallerName、pwdType和password作为参数。后两个在管理员为此操作设置了密码²时使用,并且仅在提供了正确密码时才允许函数执行。
不幸的是,ZSATrayManager不检查pwdType是否匹配PASSWORD_TYPE.ZCC_REVERT_PWD(7),这意味着密码检查函数将信任通过RPC传递的任何pwdType并执行相应的密码检查。例如,如果为pwdType提供了ZIA_DISABLE_PWD,ZSATrayManager将检查password是否与为Zscaler Internet Access设置的密码匹配,而不是用于还原应用程序的密码。
|
|
一些密码类型(包括*ZCC_REVERT_PWD*)如果未指定密码,则默认返回true。
|
|
因此,即使为PERFORM_APP_REVERT设置了密码,攻击者也可以通过将RPC中的pwdType设置为SHOW_ADVANCED_SETTINGS(6)来绕过此检查。
利用Zscaler Client Connector输入清理缺失(CVE-2023-41973)
然而,此时尚未实现崇高的NT AUTHORITY\SYSTEM权限提升。我们继续深入挖掘PERFORM_APP_REVERT。
如前所述,PERFORM_APP_REVERT接受previousInstallerName参数。此参数附加到C:\Program Files\ZScaler\RevertZcc,通常设置为{版本号}.exe。ZSATrayManager以NT AUTHORITY\SYSTEM身份执行此路径的文件。但是,由于这可以从previousInstallerName参数控制,攻击者可以发送路径遍历字符串,例如..\..\..\{攻击者控制的路径}来执行其负载。
不幸的是,对我们来说,路径上的可执行文件仍有额外检查,例如使用*WinVerifyTrust*函数进行Microsoft Authenticode签名验证。这执行操作系统级信任验证,以确保可执行文件由Zscaler正确签名。此验证似乎正确完成,因为它专门检查签名者和颁发者指纹的SHA-2哈希:
|
|
这是我们尝试启动Microsoft Word时的日志输出快照。
|
|
因此,我们需要在链中找到另一个环节。
通过ZSAService的DLL劫持实现任意代码执行
DLL劫持通常不被视为漏洞³,但在特定场景(如此场景)中链式利用时仍可发挥作用。两个条件将卑微的DLL劫持提升为权限提升工具:
- 被劫持的进程由比攻击者更高权限的进程执行,因此可以跨越安全边界。
- DLL劫持路径位于低权限攻击者可写的位置,因此执行攻击不需要额外权限。
ZScaler Client Connector二进制文件之一ZSAService易受DLL劫持,因为其搜索路径从当前目录开始。可能被劫持的DLL之一是userenv.dll。这是一个直接的DLL劫持,可以使用众多DLL劫持负载模板之一进行利用。
|
|
通过将其编译为DLL并将DLL(重命名为userenv.dll)放置在ZSAService.exe同一目录中,启动ZSAService.exe将导致恶意userenv.dll中的任意命令被执行。
因此,我们链中的最终环节完成:
- 攻击者暴力破解缓存PID以向ZSATrayManager发起RPC调用。
- 攻击者绕过
PERFORM_APP_REVERT函数的密码保护。 - 攻击者在
previousInstallerName参数中发送路径遍历负载。 - ZSATrayManager执行通过Authenticode检查的DLL劫持的
ZSAService.exe。 - 劫持DLL导致攻击者的命令以
NT AUTHORITY\SYSTEM身份执行。 - 被攻破!
结论
这是一个极其有趣的漏洞链,花费了周五晚上的大部分时间,突显了多个小漏洞如何在足够的持久性下累积。客户端-服务器进程架构中最大的挑战之一是身份验证和授权,使其成为漏洞研究人员成熟的狩猎场。我们的发现证明,即使正确验证了调用进程,也应适当清理和验证RPC输入。
披露时间线
- 2023年8月15日:向Zscaler团队报告了密码检查绕过和路径遍历漏洞。
- 2023年8月31日:Zscaler团队确认了发现。
- 2023年8月28日:向Zscaler团队报告了任意文件删除漏洞。
- 2023年9月1日:发布了Zscaler Client Connector 4.2.0.209 / 4.3.0.121,修复了CVE-2023-41972和CVE-2023-41973。
- 2024年1月11日:Zscaler团队通知团队已保留CVE。
- 2024年3月26日:Zscaler团队公开披露了CVE(https://trust.zscaler.com/private.zscaler.com/posts/18226)
[1] https://www.cve.org/CVERecord?id=CVE-2020-11635
[2] https://help.zscaler.com/client-connector/reverting-zscaler-client-connector
[3] https://itm4n.github.io/windows-dll-hijacking-clarified/
[4] https://github.com/googleprojectzero/symboliclink-testing-tools
[5] https://www.zerodayinitiative.com/blog/2022/3/16/abusing-arbitrary-file-deletes-to-escalate-privilege-and-other-great-tricks
[6] https://www.mandiant.com/resources/blog/arbitrary-file-deletion-vulnerabilities