Avira Optimizer本地权限提升漏洞
版本: Avira Optimizer < 1.2.0.367 测试操作系统: Windows 10 1803 (x64) 漏洞: 通过不安全的命名管道实现Avira Optimizer本地权限提升
漏洞概述
当用户安装最新版Avira防病毒软件时,它会附带几个不同的组件,其中之一就是Avira Optimizer。简而言之,“Avira.OptimizerHost.exe"以"NT AUTHORITY\SYSTEM"权限运行,并通过"AviraOptimizerHost"命名管道(\.\pipe\AviraOptimizerHost)接收命令。该服务对调用客户端验证不当,同时对启动的可执行文件检查不充分,使得恶意代码能够向"Avira.OptimizerHost.exe"发出进程创建调用,导致本地权限提升。
识别与利用
在评估软件权限提升漏洞时,找到起点通常很困难,因为存在许多不同的原语和漏洞类别。我的方法通常从基础开始,逐步增加复杂性。这个过程通常包括运行PowerUp等工具,识别各种简单(但常见)的错误配置。
如果没有发现有趣的结果,下一步通常是寻找逻辑漏洞。这些漏洞更难自动识别,需要更多手动探测。我的工作流程通常包括分析全局可写目录、可写注册表位置、通过NTObjectManager暴露的命名管道和RPC接口。在分析现有命名管道时,发现某些Avira进程创建了具有NULL DACL的命名管道,这实际上意味着任何请求访问的用户都被授予完全控制权限:
虽然这很有趣,但如果管道没有被特权Avira进程以某种方式使用,它就没有太大用处。检查管道的使用进程ID显示,一个SYSTEM权限的Avira进程正在使用它:
下一步是弄清楚"Avira.OptimizerHost.exe"实际上在使用命名管道做什么。这是一个值得探索的深坑,因为特权进程正在与低权限用户可以控制的资源进行交互。由于"Avira.OptimizerHost.exe"拥有管道的句柄,该进程很可能正在接收通过管道传递的某种数据。为了验证这一点,下一步是在IDA中打开"Avira.OptimizerHost.exe”。经过一番探索,发现该服务正在接受连接到"AviraOptimizerHost"命名管道的任何客户端,并验证它是否是有效的Avira文件。
为了滥用此命名管道,我们需要绕过此检查才能成功通过命名管道向服务发送数据。该服务通过GetNamedPipeClientProcessID()获取连接客户端,然后通过QueryFullProcessImageNameW()提取完整映像路径来进行检查。
获取路径后,服务会提取调用客户端的证书,并确保其由Avira签名且未被篡改。这里的想法是确保只有有效的Avira进程才能向服务发出命令。为了绕过这一点,我们可以简单地将代码注入到正在运行的Avira进程中(或者可能只是克隆现有证书)。
下一步是弄清楚我们可以通过命名管道向服务发出什么指令。在这种情况下,我通常喜欢调查任何潜在的合法客户端,并查看它们在正常操作期间的行为。由于此管道是Avira优化器的一部分,我开始查看已安装的Avira组件。经过一些死胡同后,Avira的System Speedup应用程序浮出水面,因为优化和加速是同义词。在查看Avira的"System Speedup"文件夹后,我偶然发现了Avira System Speedup库。然后,我将System Speedup文件夹中的所有文件加载到DnSpy中,开始搜索命名管道引用。这使我找到了"Avira.SystemSpeedup.Core.Client.Services.dll",特别是"StartServiceHost()“方法。
正如所料,这是连接到"AviraOptimizerHost"命名管道的代码。在此函数下方,它继续调用Avira.Optimizer.Common.Tools.OptimizerHostClient类中的"OptimizerHostCommandsClient.Connect()",这听起来非常有趣。查看此函数时,它只是调用WaitNamedPipe()等待管道准备就绪。一旦准备就绪,就使用CreateFile获取命名管道的句柄。
回顾"StartServiceHost"方法,它实例化了Avira.Optimizer.Common.Tools.OptimizerHostClient类的一个实例,连接到"AviraOptimizerHost"命名管道,然后继续调用一个名为"StartParentProcess()“的有趣方法。
查看该实例化类时,有许多有趣的方法。包括:StartProcess、StartParentProcess、StopProcess、AddTask和RemoveTask。这些方法接受各种参数,然后在将任务转换为JSON后继续调用"SendMessage”:
“SendMessage()“方法获取命令的JSON并将其发送到"AviraOptimizerHost"命名管道,SYSTEM进程"Avira.OptimizerHost.exe"在那里接收它:
查看"Avira.OptimizerHost.exe”,我们可以看到服务读取JSON并解析参数的位置:
在这种情况下,如果我们向命名管道发送"StartProcess()“方法,服务将从通过命名管道发送的JSON blob中提取"procid”、“exec”(可执行路径)、“args”(参数)等。从那里开始,它遵循与验证客户端命名管道相同的逻辑,其中它从"exec"参数获取可执行路径并检查文件的证书以确保它属于Avira。该服务依赖于主题和证书序列号(两者都由攻击者控制),因此可以使用SigPirate等工具从有效的Avira可执行文件克隆证书并将其应用于自定义有效负载。
为了利用这一点,我们需要完成几件事:
- 准备我们的有效负载。在这种情况下,它是一个名为Avira.SystemSpeedup.RealTime.Client.exe的.NET可执行文件,用于启动cmd.exe
- 从有效的Avira文件克隆证书并将其应用于我们的有效负载
- 编写代码注入到有效的Avira进程中,加载Avira.Optimizer.Common.Tools.dll并实例化OptimizerHostClient类
- 使用暴露的方法连接到"AviraOptimizerHost"命名管道并向服务发出命令
对于有效负载创建和证书克隆,我将留给读者作为练习。为了连接到命名管道并发送命令,我们可以通过添加对Avira.Optimizer.Common.Tools.dll的引用并导入Avira.Optimizer.Common.Tools.OptimizerHostClient命名空间来重用现有的Avira库。完成后,我们可以创建OptimizerHostCommandsClient类的实例并调用任何有趣的方法,例如"StartProcess”。
为了实现LPE,我们需要做的就是将此程序集注入到Avira进程中并调用我们的入口点。同样,这是留给读者的练习……但有各种项目使这个过程变得容易(https://github.com/ChadSki/SharpNeedle)。
在注入到Avira进程并执行上述C#代码后,当程序集连接到"AviraOptimizerHost"命名管道并发送带有"exec"参数设置为具有克隆Avira证书的有效负载(在这种情况下,名为Avira.SystemSpeedup.RealTime.Client.exe的有效负载)的"StartProcess()“方法时,cmd.exe将以SYSTEM权限启动。
此漏洞已在Avira Optimizer版本1.2.0.367中修复。在浏览修复程序后,Avira现在利用WinVerifyTrust()和明显的路径白名单来确保启动的进程不受影响。
披露时间线
我想花点时间赞扬Avira及其开发团队。该团队保持持续联系,并以快速的速度修复问题。在本报告的情况下,在初始报告后约30天内开发并分发了修复程序。与认真对待漏洞报告并遵循社区设定的90天修复期望的供应商合作令人耳目一新。
正如SpecterOps致力于透明度一样,我们承认攻击者在公开后采用新攻击技术的速度。这就是为什么在发布新错误或攻击技术之前,我们定期通知相应的供应商问题,提供充足的时间来缓解问题,并通知选定的、受信任的供应商,以便尽快向客户提供检测。
- 2019年7月23日:漏洞发送给Avira安全团队
- 2019年7月24日:Avira确认报告,指出PoC存在一些编译问题
- 2019年7月26日:Avira使用提供的PoC复现了漏洞
- 2019年8月6日:Avira指出开发人员修复了问题,询问我是否愿意测试修复程序
- 2019年8月6日:回复Avira关于补丁的绕过,提供了更新的PoC和详细信息
- 2019年8月16日:Avira回复指出开发人员实施了新的修复程序,并询问我是否愿意测试
- 2019年8月16日:测试了新的修复程序。让Avira知道它似乎足够好
- 2019年8月27日:修复程序上线
- 2019年8月29日:详细信息发布