某C2鸡肋漏洞分析:你的CS安全吗?

发布时间:2024年01月18日

CobaltStrike是一个知名的红队命令与控制框架,采用Beacon <-> TeamServer <-> Client架构。TeamServer存在受限路径穿越写文件与反序列化漏洞,可以被认证后客户端恶意利用。Client存在反序列化漏洞,可以被RogueCS攻击。

山寨威胁建模

由于这个软件的特殊性,我们需要想想什么才是漏洞:

  1. 直接攻击TeamServer暴露的服务

  2. 通过Beacon攻击TeamServer

  3. 通过Client攻击TeamServer

  4. 通过TeamServer攻击Client

  • TeamServer控制Beacon是功能,任何所谓TeamServer攻击Beacon的操作都不能算漏洞

可以看出TeamServer是核心,先从它下手。

历史漏洞

  • in-the-wild

利用TeamServer从Beacon下载文件时,会将Beacon可控数据中的IP字段作为目录的特点,实现路径穿越写计划任务RCE。

  • CVE-2021-36798

利用TeamServer从Beacon加载截图和键盘记录时,会根据Beacon可控数据中的字节大小申请内存的特点,实现内存耗尽DoS。

  • CVE-2022-23317

猜测是为了兼容proxy的功能(路径为http://开头),没有对URL路径做严谨的校验。动态调试可以看出这会绕过profile相关配置,直接拿到公钥等数据:

图片

虚假的DoS

BeaconC2.process_beacon_data中存在一处利用条件比较苛刻的DoS。

...
int?var4?=?var3.readInt();
...
if?(var4?>?var3.available())?{
????return?false;
}
...
byte[]?var5?=?new?byte[var4];

受限路径穿越

图片

用来防止路径穿越的核心是CommonUtils.SafeFile方法,判断解析前后的路径是否还以限定前缀开头。这其实可以让我们向上穿越一级并得到前缀开头的文件对象:

图片

  • ?CVE-2022-23457就是另一个例子

ManageUser.process为例,Client可以通过Host File功能上传文件到TeamServer并映射至Web服务,这会先发出一个armitage.upload进行预处理,随后由armitage.append上传文件数据。

图片

这里Client与TeamServer基于序列化通过socket通信,SafeFile的二参var1.arg(0)客户端可控,在UploadFile.result拼接上前缀就可以实现受限路径穿越写文件。然而这并没有什么卵用

this.conn.call("armitage.append",?CommonUtils.args(this.file.getName()
|
V
this.conn.call("armitage.append",?CommonUtils.args("../uploads"+this.file.getName()

图片

想到zip解压释放软链接那种套路,File确实可以透过软链接写入指向文件中,但这里似乎没法实现直接将用于路径穿越的软链接本身存进去。

反序列化

图片

反序列化核心是TeamSocket.readObject方法,实际使用的ObjectInputStream.readUnshared。它在ManageUser.run中被PostAuthentication.clientAuthenticated通过多线程拉起。

图片

client来自SecureServerSocket.acceptAndAuthenticate中接收的客户端数据,预检密码使用readUnsignedByte读入,在密码比对正确时会进入上述反序列化流程。

图片

在客户端Connect.dialogAction发起连接时可以向TeamServer传输序列化对象,如果服务端存在gadgets环境就可被恶意利用。

this.tqueue.call("aggressor.authenticate",?CommonUtils.args(var3,?var6,?Aggressor.VERSION),?this);
|
V
Object?payload?=?getObject()?//?URLDNS,?7u21,?...
this.tqueue.call("aggressor.authenticate",?CommonUtils.args(var3,?var6,?payload),?this)
  • 看代码流程感觉作者是考虑到了的,所以将反序列化放到了认证后

随后ManageUser.process会将登录成功/失败的消息序列化写回客户端,我们可以把SecureServerSocket.authenticate改为任何密码都校验成功(欺骗客户端通过密码预检),再写回恶意序列化对象(成为RogueCS),如果客户端存在gadgets环境就可被利用。

...
if?(!this.authenticated?&&?"aggressor.authenticate".equals(var1.getCall())?&&?var1.size()?==?3)?{
...
????Object?payload?=?getObject()?//?URLDNS,?7u21,?...
????this.client.writeObject(var1.reply(payload))
...

利用条件

Client攻击TeamServer的话,需要知道服务端的密码(比如通过泄漏/反制得到HOME目录下.aggressor.prop配置文件),而通过TeamServer则可以攻击任何前来连接的Client。

危害大小取决于运行环境中gadgets的能力,我目前还没在CS内置的lib中找到有实质危害的gadgets。对于原生JRE环境而言,可以通过DeserializationBomb造成CPU型DoS:

Set<Object>?root?=?new?HashSet<>();
Set<Object>?s1?=?root;
Set<Object>?s2?=?new?HashSet<>();
for?(int?i?=?0;?i?<?100;?i++)?{
????Set<Object>?t1?=?new?HashSet<>();
????Set<Object>?t2?=?new?HashSet<>();
????t1.add("foo");?//?make?it?not?equal?to?t2
????s1.add(t1);
????s1.add(t2);
????s2.add(t1);
????s2.add(t2);
????s1?=?t1;
????s2?=?t2;
}

图片

这个与之前OpenSSL的DoS效果类似,多核环境只会影响单核。相关上下文大都是局部变量,也不太可能通过反序列化造成内存型DoS。所以一般也就能打个DNS自嗨,但如果以前调试漏洞在jre/lib/ext之类的目录引入过危险依赖,或者有大聪明用了7u21就会导致RCE:

图片

CS内置了commons-iosleep等jar包,找到链也不是完全没有可能,或者找到一种可控方式从当前目录加载类,就能结合受限路径穿越变成RCE。万一山鸡变凤凰了呢(doge

文章来源:https://blog.csdn.net/moresec/article/details/135677541
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。