此处仅作代码分析,不涉及环境配置及工具使用。

0x00 反序列化带来的安全问题

0x1 反射基础知识

反射是Java核心特征之一,反射允许运行中的Java程序获取自身的信息,并且可以操作类或对象的内部属性。
通过反射在运行时获得程序或程序集中每一个类型的成员和成员的信息, 反射机制可以动态地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以我们可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的。
反射的核心是 JVM 在运行时才动态加载类或调用方法/访问属性,它不需要事先(写代码的时候或编译期)知道运行对象是谁。
关于反射的基础知识,可以参考大佬的文章Java反射技术详解,讲的很好。这里不再赘述。

0x2 静态代理

代理是设计模式中的一种,可以在不修改原有对象的基础上通过代理对对象进行增强,添加额外的功能。代理有两种,一种叫静态代理,一种叫动态代理。
用一个生活中的例子来理解静态代理:
在司法实践中,案件诉讼的原被告可以请律师,这个过程就相当于案件当事人把案件委托给律师来代理,使用静态代理模式来模拟这个过程:
定义一个抽象的接口Speaker,代表说话这个能力:

package Main;
public interface Speaker {public void say();
}

然后定义一个实现该接口的当事人类Litigant,代表案件中的原被告:

package Main;
public class Litigant implements Speaker {@Overridepublic void say() {System.out.println("我有诉讼");}
}

然后定义一个律师类,律师类也实现了Speaker接口,同时有一个属性叫客户:

package Main;
public class Layer implements Speaker {private Litigant yuangao = new Litigant();@Overridepublic void say() {System.out.println("律师代理案件");yuangao.say();System.out.println("根据法律,应当......");}}

然后定义一个法庭类:

package Main;public class Court {public static void main(String[] args) {Layer zhangsan = new Layer();zhangsan.say();}
}

开庭,律师出席说话,在帮原告说话的同时自己也说了一些话,用自己的法律知识帮原告辩护,这就是“律师”对“原告”这个类进行了增强:

这就是静态代理。静态代理的缺陷也很明显,它的类型是事先预定好的,需要代理其他事情就得重新编写新的代理,比如要帮被告辩护就得重新定义一个律师,或者在律师类里新增一个属性,修改了代理类本身的结构。
为了解决这个缺陷产生了动态代理。

0x3 动态代理

Java提供了proxy类和InvocationHandler接口,可以生成动态代理类和动态代理对象。
还是用之前的例子,但因为律师分身乏术,不能一人同时代理两个人的案子,我们把律师升级成律师事务所:

package Main;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class Layers implements InvocationHandler{private Object litigant;public Layers(Object litigant) {this.litigant = litigant;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("案件开始,请我的委托人说话.");method.invoke(this.litigant,args);System.out.println("我的委托人的话说完了,根据法律,应该.....");return null;}
}

然后把当事人这个类稍微修改一下,分为“本地人"类和”外地人“类,方便后面演示:
本地人接口:

package Main;
public interface Speaker {public void say();
}

实现本地人接口的”本地人“类

package Main;
public class LocalLitigant implements Speaker {String type;public Litigant(String type) {this.type = type;}@Overridepublic void say() {System.out.println("我要诉讼"+this.type+"案子");}
}

外地人接口:

package Main;
public interface OtherSpeaker {public void othersay();
}

”外地人“类:

package Main;
public class Other implements OtherSpeaker {@Overridepublic void othersay() {System.out.println("我要请人代理案子(外地方言)");}
}

法庭类也作一定的变动:

package Main;
import java.lang.reflect.Proxy;
public class Court {public static void main(String[] args) {LocalLitigant zhangsan = new LocalLitigant("刑事案件");Layers layer1 = new Layers(zhangsan);Speaker proxy = (Speaker) Proxy.newProxyInstance(Court.class.getClassLoader(), new Class[] {Speaker.class}, layer1);proxy.say();}
}


为什么要这么做呢,当我们有一个继承了另一个接口的外地人的类实例也要来委托律师的时候,静态代理就需要修改律师类,而动态代理就不用:

package Main;
import java.lang.reflect.Proxy;
public class Court {public static void main(String[] args) {LocalLitigant zhangsan = new LocalLitigant("刑事案件");Layers layer1 = new Layers(zhangsan);Other lisi = new Other();Layers layer2 = new Layers(lisi);Speaker proxy = (Speaker) Proxy.newProxyInstance(Court.class.getClassLoader(), new Class[] {Speaker.class}, layer1);OtherSpeaker proxy2 = (OtherSpeaker) Proxy.newProxyInstance(Court.class.getClassLoader(), new Class[] {OtherSpeaker.class}, layer2);proxy.say();proxy2.othersay();}
}

0x4 Java中的序列化与反序列化

序列化是指把 Java 对象转换为字节序列的过程,反序列化是指把字节序列恢复为 Java 对象的过程,打过CTF的web选手都会对php的反序列化有所了解,这里就不再赘述。
Java语言中序列化的前提:要序列化的类必须实现java.io.Serializable 接口,而且该类的所有属性必须是可序列化的
JDK中的序列化API:
使用ObjectOutputStream(对象输出流) 和ObjectInputStream(对象输入流):
ObjectOutputStream 类通过使用writeObject(Object object) 方法,将对象以二进制格式进行写入。
ObjectInputStream 类通过使用readObject()方法,从输入流中读取二进制流转换成Java对象。

0x5 反序列化带来的安全问题

反序列化基于readObject()方法,如果该方法的内容可控,就会带来安全问题,比如任意代码执行:

Java代码审计学习笔记相关推荐

  1. Java NIO 学习笔记(三)----Selector

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...

  2. 可能是最全面的 Java G1学习笔记

    转载自 可能是最全面的 Java G1学习笔记 引子 最近遇到很多朋友过来咨询G1调优的问题,我自己去年有专门学过一次G1,但是当时只是看了个皮毛,因此自己也有不少问题.总体来讲,对于G1我有几个疑惑 ...

  3. 深入浅出 Java CMS 学习笔记

    转载自  深入浅出 Java CMS 学习笔记 引子 带着问题去学习一个东西,才会有目标感,我先把一直以来自己对CMS的一些疑惑罗列了下,希望这篇学习笔记能解决掉这些疑惑,希望也能对你有所帮助. 1. ...

  4. Java NIO学习笔记之图解ByteBuffer

    转载自 Java NIO学习笔记之图解ByteBuffer ByteBuffer前前后后看过好几次了,实际使用也用了一些,总觉得条理不够清晰. <程序员的思维修炼>一本书讲过,主动学习,要 ...

  5. 转载:mongoDB java驱动学习笔记

    http://www.blogjava.net/watchzerg/archive/2012/09/22/388346.html mongoDB java驱动学习笔记 指定新mongo实例: Mong ...

  6. 2019年Java Web学习笔记目录

    Java Web学习笔记目录 1.Java Web学习笔记01:动态网站初体验 2.Java Web学习笔记02:在Intellij里创建Web项目 3.Java Web学习笔记03:JSP元素 4. ...

  7. 【Java基础学习笔记】- Day11 - 第四章 引用类型用法总结

    Java基础学习笔记 - Day11 - 第四章 引用类型用法总结 Java基础学习笔记 - Day11 - 第四章 引用类型用法总结 4.1 class作为成员变量 4.2 interface作为成 ...

  8. Java 虚拟机学习笔记 | 类加载过程和对象的创建流程

    前言 创建对象是 Java 语言绕不开的话题,那么对象是如何创建出来的呢?我们今天就来聊一聊.对象创建第一步就是检查类是否加载,而类的加载又牵扯到类的加载过程.如果单说对象的创建而绕开类的加载过程,感 ...

  9. Java中大数据数组,Java基础学习笔记之数组详解

    摘要:这篇Java开发技术栏目下的"Java基础学习笔记之数组详解",介绍的技术点是"java基础学习笔记.基础学习笔记.Java基础.数组详解.学习笔记.Java&qu ...

最新文章

  1. 33个2017年必须了解的iOS开源库
  2. 大数据如何有序地“变废为宝”
  3. 增加数据_咱晋城人口又增加了?最新数据来了
  4. linux kill命令信号,Linux kill 命令详解
  5. 0.IT-解决方案-0-VOIP
  6. 20 行 Python 代码说清量子霸权!
  7. oracle 性能诊断工具,oracle性能诊断工具
  8. 神舟电脑怎么重装系统 神舟电脑重装系统步骤
  9. 求助vscode格式化插件beautify的用法
  10. Linux期末考试简答题
  11. 只保留3天!《算法学习》入门到进阶,超全配套案例下载
  12. BDD ROBDD
  13. iOS-计算两个日期之间的天数
  14. C语言实现求n的阶乘(n!),阶乘的和。
  15. ctfshow命令执行
  16. 偏最小二乘回归 Matlab
  17. c语言实现2048程序设计小游戏
  18. 【正点原子Linux连载】第三十二章 U-Boot启动流程详解 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0
  19. 从16K跳槽到20K,最后算下来年薪却还降了,我笑了····
  20. qt基本应用及技巧介绍

热门文章

  1. 请教一下如何使用mdx文件
  2. strtus1 html5,struts1.x的入门级学习教程
  3. 了解【泰科】协作机器人产品资料大全
  4. 项目部署-虚拟机-ip-Java变量-mysql-redis
  5. python基础部分
  6. ISO3834国际焊接认证简介
  7. 计算机网络原理-应用层
  8. C语言教程(五):选择结构
  9. Android屏幕适配之解决白屏启动的正确姿势
  10. [Python图像处理] 合成微缩效果