ysoserial的payload只看过Groovy和CommonsCollections1,就一直以为ysoserial是简单的通过最终调用Runtime.getRuntime().exec(cmd)来实现各种利用链的命令执行的,太年轻。。。
本文以CommonsCollections2为例,主要介绍:
- ysoserial通过TemplatesImpl实现的通用命令执行打包
- 如何实现代码执行(非命令执行)
ysoserial 流程简介
作者也是很皮的
1 | $ java -jar target/ysoserial-0.0.6-SNAPSHOT-all.jar |
入口是ysoserial.GeneratePayload, GeneratePayload里面组合成最终的paylaod流程很简单,不多介绍
1 | final ObjectPayload payload = payloadClass.newInstance(); |
getObject
getObject是每个payload的通用接口函数,最终返回被序列化的obj
以CommonsCollections2 为例
1 | public Queue<Object> getObject(final String ... command) throws Exception { |
其中首尾需要注意,为通用打包逻辑,中间为CommonsCollections2的利用链。下文详细讲解这两个逻辑。
CommonsCollections2的利用链
ysoserial对于CommonsCollections2调用链的解释:
1 | /* |
跟进调试
1 | transform:129, InvokerTransformer (org.apache.commons.collections4.functors) |
其中有意思的点
PriorityQueue 的属性queue是个数组,PriorityQueue 反序列化会对queue每个内容进行反序列化为objN,然后调用heapify方法,大致功能应该是计算每个queue的优先级。
heapify - siftDown - siftDownUsingComparator,为了比较相邻两个值属性,引入了接口Comparator, 其中TransformingComparator是该接口的实现。
TransformingComparator compare方法,通过Transformer 将待比较的两值归一化,接口Transformer的实现类InvokerTransformer。
InvokerTransformer transform 方法使用了invoke,而且method、class、args都可自定义。
那接下来就是寻找可以class.method(args)可执行任意命令的类了。ysoserial使用的是通用的TemplatesImpl。
通用的TemplatesImpl
参考【1】中对TemplatesImpl这两段总结的很好,直接使用,总结为2点
TemplatesImpl类有意思的属性,是个byte[]数组,可以存class
TemplatesImpl类的getTransletInstance方法会将该class实例化。
那么思路就是:
将command写在class 的static 方法内,转化为byte数组存在TemplatesImpl 实例内
触发TemplatesImpl 实例的getTransletInstance 方法
利用TemplatesImpl类存储危险的字节码
这里强烈建议阅读原文,或者之后单独写篇javassist的字节码操作
留下两个相关知识点:
- class 和 byte[] 如何相互转换
- 使用javassist在class内插入static代码
相关代码逻辑在ysoserial.util.Gadgets#createTemplatesImpl上半部分
1 | public static TemplatesImpl createTemplatesImpl(final String command) throws Exception { |
ysoserial生成的class文件demo
触发TemplatesImpl类加载_bytecodes属性中的字节码
ysoserial对于TemplatesImpl调用链的解释:
1 | TemplatesImpl.getOutputProperties() |
相关代码逻辑在ysoserial.util.Gadgets#createTemplatesImpl下半部分
1 | // inject class bytes into instance |
实现代码执行
参考【2】中有实现,可以参考其中的TomcatEchoInject、TomcatShellInject
自定义继承AbstractTranslet类,static代码段为需要实现的代码
将该类class转为byte,存入TemplatesImpl byte数组即可
参考
- [1] java反序列化工具ysoserial分析
- [2] threedr3am/ysoserial
- [3] wh1t3p1g/ysomap