JAVA反序列化的简单探究
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反序列化的简单探究的更多相关文章
- Java反序列化漏洞通用利用分析
原文:http://blog.chaitin.com/2015-11-11_java_unserialize_rce/ 博主也是JAVA的,也研究安全,所以认为这个漏洞非常严重.长亭科技分析的非常细致 ...
- Java反序列化漏洞分析
相关学习资料 http://www.freebuf.com/vuls/90840.html https://security.tencent.com/index.php/blog/msg/97 htt ...
- Java反序列化漏洞实现
一.说明 以前去面试被问反序列化的原理只是笼统地答在参数中注入一些代码当其反序列化时被执行,其实“一些代码”是什么代码“反序列化”时为什么就会被执行并不懂:反来在运营商做乙方经常会因为java反反序列 ...
- 关于metaspolit中进行JAVA反序列化渗透RMI的原理分析
一.背景: 这里需要对java反序列化有点了解,在这里得推广下自己的博客嘛,虽然写的不好,广告还是要做的.原谅我: 1.java反序列化漏洞原理研习 2.java反序列化漏洞的检测 二.攻击手法简介 ...
- Java反序列化漏洞的挖掘、攻击与防御
一.Java反序列化漏洞的挖掘 1.黑盒流量分析: 在Java反序列化传送的包中,一般有两种传送方式,在TCP报文中,一般二进制流方式传输,在HTTP报文中,则大多以base64传输.因而在流量中有一 ...
- Java IO流简单使用
Java IO流简单使用 也许是以前IO方面接触的比较少,我对于读和写的概念老是混淆. 趁着现在实习比较闲小结一下,我个人理解读和写都是针对程序,分别就是程序的输入和输出,或者叫读入写出. Java ...
- Lib之过?Java反序列化漏洞通用利用分析
转http://blog.chaitin.com/ 1 背景 2 Java反序列化漏洞简介 3 利用Apache Commons Collections实现远程代码执行 4 漏洞利用实例 4.1 利用 ...
- 通过JBoss反序列化(CVE-2017-12149)浅谈Java反序列化漏洞
前段时间学校学习J2EE,用到了jboss,顺便看了下jboss的反序列化,再浅谈下反序列化漏洞. Java序列化,简而言之就是把java对象转化为字节序列的过程.而反序列话则是再把字节序列恢复为ja ...
- 学习笔记 | java反序列化漏洞分析
java反序列化漏洞是与java相关的漏洞中最常见的一种,也是网络安全工作者关注的重点.在cve中搜索关键字serialized共有174条记录,其中83条与java有关:搜索deserialized ...
随机推荐
- Git-02-版本回退
环境准备 1 修改readme.txt内容 Git is a distributed version control system. Git is free software. 2 git statu ...
- 通过Mysql提权的几种姿势
本文记录利用mysql数据库,在拿到shell之后进行提权的两种方法. 一.UDF提权 原理:UDF是mysql的一个拓展接口,UDF(Userdefined function)让用户通过该接口可以自 ...
- Windows注册表内容详解(转载)
(关于windows注册表的整理,来源网络) 前提 一.什么是注册表 注册表是windows操作系统.硬件设备以及客户应用程序得以正常运行和保存设置的核心"数据库",也可以说是 ...
- 内存吞金兽(Elasticsearch)的那些事儿 -- 常见问题痛点及解决方案
1.大数据量的查询效率如何保证: 查询的流程:往 ES 里写的数据,实际上都写到磁盘文件里去了,查询的时候,操作系统会将磁盘文件里的数据自动缓存到 Filesystem Cache 里面去 最佳的情况 ...
- noip18
T1 来自cf原题 考场直接暴力枚举 \(A,B\),15pts. 正解: 首先时间的表达式,\(T=\frac{A}{a_{i}}+\frac{B}{b_{i}}\),然后以\(\frac{1}{a ...
- noip模拟10
被打回原形了emmmmm 贴张图吧,展示一下根本不行的水平 考试经过 上来浏览一遍T1到T3,读懂题之后发现都不是很可做 T1上了想到了前缀和,往矩阵快速幂想了一下觉得不可做,半小时之后还是只会\(n ...
- .NET Core 新特性:发布单文件可执行程序
一.前言 .NET Core 3.0中新增加了一个特性:Publishing Single EXEs,可以通过dotnet publish 命令将整个.net core应用发布为一个可执行文件. 二. ...
- ASP.NET Core:依赖注入
ASP.NET Core的底层设计支持和使用依赖注入.ASP.NET Core应用程序可以利用内置的框架服务将它们注入到启动类的方法中,并且应用程序服务能够配置注入.由ASP.NET Core提供的默 ...
- C# ThreadLocal源码追踪
ThreadLocal 字段成员: private Func<T>? _valueFactory; 一个获取默认值的委托 不同线程共享此成员. [ThreadStatic] private ...
- QT 中的QTableWidget