出网
Romo<1.12.0
ROME的ToStringBean类会调用目标类getter:
TemplatesImpl#getOutputProperties
JdbcRowsetImpl#getDatabaseMetaData
的getter方法以获取目标类对象中的field值
poc
这个相当于实现了client的作用,需要起一个server的LDAP服务,具体看之前[JNDI注入 | Atlant1c`s blog](http://www.atlant1c.cn/2024/04/10/JNDI注入/)
具体应用场景的猜测是一个hessian序列化与反序列化的服务,然后里面引入了Rome依赖,以及创建了下列几个对象,然后被恶意利用了,然后url可控,或者是人为传对象。= =
1 | package hessian; |
分析
看一下简化的调用堆栈
1 | exec:347, Runtime (java.lang) |
ToStringBean
的toString
方法中,会调用getPropertyDescriptors
来获得JdbcRowSetImpl
的所有公开的get方法,然后逐个使用invoke调用。
进入connect方法,会调用lookup函数
可以看到这个dataSource为我们的那个地址
还有一个细节,在ToStringBean类的Object value = pReadMethod.invoke(_obj,NO_PARAMS);
下个断点,观察pReadMethod
方法
调用顺序是按照一个HashMap
转换而成的Descriptor
(当成List就行)来的,而我们都知道HashMap是根据键的哈希值来确定存储顺序的(相当于随机了)
总之就是在这个机缘巧合之下,getter存放顺序很合适,使得在调用到getDatabaseMetaData()
之前都不会报错
从而Rome链可以结合JdbcRowSetImpl使用
不出网
使用 java.security.SignedObject
进行二次反序列化,来实现不出网利用。这个类有个 getObject 方法会从流里使用原生反序列化读取数据,就造成了二次反序列化。
通过触发getter方法来进行拼接
HashCode
1 | hessianinput.readObject()-> |
1 | exec:347, Runtime (java.lang) |
exp
1 | package hessian; |
Equals
1 | Hashtable#readObject() -> EqualsBean#equals() -> EqualsBean.beanEquals() -> SignedObject#getObject() |
exp
1 | package hessian; |
参考:
浅谈Java二次反序列化 - 先知社区 (aliyun.com)
利用特殊反序列化组件攻击原生反序列化入口 - 先知社区 (aliyun.com)