JAVA反序列化的简单探究

本文主要是探究,在反序列化过程中是怎么调用到readObject、readResolve、readExternal方法的问题

新建一个需要被序列化的类ObjectA,写入readResolve和readObject方法:

package com.yy.serialize.readResolve;

import java.io.IOException;
import java.io.Serializable; public class ObjectA implements Serializable {
private ObjectA() {
} private static final ObjectA objectA = new ObjectA(); public static ObjectA getInstance() {
return objectA;
}
private Object readResolve() {
System.out.println("执行了readResolve方法");
return objectA;
} private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
//执行默认的readObject()方法
in.defaultReadObject();
System.out.println("执行了readObject方法");
}
}

另一个类ObjectB则写入了readExternal方法:

package com.yy.serialize.readResolve;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput; public class ObjectB implements Externalizable {
@Override
public void writeExternal(ObjectOutput out) throws IOException {
System.out.println("执行了writeExternal");
} @Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
System.out.println("执行了readExternal");
}
}

测试类:

package com.yy.serialize.readResolve;

import java.io.*;

public class SerializeDemo {
public static void main(String[] args) throws Exception {
ObjectA objectA = ObjectA.getInstance();
ObjectB objectB = new ObjectB(); // 序列化
FileOutputStream fos = new FileOutputStream("a.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(objectA);
oos.flush(); // 反序列化
FileInputStream fis = new FileInputStream("a.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
ois.readObject(); }
}

运行测试类生成a.txt文件后,可以使用SerializationDumper查看字节流的数据:

这里有两个关键的标识

TC_OBJECT:标记后面的数据为Object对象

TC_CLASSDESC:类描述符标识,表示一个类中的所有信息

    TC_CLASSDESC - 0x72
className
Length - 36 - 0x00 24
Value - com.yy.serialize.readResolve.ObjectA - 0x636f6d2e79792e73657269616c697a652e726561645265736f6c76652e4f626a65637441
serialVersionUID - 0xee 44 c6 e6 0d b3 64 b5
newHandle 0x00 7e 00 00
classDescFlags - 0x02 - SC_SERIALIZABLE
fieldCount - 0 - 0x00 00
classAnnotations
TC_ENDBLOCKDATA - 0x78
superClassDesc
TC_NULL - 0x70

调用分析

ois.readObject下个断点

进入ObjectInputStream#readObject方法,看到其调用了readObject0

跟进readObject0,在此函数中,根据了tc值来进行switch,此时的tc值为TC_OBJECT,也就是0x73十进制数115

case TC_OBJECT中,调用了readOrdinaryObject

跟进readOrdinaryObject中,发现调用了readClassDesc方法,并把值赋给了desc

跟进readClassDesc,此方法用来分发处理字节流中TC_CLASSDESC的方法,用switch来选择需要处理的方法

tc的值就是TC_CLASSDESC的值0x72,转成10进制就是114,然后进入switch判断后转到case TC_CLASSDESC:

跟进readNonProxyDesc方法,调用了resolveClass方法后,把值赋给了cl

继续跟进resolveClass后,发现使用了Class.forName来创建了ObjectA对象,然后把创建的对象进行return返回

回到readNonProxyDesc,此时cl值变成了ObjectA对象,然后把cl对象传入了initNonProxy,并且赋值给了desc

最后readNonProxyDesc方法返回了desc的值

返回的desc的值赋给了调用处readClassDesc的descriptor,然后又进行了返回

最后回到了readOrdinaryObject方法中

在这里先总结下这几个方法分别做了什么操作

总结下上面的流程顺序为:

readOrdinaryObject -》 readClassDesc -》 readNonProxyDesc -》 readResolve方法

readClassDesc :分发用于处理字节流中TC_CLASSDESC的方法,用switch来选择需要处理的方法

readNonProxyDesc :真正用来处理字节流中的TC_CLASSDESC方法,会调用resolveClass进行创建反序列化的对象

resolveClass:是用Class.forName来创建ObjectA对象的地方,在这里可以做一个检查校验,用于反序列化拦截。weblogic中补丁拦截就是在此进行的

到这里三个方法都讲了用途后,还剩最后一个readOrdinaryObject 了

readOrdinaryObject

这里的readOrdinaryObject就是真正操作调用序列化类中,readObject、readResolve、readExternal方法的地方

接着上面debug,拿到了desc的值后往下走,做了一个判断desc.isExternalizable,如果序列化的接口是Externalizable类型,就进入readExternalData,否则进入readSerialData

此处的ObjectA对象接口类型是Serializable,所以进入了readSerialData方法

最后readSerialData方法中用了反射进行调用反序列化对象的readObject方法

回到readOrdinaryObject,接下来就是调用readResolve方法的地方了

用if进行判断,为true则用反射调用反序列化对象的readResolve方法

引用一张xz上师傅文章的流程图:

https://xz.aliyun.com/t/8443#toc-2

总结

方法调用的流程顺序:

readOrdinaryObject -》 readClassDesc -》 readNonProxyDesc -》 readResolve方法

readClassDesc :分发用于处理字节流中TC_CLASSDESC的方法,用switch来选择需要处理的方法

readNonProxyDesc :真正用来处理字节流中的TC_CLASSDESC方法,会调用resolveClass进行创建反序列化的对象

resolveClass:是用Class.forName来创建ObjectA对象的地方,在这里可以做一个检查校验,用于反序列化拦截。weblogic中补丁拦截就是在此进行的

readOrdinaryObject:用于调用序列化类中,readObject、readResolve、readExternal的方法

JAVA反序列化的简单探究的更多相关文章

  1. Java反序列化漏洞通用利用分析

    原文:http://blog.chaitin.com/2015-11-11_java_unserialize_rce/ 博主也是JAVA的,也研究安全,所以认为这个漏洞非常严重.长亭科技分析的非常细致 ...

  2. Java反序列化漏洞分析

    相关学习资料 http://www.freebuf.com/vuls/90840.html https://security.tencent.com/index.php/blog/msg/97 htt ...

  3. Java反序列化漏洞实现

    一.说明 以前去面试被问反序列化的原理只是笼统地答在参数中注入一些代码当其反序列化时被执行,其实“一些代码”是什么代码“反序列化”时为什么就会被执行并不懂:反来在运营商做乙方经常会因为java反反序列 ...

  4. 关于metaspolit中进行JAVA反序列化渗透RMI的原理分析

    一.背景: 这里需要对java反序列化有点了解,在这里得推广下自己的博客嘛,虽然写的不好,广告还是要做的.原谅我: 1.java反序列化漏洞原理研习 2.java反序列化漏洞的检测 二.攻击手法简介 ...

  5. Java反序列化漏洞的挖掘、攻击与防御

    一.Java反序列化漏洞的挖掘 1.黑盒流量分析: 在Java反序列化传送的包中,一般有两种传送方式,在TCP报文中,一般二进制流方式传输,在HTTP报文中,则大多以base64传输.因而在流量中有一 ...

  6. Java IO流简单使用

    Java IO流简单使用 也许是以前IO方面接触的比较少,我对于读和写的概念老是混淆. 趁着现在实习比较闲小结一下,我个人理解读和写都是针对程序,分别就是程序的输入和输出,或者叫读入写出. Java ...

  7. Lib之过?Java反序列化漏洞通用利用分析

    转http://blog.chaitin.com/ 1 背景 2 Java反序列化漏洞简介 3 利用Apache Commons Collections实现远程代码执行 4 漏洞利用实例 4.1 利用 ...

  8. 通过JBoss反序列化(CVE-2017-12149)浅谈Java反序列化漏洞

    前段时间学校学习J2EE,用到了jboss,顺便看了下jboss的反序列化,再浅谈下反序列化漏洞. Java序列化,简而言之就是把java对象转化为字节序列的过程.而反序列话则是再把字节序列恢复为ja ...

  9. 学习笔记 | java反序列化漏洞分析

    java反序列化漏洞是与java相关的漏洞中最常见的一种,也是网络安全工作者关注的重点.在cve中搜索关键字serialized共有174条记录,其中83条与java有关:搜索deserialized ...

随机推荐

  1. Vulhub-DC-4靶场

    Vulhub-DC-4靶场 前言 这套靶场的亮点在于对hydra的运用比较多,在遇到大容量字典的时候,BurpSuite可能会因为设置的运行内存的限制,导致字典需要花很长时间导入进去,虽然通过修改配置 ...

  2. 内置函数 字符串的复制 strcpy

    1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 5 6 void main() 7 ...

  3. Android开发如何准备技术面试(含Android面试押题)

    今年毋庸置疑是找工作的寒冬,每一个出来找工作的同学都是值得尊敬的.现在找工作,虽然略难,但是反过来看也会逼迫我们成为更加优秀的自己. 但是不管是旺季还是寒冬,有一些优秀的同学找工作还是挺顺利的.所以说 ...

  4. Spring Cloud Aliaba - Ribbon

    Ribbon(有关介绍见RestTemplate末尾) Ribbon负载均衡实现策略 Ribbon负载均衡实现策略通过接口IRule进行实现,默认使用ZoneAvoidanceRule规则进行负载均衡 ...

  5. Check Directory Existence in Shell

    The following command in one line can check if a directory exists. You can check the return value (& ...

  6. Grid布局如何设置动画效果

    CS代码 新增 GridLengthAnimation继承自AnimationTimeline public class GridLengthAnimation : AnimationTimeline ...

  7. 用Vsftpd服务传输文件

    文件传输协议 文件传输协议(FTP,File Transfer Protocol),即能够让用户在互联网中上传.下载文件的文件协议,而FTP服务器就是支持FTP传输协议的主机,要想完成文件传输则需要F ...

  8. Blazor Server 应用程序中进行 HTTP 请求

    翻译自 Waqas Anwar 2021年5月4日的文章 <Making HTTP Requests in Blazor Server Apps> [1] Blazor Server 应用 ...

  9. 【MyBatis系列5】MyBatis4大核心对象SqlSessionFactoryBuiler,SqlSessionFactory,SqlSession,Mapper

    前言 前几篇篇我们简单讲解了MyBatis的简单用法,以及一对一和一对多以及多对多的相关动态sql查询标签的使用,也提到了嵌套查询引发了N+1问题,以及延迟加载相关功能,本篇文章将会从MyBatis底 ...

  10. Qt迭代器(Java类型和STL类型)详解

    迭代器为访问容器类里的数据项提供了统一的方法,Qt 有两种迭代器类:Java 类型的迭代器和 STL 类型的迭代器. 两者比较,Java 类型的迭代器更易于使用,且提供一些高级功能,而 STL 类型的 ...