攻击者滥用MSBuild绕过防御系统并植入Cobalt Strike Beacon
Microsoft Build Engine是在Windows系统上构建应用程序的一个平台,主要用于没有安装Visual Studio的环境中。该引擎也被称为MSBuild,它为项目文件提供了一个xml模式,用于告诉构建平台如何处理和构建软件[1]。其中,项目文件中名为“Tasks”的元素,用于指定在项目构建过程中运行的独立可执行组件。虽然这类元素的本意是执行构建操作,但却可能被攻击者滥用:在MSBuild的伪装下运行恶意代码。该技术在MitreATT&CK中,通常归类为 "受信任的开发工具代理执行"——T1127.001。
这已经是我在不到一周的时间里捕获的第二例基于MSBuild的恶意攻击活动了。通常情况下,这类攻击首先会使用有效账户获得RDP访问权限,通过远程Windows服务(SCM)在网络上传播,并滥用MSBuild的任务功能,并将CobaltStrike Beacon推送给企业主机,具体如下文所述。
滥用MSBuild
为了更容易理解攻击者是如何滥用MSBuild的,请看图1。它展示了一个简单项目(HelloWorld.csproj)的xml文件,其中有一个名为HelloWorld的任务,用于在项目构建期间编译和执行自定义C#代码。
图1 MSBuild的HelloWorld示例项目
当使用MSBuild构建项目时,如图2所示,任务HelloWorld将被执行,它将依次调用Execute()和Start()方法,最后,它会在控制台输出“Hello World”。其中,Execute()方法来自“HelloWorld”类实现的接口“ITask”[2]。
图2 通过MSBuild构建HelloWorld项目
现在,让我们看看图3中恶意的MSBuild项目文件。同理,当该文件被MSBuild调用时,它将在受害者的机器上编译和执行自定义的C#,解码和执行Cobalt Strike Beacon。
图3 恶意的MSBuild项目文件
图4 MSBuild执行CobaltStrike Beacon
在图5中,可以看到信标已经连接到C2服务器(23.227.178.115)。
图5 连接到C2服务器的CobaltStrike Beacon
分析Cobalt Strike Beacon
为了分析恶意MSBuild项目所执行的代码,首先,有必要对变量“buff”进行解码(参考图3)。在MSBuild执行过程中,该变量将通过图6中标出的for循环进行解码。具体来说,就是将“buff”的每个字节与key_code数组的对应的字节进行XOR运算。最后,“buff”字节数组中存储的就是解码后的恶意内容。剩下的代码的作用,是通过Marshal.GetDelegateForFunctionPointer分配内存并执行有效载荷。
图6 解码恶意payload
我已经用Python实现了功能相同的解码函数,具体如图7所示。在解码循环之前,该脚本会先从MSBuild项目文件中读取buff和key_code的内容,并复制到Python脚本中的相应变量中。该脚本的代码可以在这里可以找到。
图7 通过Python实现的解码函数
为了对生成的二进制文件进行分析,我首先尝试在VirusTotal上寻找其哈希值,结果没有找到匹配的值。然后,我继续从字符串开始下手,结果发现了一些可疑的字符串,因为这些字符串我曾经在其他Cobalt Strike Beacon中见过,比如“couldnot create remote thread in %d: %d”和“IEX (New-ob jectNet.Webclient). DownloadString('http://127.0.0.1:%u/'); %s”。
为了进行确认,我使用了Sentinel-One[3]中的工具CobaltStrikeParser。该工具可以用来解析CobaltStrike Beacon并提取其配置,如图8所示。
图8 提取CobaltStrike Beacon的配置
上面的配置表明,它将通过HTTPS(加密通信量)经由端口TCP/8888与C2服务器(23.227.178.115)进行通信。通过它,我们还可以看出:端点/dpixel用于GET请求,/submit.php用于POST请求,并且生成的进程为rundll32.exe——这是用于在受害者的机器上运行C2请求的命令的进程。
在配置并运行C2服务器之后,通常接下来要做的事情就是分析流量,并试图发现更多关于入侵活动的信息。在这种情况下,我使用Didier Steven提供的一个项目验证了CobaltStrike Beacon的私钥是否已知。该项目不仅解析了Cobalt Strike的信标配置,而且指出了Didier是否在Internet上恶意CobaltStrike服务器上找到了相应的私钥。感兴趣的读者,可以参阅[5]来了解关于该项目的详细信息。
在运行1768工具之后,我发现所分析的CobaltStrike Beacon的私钥是已知的,具体如图9所示。
图9 CobaltStrike Beacon已知的私钥
但是,在使用私钥解密Cobalt Strike通信之前,别忘了与C2的通信是通过SSL加密的。在图10中,给出了一个捕获的通信流量示例。
图10 经过加密的C2通信流量
解密SSL通信流量的一种方法,就是使用中间人方法。为此,我使用了项目MitmProxy。使用这样的工具时,通信模式可以设为让客户端(Cobalt Strike 信标)与SSL代理进行交互,并让SSL代理与C2服务器进行交互。作为中间人(代理),我们看到的流量是未加密的。
运行MitmProxy的命令如下所示:
$SSLKEYLOGFILE="~/.mitmproxy/sslkeylogfile.txt" mitmproxy -k --modetransparent
SSLKEYLOGFILE变量用于指示mitmproxy将SSL/TLS主密钥存储在文件sslkeylogfile.txt中。这个文件可以用来供外部工具(如Wireshark[https://docs.mitmproxy.org/stable/howto-wireshark-tls/])解密流量。而-k选项用于指示mitmproxy不必验证上游服务器的SSL/TLS证书,当客户端不知道或被配置为使用代理时,就使用透明模式。
在运行mitmproxy之前,记得启用“IP forwarding”功能,并创建必要的NAT规则,以将SSL流量从客户端机器(运行CobaltStrike Beacon的机器)重定向到mitmproxy端口。就本例来说,相应的命令为:
$sudo sysctl -w net.ipv4.ip_forward=1
$sudo iptables -t nat -A PREROUTING -i <interface> -p tcp --dport 8888 -jREDIRECT --to-port 8080
另一件重要的事情是,别忘了在运行信标的Windows机器上安装mitmproxy证书。通常情况下,默认的证书位于~/.mitmproxy/mitmproxy-ca-cer.cer文件中。这里需要把它复制到Windows机器上面,并把证书安装到Trusted Root Certification Authorities和TrustedPublishers上,具体如图11所示。
图11 安装MITMPROXY证书
完成上述操作之后,运行mitmproxy就可以收集到SSL未加密的流量,具体如图12和图13所示。
图12 C2流量收集
图13 C2流量详情
别忘了,根据Cobalt Strike Beacon的配置(图8),HTTP获取的元数据被存储到用ba se64编码的“Cookie”头部中。因此,图13中标为红色的内容是要用CobaltStrike私钥解密的内容。
为了对相关内容进行解密,我使用了Didier Stevens的另一个优秀工具:cs-decrypt-me tadata[6],如图14所示。
图14 解密元数据
最后,如果希望通过Wireshark对流量进行解密,可以使用存储在“~/.mitmproxy/sslkeylogfile.txt”中的SSL/TSL密钥。为此,可以使用Wireshark菜单Edit->Preferences->Protocols->TLS->(Pre)-Master-Secret日志文件名导入文件,这样,就可以看到解密后的流量,具体如图15所示。
图15 解密后的TLS流量
安全建议
MSBuild是有许多应用程序组成的,并且这些程序都带有微软的签名,重要的是还能用来执行其他代码。根据微软的建议[7],这些应用程序应该被WindowsDefender应用程序控制(WDAC)策略所阻止。
不过,对MSBuild.exe来说,如果系统在开发环境中被用来构建托管应用程序,建议在代码完整性策略中允许使用msbuild.exe。
参考资料
[1] https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild?view=vs-2022
[2] https://docs.microsoft.com/en-us/visualstudio/msbuild/task-writing?view=vs-2022
[3] https://github.com/Sentinel-One/CobaltStrikeParser
[4] https://blog.didierstevens.com/2021/11/21/update-1768-py-version-0-0-10/
[5] https://blog.didierstevens.com/2021/10/21/public-private-cobalt-strike-keys/
[6] https://blog.didierstevens.com/2021/11/12/update-cs-decrypt-metadata-py-version-0-0-2/
最新评论