- 类别:common 别名:— 优先级:—
- 作者:—
- 依赖:
xalan:xalan:2.6.0
构造一个 Xalan 的 org.apache.xpath.objects.XStringForChars 对象作为「跳板」,利用其继承自 XString 的 equals(Object) 会调用参数对象 toString() 的特性,把上游触发的一次 equals() 转换为对下游任意对象的 toString() 调用。是打通 Equals → ToString 的桥接构件,等价于经典 XString.equals()→toString() 跳板的 XStringForChars 变体。
- 入口
tags:Equals—— 承接一个「会触发equals()比较」的上一环(如 HashMapEquals、HashTableEquals、ConcurrentHashMapEquals 等 HashMap 键碰撞类 gadget)。 - 衔接
nextTags:ToString—— 之后需接一个「其toString()会触发危险逻辑」的下游 gadget(如FastjsonToString1、JacksonToString、XBeanToString等)。 excludes:无。
本类不含基类,直接实现 Gadget 接口,逻辑集中在 getObject() 与 invoke():
@GadgetTags(tags={"Equals"}, nextTags={"ToString"})
public class XalanXStringToString2 implements Gadget {
public Object getObject() throws Exception {
XStringForChars xStringForChars = new XStringForChars(new char[0], 0, 0);
Reflections.set(xStringForChars, "m_strCache", ""); // 预置字符串缓存,规避真正读取 char[]
return xStringForChars;
}
@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
Object obj2 = chain.doCreate(context); // 内层对象:真正要触发 toString() 的目标
Object obj1 = this.getObject(); // 本层跳板:XStringForChars
Object[] objects = new Object[]{obj1, obj2}; // 约定:返回 {跳板, 目标} 二元组
return objects;
}
}逐段解释:
getObject()构造跳板:new XStringForChars(new char[0], 0, 0)用空字符数组构造一个XStringForChars(XString的子类)。随后Reflections.set(xStringForChars, "m_strCache", "")通过反射把字符串缓存字段m_strCache直接置为空串。XString的str()会优先返回m_strCache,预置缓存后equals内部取本对象字符串值时不会去解析空的char[]而抛异常,保证跳板自身「无害且稳定」。invoke()组装二元组:先chain.doCreate(context)取得内层对象obj2(链中后一个 gadget 的产物,即真正希望触发toString()的对象),再生成本层跳板obj1,最后返回Object[]{obj1, obj2}。
触发原理:本 gadget 不自行发起调用,而是把 {跳板, 目标} 交给上游的 Equals 类 gadget 消费。以 HashMapEquals 为例,其 invoke 会 Object[] objects = (Object[]) chain.doCreate(context) 拿到本二元组,再 PayloadHelper.makeMap(objects[0], objects[1]) 造出一个「键会发生哈希碰撞」的 HashMap;HashMap.readObject() 重建时对碰撞的两个键调用 key1.equals(key2),即 obj1.equals(obj2)。此处 obj1 是 XStringForChars,其继承自 XString 的 equals 实现会对参数执行 str().equals(obj2.toString())——由此触发 obj2.toString(),完成向 ToString 环的跳转。annotation 的 description 概括了这条路径:XXX#equals() => AXStringForFSB#equals => YYY#toString()。
本类无 @Param(gadgets.json 中 params 为空);跳板对象与目标对象均由链上下文自动装配,无用户可配字段。
- 依赖
xalan:xalan:2.6.0(org.apache.xpath.objects.XStringForChars由 Xalan 提供;JDK 内也内置了com.sun.org.apache.xpath.internal.objects.XString的等价实现,对应 javanative 分类下的XString*系列)。 - 与同族 XalanXStringToString1(用基类
XString)、XalanXStringToString3(用XStringForFSB)原理一致,差异仅在所构造的XString子类与需反射预置的字段:本类用XStringForChars并预置m_strCache,以规避空char[]在取字符串时报错。 - 关键坑点:上游若是
HashMap键碰撞路径,equals之前会先调用键的hashCode()(见 HashMapEquals 注解提示),因此跳板对象必须能安全地计算hashCode;XStringForChars预置m_strCache=""后hashCode/equals均可正常执行。
自由构件,未直接出现在预设链(usedInChains 为空)。可在需要「equals 转 toString」的自定义二次跳板场景中手动组合,例如 Hessian/JSON 反序列化里以 toString 作为最终 sink 触发点的链路。
- 上游(
tags=Equals,即nextTags=Equals的 gadget):HashMapEquals、HashTableEquals、ConcurrentHashMapEquals。 - 下游(
nextTags=ToString):FastjsonToString1、JacksonToString、XBeanToString等以toString()为触发点的 gadget。 - 同族:XalanXStringToString1(
XString基类版)、XalanXStringToString3(XStringForFSB版)。