freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

关于我学渗透的那档子事之Java反序列化-CC1链-2
potatosafe 2022-01-17 19:24:27 99755

前言

上一篇说了CC1链的利用方法,这篇紧接着继续说,之前的利用走的是TransformedMap,这篇我们按照yso的CC1链走一遍,其实就是把TransformedMap换成了LazyMap,利用动态代理方式触发。话不多说,我们直接开始。

一、利用链流程

老规矩,画了一张流程图,供大家参考。如图所示,这里还是按照三部分讲解

Transformer接口->制作链式调用恶意方法
LazyMap->套娃触发ChainedTransformer.transform
AnnotationInvocationHandler->动态代理触发invoke

二、Transformer接口

这里内容和CC1链-1一样,看过的师傅可以直接跳转该小节

这里需要说Transformer三个实现类,InvokerTransformer、ConstantTransformer、ChainedTransformer。

我不太想脱离分析流程按照顺序讲解三个类的原理在拼接。我为了更好的梳理思路,我们进行potato链式讲解(自定义)。

我们首先来看一下Transformer接口。

1642262909_61e2f17dcef23c4f053be.png!small?1642262943327

1642262889_61e2f16967ec86d8abf5f.png!small?1642262922533

接口没什么特别的,做了个transform方法。我们看一下接口的实现类。这个InvokerTransformer就是我们这条利用链的触发点,我们进入这个类看一看。

1.InvokerTransformer

首先我们跟进transform方法,我们可以看到这个方法将传入的对象反射方法,然后执行方法,这就是个任意方法调用了。

1642263335_61e2f32795c3c6f6f03f2.png!small?1642263370871

我们看上图可以知道,transform可以进行任意方法调用,我们看一下iMethodName、iParamTypes、iArgs是怎么赋值的,我们跟进构造函数。

1642263800_61e2f4f8cc4f472c7957b.png!small?1642263832985

OK,参数全部可控,这样我们就可以进行直接写个任意方法执行了。

Runtime类分析

我想了想,还是说一嘴Runtime的问题,师傅们别嫌我啰嗦哈。

首先我们知道我们一般执行命令是通过Runtime.getRuntime().exec("command");执行命令的,而Runtime是一个单例模式,我们是没办法直接创建的,所以我们都是通过getRuntime去获取然后执行exec方法。

1642264649_61e2f8495254e4c043813.png!small?1642264682004所以我们这里想要实现InvokerTranformer,通过getRuntime获取就可以了。

1642264812_61e2f8eceb7b53a761383.png!small?1642264847621

我们知道Runtime是无法序列化的,但是InvokerTransformer可以任意执行方法,我们只需要将反射的反射通过InvokerTransformer的格式去调用就OK了,

1642266009_61e2fd9994d1b5298b42c.png!small?1642266043899

2.ChainedTransformer

我们根据上面InvokerTransformer可以看出,这个相当于InvokerTransformer一层一层的调用,也就是链式调用,所以这就引出了我们这里说的Transformer接口的第二个实现类ChainedTransformer,我们跟进去这个类看一看。

1642266462_61e2ff5e09a93bf27fc15.png!small?1642266494168

我们看到它写了个循环,应该也叫递归吧,他的transform就是一层一层的调用,然后我们在通过Runtime.class触发就可以了。我们接下来看一下它的构造函数。

chainedTransformer.transform(Runtime.class);

1642267026_61e301920e27a7c6502b2.png!small?16422670586431642267034_61e3019a67418ac3ef267.png!small?1642267066642

这里我们就明白了,我们只需要将需要执行的方法通过链式的形式写到Transformer里面就可以了,其实就是个链式调用。但是我们触发的话还需要传一个Runtime.class,当然你将传入transform(Runtime.classs)的链在放一个里面也行,还有更美观的一个方法,就是Transformer接口的第三个实现类ConstantTransformer。

3.ConstantTransformer

其实用这个实现类的目的就是将Runtime.class返回放到chainedTransformer的链子里面,其实这个不是利用链的关键。我们跟进这个类看一看吧

1642267894_61e304f64c025963014d2.png!small?1642267926598

1642267914_61e3050a830f9096266ce.png!small?1642267946720

这个实现类将我们传入的对象通过transform原封不动的返回了,这样我们就可以和InvokerTransformer一起封装到ChainTransformer链里面了。

至此为止我们Transformer接口分析结束,简单总结一下就是通过InvokerTransformer制作runtime类的反射,ConstantTransformer传入runtime.class制作链的触发,chainTransformer将链封装起来。

三、LazyMap

其实到这里之前都是cc1-1链的内容,我们CC1-1调用的是transformMap而CC1-2调用的是LazyMap。我们跟着上面的思路继续走,看看谁调用了transform方法。

1642416225_61e548611638dd7d99a55.png!small?1642416228921

定位到LazyMap,我们继续跟进,查看一下get方法。

1642416270_61e5488e1431f7943535b.png!small?1642416271378

可以看到factory.transform是我们需要的,我们看一下factory是怎么定义的,跟进构造函数。

1642416306_61e548b226c3cb0e717db.png!small?1642416308315

上图我们可以得知factory为我们可控,我们看一下谁调用了get,当然这个get其实很难找上面的调用。我们也不纠结那么多,我们直接跟到AnnotationInvocationHandler的invoke方法

四、AnnotationInvocationHandler

跟进Invoke方法,我们可以看到调用了memberValues.get。我们去查看构造方法可以看到我们其实是可以控制type、memberValues,memberValues是我们传入的可控Map。

1642416460_61e5494cf3c7634e74e10.png!small?1642416462878

1642269846_61e30c96b2ae234f7e467.png!small?1642269879775

接下来我们再次查看该类,invoke方法,看到这里我们可以想到~动态代理~InvocationHandler接口

1642416910_61e54b0e5ee71455a1a45.png!small?1642416912290

1642416951_61e54b37dc9e0a35603c4.png!small?1642416953184

接下来我们制作动态代理Map

InvocationHandler h = (InvocationHandler) annotationInvocationdhdlConstructor.newInstance(Override.class,lazyMap);

Map Proxy = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),new Class[]{Map.class},h);

我们知道动态代理方法在执行时调用h里面的invoke方法去执行,且分析AnnotationInvocationHandler的invoke方法,我们可以知道需要无参方法通过。

1642417050_61e54b9a925ba1729bca6.png!small?1642417052648

这里我们查看readObject,正好有一个无参方法调用。

1642417068_61e54bac9c53560206726.png!small?1642417070871

最后我们正向捋一下思路,annotationInvocationdhdlConstructor反序列化执行readobject到memberValues.entrySet触发动态代理,跳转到AnnotationInvocationHandler.invoke触发memberValues.get,跳转到LazyMap.get触发chaintransform.transform,之后直接往下走就调用恶意方法了。

五、断点调试利用链

1642418096_61e54fb03388b00541fec.png!small?1642418100763

1642418031_61e54f6f09a393eb6bf8f.png!small?1642418034933

1642418117_61e54fc5606203588ce11.png!small?1642418121849

可爱小尾巴~~~

我只是个基础很差 技术很菜 脚本小子里面的小菜鸡,文章里面有什么写的不对的地方,望师傅们多加指正,我肯定狂奔加小跑的学。CC1链就算说完了,之后这个篇章可能继续按这个线说CC6也可能按顺序说一下优先队列的CC2。写写思路总结锻炼锻炼自己还是挺好的。

# web安全 # 代码审计
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 potatosafe 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
Java反序列化—利用链篇
potatosafe LV.4
这家伙太懒了,还未填写个人描述!
  • 19 文章数
  • 86 关注者
擅长捉弄的内存马同学:Valve内存马
2022-11-02
名侦探土豆:Fastjson反序列化漏洞-TemplateImpt链
2022-03-13
名侦探土豆:Fastjson反序列化漏洞-JdbcRowSetImpl链
2022-03-13
文章目录