[TOC]
随着云函数概念越来越火热,最近几次攻防演练经常能看见云函数扫描器以及云函数隐藏C2服务器,网上只有使用云函数攻击的技术,而基本没有防御的技术,于是我想着就总结一下,如有差错,欢迎斧正
关于环境的搭建,前人之述备矣
我这里补充一些版本更新过后可能会出现的一些坑
service-xxxxxxxx-xxxxxxxxxx.sh.apigw.tencentcs.com
这样的格式,否则不会成功现在我的环境已经配置好了,我们先从流量方面分析,cs的流量可以简单的分为三个阶段
如果是unstage则只有俩个(因为unstage相当于stage+payload,所以unstage的大小比stage大很多,stage才17KB多,unstage直接上了200)
stage下载
当你执行bean文件时(我用的是这个stager,他可以远程下载一个 payload),它会注入到当前被执行服务器内存,然后执行C2的命令
beacon的心跳包阶段
beacon按照在profile里面的配置以get
方法向c2发起心跳请求,同时将宿主机的信息经过公私钥加密后再通过配置文件的加密混淆方式加密再发出
执行C2服务器的命令并将结果回传阶段
C2服务器不会主动请求客户端,当客户端向C2服务端发送心跳包的时候,C2会把命令放入http心跳请求返回包中
然后当beacon端处理完成后,通过post方法回传数据。
请求包
这个地方有一个特点,就是 符合一个checksum8规则,即:路径的ascii之和与256取余计算值等于92。
返回包
相对应的profile文件
这一阶段分析措施主要是看这个大流量包,流量包的大小差不多是在210kb左右,通过解析后可以看到回连地址、加密字段、公钥等配置信息
对加解密有兴趣的可以看看这个工具
https://github.com/WBGlIl/CS_Decrypt
set uri_x86 就是 32位的机子发送的
set uri_x64 就是64位的机子发送的
我的靶机是64位所以Get请求包是访问 /bootstrap-2.min.js
此外,返回包里面还包括了云函数特有的几个属性
X-Request-Id: 请求的id
X-Api-FuncName: 函数名,比如我在云函数里面设置的就是 test,这个是会被看出来的,所以建议红队伪装一个业务名字
X-Api-AppId: 对应账号但是不是账号,后面说明
X-Api-ServiceId: 服务id
X-Api-HttpHost: 就是把appid 账号id 还有腾讯云函数的域名放一起
X-Api-Status: 200 返回值
X-Api-UpstreamStatus: 200 返回值
但凡看到有这个格式,基本可以判断是云函数了(但具体是不是业务需要和甲方业务组沟通)
这是cs的心跳包,心跳包通过cookie传输机器信息(使用了公私钥加密),先经过一次base64编码,再添加"SESSIONID=",最后添加 header "Cookie";
对于云函数配置下的cs配置文件(此处可以更改)
http-get {
set uri "/api/getit";
client {
header "Accept" "*/*";
metadata {
base64;
prepend "SESSIONID=";
header "Cookie";
}
}
X-Api-AppId 不是账号啊ID,但是是对应着账号ID的,
X-Api-ServiceId 我在控制台没找到,应该是对应test云函数服务的id 的
执行了两次命令 一次是whoami 一次是pwd
流量包是这样的
可以看出请求头依旧会带有很明显的云函数特征,Host头带有请求云函数的api的url,header中带有云函数的各种参数
红队对cs魔改大部分是profile文件,这是一个比较常见的云函数的profile文件
set sample_name "t";
set sleeptime "3000";
set jitter "0";
set maxdns "255";
set useragent "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/5.0)";
http-get {
set uri "/api/x";
client {
header "Accept" "*/*";
metadata {
base64;
prepend "SESSIONID=";
header "Cookie";
}
}
server {
header "Content-Type" "application/ocsp-response";
header "content-transfer-encoding" "binary";
header "Server" "Nodejs";
output {
base64;
print;
}
}
}
http-stager {
set uri_x86 "/vue.min.js";
set uri_x64 "/bootstrap-2.min.js";
}
http-post {
set uri "/api/y";
client {
header "Accept" "*/*";
id {
base64;
prepend "JSESSION=";
header "Cookie";
}
output {
base64;
print;
}
}
server {
header "Content-Type" "application/ocsp-response";
header "content-transfer-encoding" "binary";
header "Connection" "keep-alive";
output {
base64;
print;
}
}
}
您可以通过配置文件配置 Beacon 的默认值。有两种类型的选项:全局选项和局部选项。全局选项更改全局的信标设置。
本地选项是特定于事务的 (这句话的翻译自cs的官方手册,原文是 Local options are transaction specific 在我看来,在这里的意思是专注于方式的配置,比如对于http协议应该如何配置,对于https又应该选择如何配置)
如
set sleeptime "3000";
是设置默认的睡眠时间,注意此处是以毫秒为单位的
set jitter "0";
这个是设置数据抖动
官方给出的解释是
Append random-length string (up to data_jitter value) to http-get and http-post server output.
就是让返回包的大小在一定范围内随机抖动,单位是百分比
在一些文章中,会通过它cs流量包的默认大小来溯源,建议修改
` set maxdns
是 通过 DNS 上传数据时主机名的最大长度 (0-255)
set useragent 这个显而易见 设置UA
如果你对这个感兴趣,可以参考
https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics/malleable-c2_profile-language.htm#_Toc65482842
首先它会有一个模板
# this is a comment
http-get {
set uri "/api/x";
client {
header "Accept" "*/*";
metadata {
base64;
prepend "SESSIONID=";
header "Cookie";
}
}
server {
header "Content-Type" "application/ocsp-response";
header "content-transfer-encoding" "binary";
header "Server" "Nodejs";
output {
base64;
print;
}
}
}
这是一个对get请求方式的局部选项配置
# 是代表注释
set uri 分配客户端和服务器在此事务期间将引用的 URI, set 语句需要出现在客户端和服务器代码块之外,因为它适用于它们两者。
header 添加header
metadata {
base64;
prepend "SESSIONID=";
header "Cookie";
}
是代表metadata先经过一次base64编码,再在编码后的数据前面添加"SESSIONID=",最后在修改过的数据后添加 header头 "Cookie";
output {
base64;
print;
}
输出的metadata进行base64编码,再打印
所以 综上所述 有几个分析与反制的思路
service-173y3w0z-xxxxxxxxxx.sh.apigw.tencentcs.com
这样的格式,有点类似域前置,host为白域名,可以着重注意host为apigw.tencentcs.com
格式的流量,如果业务部门没有这样的业务,特殊时期,可以直接封禁这个域名apigw.tencentcs.com
(云函数特征)