JAVA反序列化漏洞入门学习笔记(一)--反序列化简介
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
JAVA反序列化漏洞⼊门学习笔记(⼀)--反序列化简介JAVA 真的令⼈头⼤
参考⽂章
JAVA 序列化与反序列化
简介
同 PHP/Python 类似,java 序列化的⽬的是将程序中对象状态转换成以数据流形式,反序列化是将数据流恢复为对象。
此举可以有效地实现多平台之间的通信、对象持久化存储。
序列化实例
import java.io.*;
//定义⼀个可序列化的类,该类必须实现 java.io.Serializable 接⼝
class Giao implements java.io.Serializable
{
public String name;
public String motto;
public void saygiao()
{
System.out.println(this.motto);
}
// ⾃定义 readObject ⽅法
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException{
//执⾏默认的readObject()⽅法
in.defaultReadObject();
//执⾏命令
Runtime.getRuntime().exec("calc.exe");
}
}
//序列化/反序列化
public class SerializeGiao
{
public static void main(String [] args) throws IOException, ClassNotFoundException{
//实例化⼀个可序列化对象
Giao testClass = new Giao();
= "说唱带师";
testClass.motto = "⼀给我哩 giao giao!";
//序列化
//将序列化后的对象写⼊到⽂件
FileOutputStream fos = new FileOutputStream("test.ser");
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(testClass);
os.close();
fos.close();
//反序列化
Giao obj = null;
//从⽂件读取序列化的结果后进⾏反序列化
FileInputStream fis = new FileInputStream("test.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
obj = (Giao)ois.readObject();
ois.close();
fis.close();
System.out.println();
System.out.println(obj.motto);
}
}
//由此可见:⼈⽣苦短,我⽤ Python
序列化结果:
反序列化结果:
序列化条件
⼀个类的对象要想序列化成功,必须满⾜两个条件:
该类必须实现 java.io.Serializable 或 java.io.Externalizable 接⼝。
Externalizable 接⼝继承⾃ Serializable 接⼝,实现Externalizable 接⼝的类完全由⾃⾝来控制序列化的⾏为,⽽仅实现 Serializable 接⼝的类可以采⽤默认的序列化⽅式。
class Giao implements java.io.Serializable{}
该类的所有属性必须是可序列化的。
如果有⼀个属性不是可序列化的,则该属性必须注明是短暂的。
实现序列化/反序列化的⽅法
其中实现序列化与反序列化的两个类为:
java.io.ObjectOutputStream
序列化:⾸先给该类传⼊⼀个⽂件对象(⽤于写⼊序列化结果),然后通过调⽤该类的 writeObject(⽬标对象) ⽅法将⽬标对象写⼊到⽂件
java.io.ObjectInputStream
反序列化:⾸先给该类传⼊⼀个⽂件对象(⽤于读取⽂件中的序列化结果),然后通过调⽤该类的 readObject() ⽅法将其反序列化为⽬标对象
看到下⾯代码的执⾏结果:
输出了1ndex,说明反序列化时调⽤了⽤户类 Giao 中的 readObject ⽅法,并且当我注释in.defaultReadObject();代码,实际会输出 null
因此,实际上完成反序列化的操作的具体步骤是⽤户类 Giao 中的 readObject ⽅法,也就是继承⾃ Serializable 接⼝的 readObject ⽅法
为什么会出现反序列化漏洞
当被反序列化的数据流⽤户可控时,那么攻击者即可通过构造恶意输⼊,让反序列化产⽣⾮预期的对象,在此过程中执⾏构造的任意代码
关键点在于⽤户⾃定义类中的 readObject() ⽅法形成了不安全的类,导致了反序列化安全问题
简单的 demo
漏洞代码:
class RCE implements java.io.Serializable {
public String cmd;
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
Runtime.getRuntime().exec(cmd);
}
public class ToRCE{
public static void main(String[] args) throws IOException, ClassNotFoundException {
RCE testClass = new RCE();
testClass.cmd = "calc";
FileOutputStream fileoutputstream = new FileOutputStream("RCE.ser");
ObjectOutputStream outputstream = new ObjectOutputStream(fileoutputstream);
outputstream.writeObject(testClass);
outputstream.close();
FileInputStream fileinputstream = new FileInputStream("RCE.ser");
ObjectInputStream inputstream = new ObjectInputStream(fileinputstream);
RCE obj = (RCE)inputstream.readObject();
inputstream.close();
}
}
看完上⾯的代码,是不是觉得 JAVA 反序列化漏洞跟 PHP 反序列化漏洞有些相似
但是怎么会有⼈写这么愚蠢的代码呢?JAVA 反序列化的⾼端操作还得看构造反序列化链
JAVA 反序列化漏洞⼊门学习笔记(⼆):。