0X00 前言
在这篇文章中,笔者将会探讨检测Sliver C2攻击的方法,并列举出如何追踪那些利用Sliver框架实现目标的攻击者。笔者在论坛当中经常看见Sliver的教程,于是就写下了这篇文章。
Sliver框架作为一种高级的指挥与控制(C2)工具(如下图),为网络安全威胁行为者提供了不错的渗透工具,攻击者常用于管理和控制被感染的目标主机系统。C2工具的设计可以允许攻击者通过与目标系统在项目不同的阶段,建立稳定而可靠的通信渠道,远程执行一系列操作,而无需直接接触到受影响的系统。
"阶段"表示攻击阶段的指定目标,红队成员和威胁行为者可以利用该目标确定哪些工具将被用来实现该目标:
Stage0: 其主要任务是获得对某个环境的初始入侵,通常通过Qakbot、IcedID、Emotet和Trickbot等恶意软件实现;
Stage1: 其主要任务是在某个环境中的权限维持,使用的工具包括Cobalt Strike和Sliver等远程管理工具;
Stage2: 其主要任务是权限提升和横向移动,这也是Sliver擅长的;
Stage3: 其主要任务是使用渗透工具从环境提取数据,如MEGASync、Rclone和各种远程管理工具;
0X01 Sliver C2框架简介
Sliver框架是2019年由Bishop Fox公开发布,作为一个开源的,跨平台的C2框架。该工具使用Golang编写,支持Windows、Unix和MacOS的跨平台编译。Sliver C2可以作为Cobalt Strike的开源替代方案,Cobalt Strike是一个被众多APT组织和勒索软件团队使用的C2工具。但是由于Cobalt Strike昂贵的价格和容易被检测的限制,因此,Sliver成为了安全从业人员的另一种选择,并且由于Sliver C2开源的特征,安全从业人员可以在此基础上二次开发,规避安全软件的检测。此外,由于Sliver C2使用Armory制作的便捷的载荷模块系统,Sliver提供了对其他C2框架的替代方案。Armory是Sliver的别名和扩展包管理器,可以用于安装各种第三方工具,如信标(BOF是可以在信标进程中执行的编译过的C程序,可以用来扩充C2框架的后期利用功能)以及诸如Rubeus、SharpMapExec、SharpRDP和SharpHound等.NET工具。
Sliver框架是一个开源项目,源代码可以在Github上获取。通过仔细阅读Sliver C2的源代码,并结合ATT&CK框架进行分析,我们可以总结出Sliver的三种主要攻击方法。具体的攻击方法和对应的检测方式参考下表:
检测 | 功能描述 | ATT&CK | 数据描述 |
---|---|---|---|
方法一 | 利用Sliver执行 Powershell命令 | DS0009 DS0017 DS0022 (EVTX) | 监视Powershell的进程 |
方法二 | 利用Sliver执行user tokens命令 | DS0009 | 利用impersonated tokens监视进程/线程 |
方法三 | 利用Sliver注入shellcode | DS0009 | 监视shellcode的运行 |
0X02 检测Sliver C2攻击(方法一)
笔者建议利用EDR等安全工具来检测Sliver C2攻击,Sliver可以使用命令shell在Windows系统上启动PowerShell(PowerShell是一个为Windows操作系统设计的交互式命令行接口和脚本环境)。根据PowerShell在Windows系统上的执行方式,它会在Windows注册表、Windows事件日志以及系统内存中留下痕迹。Sliver的内置命令shell执行PowerShell命令时使用可执行文件C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
和进程参数-NoExit [Console]::OutputEncoding=[Text.UTF8Encoding]::UTF8
。
通过在目标系统上使用Velociraptor,可以利用安全工具检测这种攻击:
通过寻找PowerShell作为子进程的进程,
通过寻找Sliver使用的特定可执行文件和进程参数
通过寻找Sliver执行的恶意命令
通过寻找Sliver执行脚本块和命令加载监控
0X03 检测Sliver C2攻击(方法二)
Sliver会通过窃取令牌提升权限。Windows操作系统使用令牌来确定进程的所有权。这些令牌可以用于通过提升进程的安全上下文来获得更高级别的权限。Sliver可以窃取目标用户帐户的令牌,并使用命令impersonate启动一个提升的命令提示符。通过迭代所有正在运行的进程,并读取进程的令牌(OpenProcessToken),该进程由目标用户帐户拥有,以模仿用户(ImpersonateLoggedOnUser)和复制令牌(DuplicateTokenEx)。然后,为命令提示符的当前线程启用必要的权限(SeAssignPrimaryTokenPrivilege和SeIncreaseQuotaPrivilege)(AdjustTokenPrivileges)。
在命令提示符的进程中使用被窃取的令牌的线程可以使用安全工具来检测(如图所示,图片来源)。该线程的令牌由用户账户"NT AUTHORITY\SYSTEM(ImpersonationToken.User)"拥有,其拥有者与执行它的进程的令牌的拥有者不同的,后者由用户账户"MSEDGEWIN10\IEUser(OwnerSid)"拥有。Sliver的Impersonate命令和使用Windows利用工具Mimikatz模仿用户帐户时,最终结果是相同的。
0X04 检测Sliver C2攻击(方法三)
Sliver会通过将Shellcode注入进程来隐藏代码执行,隐藏代码执行有助于躲避基于进程的防御的安全解决方案的检测,通过将恶意代码注入到一个独立进程的内存区域中。Sliver可以将shellcode注入进程并使用命令execute-shellcode执行它。
Sliver默认通过执行可执行文件C:\windows\system32\notepad.exe
,并在进程中创建(VirtualAllocEx)一个具有读写访问权限(PAGE_READWRITE)的内存区域来实现这一点,之后shellcode被写入(WriteProcessMemory)到该区域中。然后,区域被调整为执行和只读访问(PAGE_EXECUTE_READ),这允许通过创建线程(CreateRemoteThread)来执行shellcode,如下图所示:
Sliver在开发当中创建了两个函数,分别是"ExecuteShellcodeCmd和PrintExecuteShellcode",用于在目标主机上执行shellcode,部分代码如下所示:
// ExecuteShellcodeCmd - Execute shellcode in-memory.
func ExecuteShellcodeCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
}
rwxPages, _ := cmd.Flags().GetBool("rwx-pages")
interactive, _ := cmd.Flags().GetBool("interactive")
if interactive && beacon != nil {
con.PrintErrorf("Interactive shellcode can only be executed in a session\n")
return
}
pid, _ := cmd.Flags().GetUint32("pid")
shellcodePath := args[0]
shellcodeBin, err := os.ReadFile(shellcodePath)
if err != nil {
con.PrintErrorf("%s\n", err.Error())
return
}
if pid != 0 && interactive {
con.PrintErrorf("Cannot use both `--pid` and `--interactive`\n")
return
}
if shellcodeTask.Response != nil && shellcodeTask.Response.Async {
con.AddBeaconCallback(shellcodeTask.Response.TaskID, func(task *clientpb.BeaconTask) {
err = proto.Unmarshal(task.Response, shellcodeTask)
if err != nil {
con.PrintErrorf("Failed to decode response %s\n", err)
return
}
PrintExecuteShellcode(shellcodeTask, con)
})
con.PrintAsyncResponse(shellcodeTask.Response)
} else {
PrintExecuteShellcode(shellcodeTask, con)
}
}
// PrintExecuteShellcode - Display result of shellcode execution.
func PrintExecuteShellcode(task *sliverpb.Task, con *console.SliverClient) {
if task.Response.GetErr() != "" {
con.PrintErrorf("%s\n", task.Response.GetErr())
} else {
con.PrintInfof("Executed shellcode on target\n")
}
}
ExecuteShellcodeCmd函数:此函数首先获取用户的活动会话,然后检查是否使用自定义程序名及界面、进程ID、shellcode路径等相关参数。且函数会检查是否同时使用了pid和interactive两个参数,如果是,将会报错(因为这两个参数只能使用其中之一)。
PrintExecuteShellcode函数:PrintExecuteShellcode函数是用于展示shellcode执行结果的函数。这个函数接收一个task对象,这个对象中包含执行任务的响应数据,以及一个con对象,这是一个SliverClient的实例,用于与Sliver控制台交互。
0X05 检测Sliver C2攻击(补充)
Sliver的客户端需要与Sliver服务器通信(如下图所示),以便攻击者可以在目标系统上远程执行命令。Sliver支持的网络协议包括HTTP(s)、DNS、TLS......根据环境的不同,使用广泛的协议可能会减少基于网络流量检测植入物的可能性。在所有这些协议中,Sliver推荐使用TLS协议,这是一种使用相互认证的协议,确保客户端和服务器基于TLS证书声明的身份是真实的。这提供了额外的安全层,因为未经授权的客户端不能仅仅向C2服务器发送请求。这并不意味着这些C2服务器在互联网上不能被追踪,但是,Sliver由于使用了TLS协议,安全运营人员可以通过JARM对TLS配置进行指纹识别,使得基于TLS协议识别C2服务器成为可能。
JARM: JARM是一种网络指纹识别工具,它支持对使用TLS的活动服务器进行指纹识别,通过与服务器连接并捕获TLS服务器响应的特定属性,这些属性被散列产生JARM指纹。然后可以使用这个指纹通过网络安全解决方案如Shodan和Censys来寻找C2服务器。
网络协议 | 检测方法 |
---|---|
HTTP(S) | 监视端口31337上的TLS流量,其中TLS证书与颁发者CN=operators 和CN=multiplayer会组合使用,这是默认的Sliver C2配置;根据JARM签名监控流向已知恶意TLS服务器的网络流量 |
DNS域名 | 监控异常流量DNS请求; 根据DNS请求中的域名对 HTTP(S) 流量进行异常检测 |
TLS协议 | 根据JARM签名监控流向已知恶意TLS服务器的网络流量; 对基于HTTP(S)流量的域和IP地址执行异常检测 |
上述方法,可以使我们更加方便的获取Sliver C2服务端的地址。例如:我们可以通过Fofa和Shodan等空间测绘工具去检测C2的服务器:
0X06 总结
在本文中,笔者研究了如何检测Sliver C2攻击,那今天的分享就到这里了,如有不对,欢迎评论区指正。
参考链接:
https://www.microsoft.com/en-us/security/blog/2022/08/24/looking-for-the-sliver-lining-hunting-for-emerging-command-and-control-frameworks/
https://www.huntandhackett.com/blog/hunting-for-a-sliver
https://www.linkedin.com/uas/login-submit
https://www.immersivelabs.com/blog/detecting-and-decrypting-sliver-c2-a-threat-hunters-guide/