一、基本信息

Cobalt Strike是一个著名的框架,它通常被安全专业人员用于攻防演练,因其功能完善,使用灵活,逐渐成为攻击方常用的框架。

Cobalt Strike的植入物,被称为“beacon”,能够使用不同的协议与命令和控制(C2)服务器通信:

  • HTTP/HTTPs-植入物和C2服务器之间交换的数据被打包在一个HTTP请求中。

  • SMB-该通道主要用于点对点通信,它使用SMB协议与可能在基于windows的内部网络上看到的常规通信流融合在一起。

  • TCP-与SMB通道的用途类似,但使用普通TCP套接字。在SMB受到限制或严格监控的情况下,用于横向移动,还可以用于特权提升。

  • DNS-使用各种DNS查询,Cobalt Strike的beacon可以仅使用DNS与C2服务器通信,优点是名称解析几乎总是被允许的,并且在植入服务器和C2服务器之间没有直接通信,因为DNS解析将使用默认的名称服务器进行。

  • Custom-使用记录良好的外部C2协议,该机制可使用户自定义通信方式,可不依赖于Cobalt Strike的默认信道。一个有名的例子是F-Secure的C3框架。

这项研究通过主动探测,对使用DNS作为通信通道的Cobalt Strike服务器进行指纹识别。尽管研究方法会有些不同,但结果将类似于JARM对受Cobalt Strike限制的HTTP/HTTPs请求。

二、DNS重定向

在开始实际的探测之前,了解Cobalt Strike的标准DNS服务器是如何部署的是很重要的。“重定向器"的概念是为了进一步强化攻击基础结构、分离被攻击的组件和实际 C2 服务器所暴露的内容而引入的, 这为使用者提供了更大的灵活性,可防止暴露在互联网上的控制服务器在攻击期间被发现。事实上,更换一个新的重定向器可能需要数小时,而重建一个新的C2服务器可能会对操作产生更大的影响。

通常,标准的Cobalt Strike DNS重定向器是使用socat或iptables创建的。事实上,官方文档建议将其作为创建基于DNS的重定向器的首选工具。

例如,下面的命令能够为DNS创建一个简单的重定向:

    # socat will listen on TCP 5353 and redirect to cobalt strike"s DNS serversocat tcp4-listen:5353,reuseaddr,fork UDP:127.0.0.1:53

    # port 5353 will be exposed via an SSH tunnel on the external redirectorssh ubuntu@redir.c2 -R5353:127.0.0.1:5353

    # on the redirector, socat will listen on 53 and forward the data to the SSH tunnel, that eventually will reach the C2 serversocat udp4-listen:53,reuseaddr,fork tcp:localhost:53535

    在Cobalt Strike内部创建DNS监听器的问题不在本文讨论范围内,因为这超出了本研究的范围。要了解更多细节,建议查看Steve Borosh的重定向Cobalt Strike DNS beacon或bluescreenofjeff的Red-Team-Infrastructure-Wiki。

    得到的通信流如下图所示:

    可以通过查询最初为DNS C2配置的主机名来验证设置。如果设置正常工作,DNS响应应该是在DNS idle malleable配置文件选项中配置的,默认情况下它等于“0.0.0.0”:

      nslookupmalware.c2

      Non-authoritativeanswer:Name:malware.c2Address: 0.0.0.0

      “0.0.0.0”,如前所述,是 Cobalt Strike的默认值。

      三、探测阶段

      F-Secure进行的研究是基于以下声明:

      无论接收到什么查询,只要它不是C2通信的一部分,Cobalt Strike的DNS监听器将使用dns_idle字段中定义的值进行应答。

      事实上,beacon将dns_idle作为检查新任务的重要部分。但有一个问题,默认的 DNS 服务器也会使用该值回复其他域的所有其他查询。

      假设DNS服务器总是以相同的IP地址回应所有的查询,这可能是Cobalt Strike存在的一个指示器。当然,这种方法也不是没有假阳性,研究的一部分是量化这种机制的真实度。

      可以通过启动的Cobalt Strike服务器验证真实度:

        dig @70.35.206.199 +short amazon.com0.0.0.0

        dig @70.35.206.199 +short google.com0.0.0.0

        dig @70.35.206.199 +short nonexistent.domain0.0.0.0

        dig @70.35.206.199 +short -t TXT google.com0.0.0.0

        domain0.0.0.0dig @70.35.206.199 +short -t TXT google.com0.0.0.0

        可以看到,服务器用默认dns_idle值"0.0.0.0"回复了所有查询,即使更改了默认值,这种方法也会起作用,因为所有查询仍将返回相同的值。有趣的是,即使查询的不是 “A” 记录,Cobalt Strike仍然返回了"A"记录。这打破了大多数常见库的名称解析逻辑。下面的片段显示了一个示例:

          digTXTtest @35.178.76.239

          ; <<>>DiG 9.10.6 <<>>TXTtest @35.178.76.239;;globaloptions: +cmd;;Gotanswer:;;->>HEADER<<-opcode:QUERY,status:NOERROR,id: 45988;;flags:qrrdad;QUERY: 1,ANSWER: 1,AUTHORITY: 0,ADDITIONAL: 0;;WARNING:recursionrequestedbutnotavailable

          ;;QUESTIONSECTION:;test.INTXT

          ;;ANSWERSECTION:test. 1INA 8.8.8.8

          ;;Querytime: 97msec;;SERVER: 35.178.76.239#53(35.178.76.239);;WHEN:TueMar 23 10:11:00CET 2021;;MSGSIZErcvd: 42

          为了避免更高级别的解析逻辑,Scapy 库用于伪造原始 DNS 数据包并构建自动扫描程序。下面的片段显示了包发送和响应进行比较的核心功能:

            defcheckDNS(name): ip = nametry:  ans = sr1(IP(dst=ip)/UDP(sport=RandShort(), dport=53)/DNS(rd=1,qd=DNSQR(qname="google.com",qtype="TXT")), verbose=False, timeout=0.5) ansTXT = ans[DNSRR][0].rdata ans = sr1(IP(dst=ip)/UDP(sport=RandShort(), dport=53)/DNS(rd=1,qd=DNSQR(qname="amazon.com",qtype="A")), verbose=False, timeout=0.5) ansA1 = ans[DNSRR][0].rdata ans = sr1(IP(dst=ip)/UDP(sport=RandShort(), dport=53)/DNS(rd=1,qd=DNSQR(qname="google.com",qtype="A")), verbose=False, timeout=0.5) ansA2 = ans[DNSRR][0].rdataif ansTXT == ansA1and ansA1 == ansA2and ansA2 !=""and valid_ip(ansA1): print("[+] Cs Detected: " + ip +" replied with: " + ansTXT)except Exceptionas e:pass

            这段代码很容易解释,只是将最初的假设转换为实际的Python代码。该脚本的其余功能只是增加了多线程和更好的输出格式,主要的逻辑是上面所示的。

            扫描代码针对一小部分数据进行了测试,数据是通过测试版的Shodan获取的,主要是通过JARM 签名,筛选出潜在的Cobalt Strike C2服务器:

            所有的结果数据都被下载下来,然后通过Shodan CLI进行解析,以提取IP地址:

              #addshodanqueryshodanparse--fieldsip_stre5a2e2e7-e029-4b10-a5f8-63687aa7a09c.json.gz >cobalt.txt 

              初始数据集的结果为阳性的,具有多个匹配项:

                python scan.py ~/Downloads/cs-dns.txt[+] Cs Detected:24.252.133.75 replied with:10.0.0.1[+] Cs Detected:193.202.92.36 replied with:193.202.92.36[+] Cs Detected:194.204.33.130 replied with:127.53.53.53[+] Cs Detected:194.62.33.31 replied with:192.168.33.31[+] Cs Detected:5.8.16.29 replied with:72.5.65.111[+] Cs Detected:37.191.180.47 replied with:37.191.180.47[+] Cs Detected:35.178.76.239 replied with:8.8.8.8[+] Cs Detected:85.27.174.244 replied with:85.27.174.244[+] Cs Detected:70.35.206.199 replied with:0.0.0.0[+] Cs Detected:209.9.227.212 replied with:209.9.227.212[+] Cs Detected:175.176.185.229 replied with:103.60.101.170[+] Cs Detected:179.191.84.68 replied with:10.0.0.1

                四、互联网调查

                在一定程度上,研究的下一步是将分析范围扩展到整个互联网。为了获得所需的结果,有必要对所有暴露端口53/UDP的主机进行全网扫描,最后决定使用Project Sonar的数据集,而不是手动进行扫描,该数据集已经收集了所需的信息,这使得可以将扫描范围从数十亿个ip缩小到大约700万条记录。考虑到检测基于UDP的协议,选择“Project Sonar”的数据集非常有必要,因为UDP协议通常较慢,并且不如TCP可靠。

                对数据集扫描会产生大约1400个结果,研究人员认为这个数量过多,需要再根据Cobalt Strike C2服务器的其他特征,进一步辅助验证。比如:

                • 开放端口50050

                • 在HTTP/S请求中是404状态码,并且内容长度为0,这是Cobalt Strike的明显特征

                • 有一个匹配的JARM签名

                • 对于启用分阶段模式的控制服务器,可通过特定HTTP请求,获取到beacon配置

                • 回复“0.0.0.0”,这是“dns_idle”的默认值

                上述过程的结果如下:

                • 24台服务器开启了50050端口

                • 49台服务器返回了,Cobalt Strike的默认HTTP响应

                • 27台服务器启用了分阶段模式,使研究人员获取到了beacon配置

                • 91个服务器回复“0.0.0.0”

                • “07d14d16d21d21d07c42d41d00041d24a458a375eef0c576d23a7bab9a9fb1”是16个服务器的JARM签名,表明是Cobalt Strike攻击

                在 1400 个结果中,由于匹配到上面特征中的一个或多个,122 个极有可能是Cobalt Strike服务器。使用extremely useful Nmap script进一步调查beacon配置后,注意到使用 8.8.8.8 作为dns_idle的重复模式:

                  {"x64":{"md5":"26dca1f00735af2e11d856cdbc239a72","sha1":"0f964782e58ac43ab0433b7cbb007295eed1bcd1","time":1616664618025.3,"config":{"Port":80,"Beacon Type":"0 (HTTP)","Polling":50000,"Pipe Name":"","User Agent":"Mozilla\\\\/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident\\\\/5.0; IEMobile\\\\/9.0; LG; LG-E906)","Jitter":15,"Header 1":"","Method 2":"POST","Spawn To x86":"%windir%\\\\\\\\syswow64\\\\\\\\rundll32.exe","C2 Server":"[REDACTED],\\\\/_\\\\/scs\\\\/mail-static\\\\/_\\\\/js\\\\/","Method 1":"GET","Spawn To x64":"%windir%\\\\\\\\sysnative\\\\\\\\rundll32.exe","Max DNS":255,"Header 2":"","HTTP Method Path 2":"\\\\/mail\\\\/u\\\\/0\\\\/","DNS Sleep":0,"DNS Idle":"8.8.8.8" },"sha256":"ce4d2de8d28423bc975b7792b69722e8b8e01c01c723f43e494709062fcdb550" },"x86":{"md5":"d836ddfcb06c1959d002fabd70aff8fd","sha1":"7d8c5d34da8a0ece4fcda322a1c814b285d4b8f8","time":1616664587530.2,"config":{"Port":80,"Beacon Type":"0 (HTTP)","Polling":50000,"Pipe Name":"","User Agent":"Mozilla\\\\/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident\\\\/4.0; BTRS125526)","Jitter":15,"Header 1":"","Method 2":"POST","Spawn To x86":"%windir%\\\\\\\\syswow64\\\\\\\\rundll32.exe","C2 Server":"[REDACTED],\\\\/_\\\\/scs\\\\/mail-static\\\\/_\\\\/js\\\\/","Method 1":"GET","Spawn To x64":"%windir%\\\\\\\\sysnative\\\\\\\\rundll32.exe","Max DNS":255,"Header 2":"","HTTP Method Path 2":"\\\\/mail\\\\/u\\\\/0\\\\/","DNS Sleep":0,"DNS Idle":"8.8.8.8" },"sha256":"52029626c23dc2cd60f65e0bfa087021f0ee4d96ed0259a6e03cd7ff2fd471ac" }}

                  研究人员决定将该值作为另一个特征,最终统计出Cobalt Strike服务器的总数为135个。剩余的服务器分为以下类别:

                  • 假阳性,我们发现一些家用路由器版本的行为方式与Cobalt Strike的DNS服务器类似。可能是误报,也可能是CS服务器。

                  • Cobalt Strike DNS服务器改变了默认“dns_idle”值,没有在同一IP地址上托管HTTP服务器。

                  • DNS水坑和蜜罐。尽管已经做出了努力来避免这种情况,但一些DNS服务器的行为方式可能与Cobalt Strike类似。

                  注:完整的扫描结果将在这篇博文发布后发布,同时还有扫描程序的源代码。

                  五、Red团队案例

                  研究人员进行这项研究的根本原因是DNS重定向器是愚蠢的,这意味着它将DNS请求毫无逻辑地转发给Cobalt Strike。例如,如果研究人员看一下基于HTTP的重定向器的发展,会发现使用socat或iptables很快就被抛弃了,取而代之的是更好的替代方案,如使用mod rewrite的Apache或Nginx。

                  问题是研究人员还没有看到同样的方法应用于DNS重定向器,一个可能的解决方案是创建一个智能重定向器,它能够根据请求的域名将DNS请求代理到特定的DNS服务器:

                  研究人员发现,使用CoreDNS等开源DNS服务器解决了这个问题。事实上,使用如下所示的“Corefile”,也可以避免这种琐碎的检测:

                    .{forward. 9.9.9.9}malware.c2{forward. malware.c2:5353}. { forward . 9.9.9.9}malware.c2 { forward . malware.c2:5353}

                    CoreDNS 可以部署在暴露在互联网上的 VPS 上,并充当"智能"重定向器。此配置将仅代理Cobalt Strike对"malware.c2"域的请求,其他一切都将使用"9.9.9.9"公共解析器解决。

                    六、结论

                    这项研究展示了一种可以用来追踪暴露在互联网上的Cobalt Strike服务器方法,可以用来丰富威胁情报数据,以实现更好的检测。

                    对于使用Cobalt Strike或其他支持DNS的C2框架的red 团队和渗透测试人员,研究人员提供了一种方法,可以使用开源工具构建更好、更智能的DNS重定向器。

                    注:关于CobaltStrike TLS流量分析可以参考https://mp.weixin.qq.com/s/9xklwpHl-vhXen1luQslSg

                    参考文献

                    1. Bluescreenofjeff - Red Team Infrastructure Wiki

                      https://github.com/bluscreenofjeff/Red-Team-Infrastructure-Wiki

                    2. Steve Borosh - Redirecting Cobalt Strike DNS Beacons

                      https://medium.com/rvrsh3ll/redirecting-cobalt-strike-dns-beacons-e3dcdb5a8b9b

                    3. Cobalt Strike - Simple DNS Redirectors for Cobalt Strike

                      https://blog.cobaltstrike.com/2021/03/11/simple-dns-redirectors-for-cobalt-strike/

                    4. Whiskey-r7 - grab_beacon_config

                      https://github.com/whickey-r7/grab_beacon_config

                    5. Salesforce - JARM

                      https://engineering.salesforce.com/easily-identify-malicious-servers-on-the-internet-with-jarm-e095edac525a

                    6. CoreDNS

                      https://coredns.io/

                    本文为CNTIC编译,不代表本公众号观点,转载请保留出处与链接。

                    联系信息进入公众号后点击“论坛信息”可见。

                    原文链接:

                    https://labs.f-secure.com/blog/detecting-exposed-cobalt-strike-dns-redirectors/

                    原文标题:Detecting exposed Cobalt Strike DNS redirectiors

                    编译:CNTIC情报组

                    声明:本文来自国家网络威胁情报共享开放平台,版权归作者所有。文章内容仅代表作者独立观点,不代表安全内参立场,转载目的在于传递更多信息。如有侵权,请联系 anquanneican@163.com。