前言
前段时间有个学弟告诉我说我的网站打不开了,后面排查觉得可能是因为我的服务器上搭建了CS,50050端口的特征非常明显,被某安全公司检测到,所以我的ip被他们学校的网管拉黑了。然后我想了想自己之前折腾的k3s,来试试隐藏CobaltStrike的特征吧。
修改端口
首先CobaltStrike的默认端口为50050,通过修改teamserver来更换其他端口,比如可以尝试换到5901端口
除此之外其实也可以尝试使用一些端口转发的方案,比如用k3s新建一个service将5900端口转发到对应容器的50050端口
修改默认证书
从teamserver的脚本中可以看到cobaltstrike.store文件就是cobaltstrike的证书,如果这个文件不存在则会使用keytool添加一些默认的信息生成一张证书:
而生成的这张证书的特征都很明显密码是123456,使用keytools命令也可以看到:
|
|
所以需要生成一张新的证书来替换掉默认的证书:
|
|
然后用生成的cobaltstrike.store
替换默认的cobaltstrike.store
文件
流量混淆
流量混淆需要用到Malleable C2 Profile
,编写Profile可以参考
|
|
在官方给出的例子中也有比如伪造成RTMP通信流量、伪造googledrive通信流量。其他的还有例如threatexpress/malleable-c2伪造了jquery的通信流量。
然后运行teamserver
的时候需要在参数后面加上C2 Profile
的路径:
|
|
然后CobaltStrike就会按照我们编写的C2 Profile
进行通信。一个基本的C2配置文件如下所示:
|
|
其中http-get
和http-post
都有client
和server
两个块。其中client
代码块为beacon
回连服务器时发送的数据,server
代码块为CS服务器返回给beacon
的数据。
client
块中的metadata
如下:
|
|
就是说规定传输metadata
的时候先base64编码一遍,然后在前面加上__cfduid=
,最后以header "Cookie";
结尾将数据放到HTTP
报文的Cookie
中进行传输。
而server规定响应的报文如何传输:
|
|
也就是说对于响应的头部中包含Content-Type: application/javascript
,先经过xor
编码一遍,然后base64
编码,最后print
到响应的body中。prepend
和append
不难理解就是将字符串加在通信数据的前面或者后面。
数据传输的编码方式又有这几种:
Statement | Action | Inverse |
---|---|---|
append "string" | Append "string" | Remove last LEN(“string”) characters |
base64 | Base64 Encode | Base64 Decode |
base64url | URL-safe Base64 Encode | URL-safe Base64 Decode |
mask | XOR mask w/ random key | XOR mask w/ same random key |
netbios | NetBIOS Encode ‘a’ | NetBIOS Decode ‘a’ |
netbiosu | NetBIOS Encode ‘A’ | NetBIOS Decode ‘A’ |
prepend "string" | Prepend "string" | Remove first LEN(“string”) characters |
还有如下几个是终止语句:
Statement | What |
---|---|
header “header” | Store data in an HTTP header |
parameter “key” | Store data in a URI parameter |
Send data as transaction body | |
uri-append | Append to URI |
终止语句规定了传输的数据应该放在HTTP报文的哪个位置。
了解了这些语句大概就能写出来一些伪装成正常HTTP报文的C2了,例如可以伪造淘宝、B站、Github这些网站的,例如把这些网站的HTML保存下来用prepend
和append
将其放在server
返回的报文中,看起来就非常像是正常的流量。
在C2 Profile
中还可以配置ssl
证书:
|
|
为了看起来比较像一个正常的网站,这里可以申请一个合法的证书,然后将pem
证书和key
私钥转化为store
格式的证书的命令如下:
|
|
但是我觉得如果使用了nginx
反向代理,这一步似乎也不是特别必要,因为可以让nginx
跑https
再用反向代理转发给C2
所在的服务器
nginx反向代理
nginx
反向代理可以用来隐藏C2
服务器:
server {
listen 80;
server_tokens off;
server_name github.com;
location /abcd {
client_max_body_size 20m;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
if ($http_user_agent ~* 'GitHub') {
proxy_pass https://cs_real_ip;
}
}
location / {
root /usr/local/nginx/html;
}
}
在上面的例子中beacon
需要将host
改为github.com
,然后路径为/abcd
,header
中也带上GitHub
之后nginx
才会将请求转发给对应的c2
服务器。那么到这一步之后它看起来就是一台人畜无害的的nginx
服务器,没有人可以只通过端口扫描就把你的服务器标记为恶意服务器了 。
域前置
域前置大概就是说给C2
的网站加个CDN
,如果某个高信誉的域名和我使用了同一个CDN,则为可以将上线的回连地址设置为该地址,将请求头中的Host
设置为攻击者的Host
。上线时CDN
判断请求头中的Host
将请求转发到真实的IP,从而达到隐藏真实IP的效果。这种方式可以做到让DNS请求、SNI信息、Beacon回连的IP地址都是高信誉的,不对HTTPS进行解码的话是无法察觉的。不过这种技术已经是好几年前提出来的了,目前大部分CDN应该都禁止了这种方式,更详细的原理可以这篇文章
Referer
https://xlab.tencent.com/cn/2021/05/14/domain-borrowing/
https://wbglil.gitbook.io/cobalt-strike/cobalt-strikekuo-zhan/malleable-c2