Avira Optimizer本地权限提升
版本: Avira Optimizer < 1.2.0.367
测试操作系统: Windows 10 1803 (x64)
漏洞: 通过不安全的命名管道实现Avira Optimizer本地权限提升
漏洞概述
用户安装最新版Avira antivirus时,会附带多个组件,其中包括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#代码后,cmd.exe将在程序集连接到"AviraOptimizerHost"命名管道并使用"exec"参数设置为具有克隆Avira证书的负载(在这种情况下,名为Avira.SystemSpeedup.RealTime.Client.exe的负载)发送"StartProcess()“方法后以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日:详细信息发布