背景
近来正好有时间研究java反序列漏洞,在此记录下java反序列化漏洞研究需要的基础知识。对于纯java小白来说,如果上来不了解java语法和一些基础特性,很难上来就说去分析java反序列化漏洞链和调试分析,因此掌握java的基本语法是十分必要的。本篇介绍的java反序列化漏洞必备知识主要包括如下内容,后续会不断补充:
1. java接口和继承
2. java class类和object类
3. 利用反射机制执行命令
4. java序列化和反序列化函数
必备知识
java接口和继承
java接口
接口是一个或多个抽象方法的集合,接口本身并没有任何关于方法的具体实现,接口以interface
关键字来声明。
接口无法被实例化,但是可以被类实现。一个实现接口的类,必须实现接口内所描述的所有方法。
接口注意事项:
- 类通过
Implentmens
关键字实现且可实现多个接口 - 接口可通过
extends
关键字继承其他多个接口 - 接口没有构造方法,接口中所有的方法必须是抽象方法
java继承
继承就是子类继承父类的特征和行为,使得子类对象具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为,使用extends
关键字实现。
继承注意事项:
- 子类拥有父类非 private 的属性和方法,也可自行扩展其他方法,甚至重写(不是重载)父类方法
- 类的继承是单继承,但是可以多重继承,如A继承B,B继承C
final
关键字可以把类定义为最终类(不能继承),或用于修饰方法,该方法不能被子类重写- 提高了类之间的耦合性,这是继承的缺点
java class类和object类
object类
在java中,包括String等关键字都是对象,即一切皆对象。类 Object 是根类,Object是所有类的父类。所有对象都实现这个类的方法。
Object类主要包含以下方法:
java中所有对象都具有以上方法
class类
class也是java的一个类,保存的是java运行时类的元信息,用来描述这个类的结构,如有哪些成员和方法。class类常用于java的反射,反射就是把java类中各种成分映射成一个个java对象,如下图是类的正常加载过程:
利用反射机制执行命令
在java反序列化漏洞中,有一类场景就是利用java的反射机制来进行命令执行,其实核心就是调用Runtime.getRuntime().exec("calc.exe");
,只不过是用反射来实现。win10环境的demo如下,经典的调用本地计算器:
public class test {
public static void main(String[] args) throws Exception {
//加载java.lang.Runtime库,返回getRuntime方法调用对象,且该方法无参
Object runtime = Class.forName("java.lang.Runtime").getMethod("getRuntime", null).invoke(null);
//调用exec函数,该函数有一个参数,参数类型是String类型,传入一个实参:calc.exe
Class.forName("java.lang.Runtime").getMethod("exec", String.class).invoke(runtime, "calc.exe");
//不用反射,直接调用也可以
//Object evil = Runtime.getRuntime().exec("calc.exe");
}
}
java序列化和反序列化函数
什么时候用序列化:
- 把的内存中的对象状态保存到文件或数据库中
- 在网络上传送对象的时候
java中类要实现序列化和反序列化只有两种方式:
- 实现Serializable接口
- 实现Externalizable接口
相比之下,后者的灵活度更高,可通过transient
来选择不想进行序列化的属性,当然程序员需要自己重写writeObject和readObject方法,采用Externalizable也无需产生序列化ID(serialVersionUID),java反序列化漏洞的攻击链中往往都是涉及到 接口的readobject函数。