HotSwappableTargetSource+XString利用分析
1174735059082055 发表于 浙江 WEB安全 467浏览 · 2025-05-12 04:05

HotSwappableTargetSource+XString利用分析

前言:为什么 XString 需要配合 HotSwappableTargetSource 进行利用而不能直接单独使用由 equals 调用到 tostring 方法。

XString 构造

这里先尝试只用 XString 来进行构造看能不能调用到 tostring 方法,拿调用 JsonObject#toString 来实验,那么链子如下,

先照着 HotSwappableTargetSource 的格式写个 poc

看上面 gadget,其实最主要的部分还是 HashMap#putVal- >XString#equals 这段调用,进入 HashMap#putVal 方法看到要想调用到 key.equals 需要不满足一个 if 条件,



需要想 hashmap 中添加两个键值对,然后注意到 tab[i = (n - 1) & hash],会判断这个 tab[i] 是不是空,不是就会调用 equals 方法。

所以我们需要让两次的 tab[i] 的 i 值一样,这样第二次判断时不为 null 就会调用我们需要的 equals 方法(k 参数就是上一次的 key),而这个 i 值看到主要是由 hash 决定,n 值都一样。

朔源 hash 值,看到是根据 hash(key) 得来的,



这里的两次 hashmap 键值对为下面,不难想象如果 tab[i] 不为空后最后会调用 xs.equals(jsonObject)

这里 XString 的 hash 值计算还有个特点,会把其参数强制转换为 string 类型来进行 hash 计算,上面是 XString("x") 所以最后会计算 hash(x),现在最主要的是怎么让其 hash 值相等,这里就可以用到下面这个 hash 爆破脚本

这个脚本是计算 key.hashcode(),调试看到 jsonObject.hashcode() 的值为 10



爆破的的值为 /n,那么构造

看到满足条件



继续跟进,最后成功来到 equals 方法



然后调用到了 JSONObject.toString 方法



不过这里再看看上面 payload 发现

要想最后调用 TemplatesImpl#getOutputProperties 方法还需要这样构造

然后再次重新爆破 hash 值,但是如果 jsonObject 中的 map 的 key 是 TemplatesImpl 对象的话其实有个问题,看看 hash(JSONObject)



跟进 key.hashcode()



主要看看这里的 this.map



这里因为TemplatesImpl 没有 hashcode 方法,会调用到 Object.hashCode(),而这个在每次实例化的时候都不一样,所以通过new实例化的TemplatesImpl和readObject实例化的TemplatesImpl是两个不同的对象,这就导致每次报错得到的 hash 和最后反序列化触发的时候始终不一样。

不过经过上面一通分析发现只是调用 tostring 方法单靠 XString 还是能做到得,那么只有最后的对象存在 hashcode 方法就行了。

HotSwappableTargetSource 妙用

接下来分析 HotSwappableTargetSource 怎么解决的最后利用问题,poc

同样到 hash 函数



因为这里的 HotSwappableTargetSource 类存在 hashcode 方法,直接调用其 hashcode 方法,



所以两个键的 hash 值也就相等了,都是 HotSwappableTargetSource 类,接下来就会调用到 HotSwappableTargetSource.equals 方法,参数也是 HotSwappableTargetSource 对象



继续跟进看到接下来会调用 HotSwappableTargetSource 对象的 target 的 equals 方法



两个 target 看上面就行了,所以最好调用到 XString.equals 方法,并且 JSONObject 中的 map 也是可以利用的 TemplatesImpl



其他 Xstring 组合

比如说在 resin 反序列化中的 QName 利用链,就是通过 tostring 触发到远程类加载,看了师傅们的链子是通过 hessian 反序列化触发 hshamap.put,然后通过 Xstring 来实现的调用,

poc

执行成功弹出计算机



为什么这里只用 XString 依赖就能成功调用到 toString 方法呢?其实很简单,上面说了是因为这里的 QName 是存在 hsahcode 方法的使得其每次对象的 hash 值是一样的,这样本地爆破出的来的 hash 值和反序列化时就是一样的,

看其 hashcode 方法



看到获得是一个字符串,也就是上面构造函数传入的两个字符串,所以 hash 值完全可控不会变,这样就可以直接由 Xstring 调用到 toString 方法了。



当然这只是一个例子,其他的还有很多。

参考

https://boogipop.com/2023/05/18/Resin&&XBean反序列化利用链学习/#toString-Qname

后面发现早有师傅分析过这个问题了。

https://mp.weixin.qq.com/s/cqntHdPy0b-W0ozNilVMsQ

3 条评论
某人
表情
可输入 255