6

Java反序列化-基础(一)

 2 years ago
source link: https://timeshu.github.io/2022/01/02/Java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96-%E5%9F%BA%E7%A1%80%E4%B8%80/#0x04-%E5%8F%82%E8%80%83%E9%93%BE%E6%8E%A5
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
Time'Blog

Java反序列化-基础(一)

发表于2022-01-02|更新于2022-01-02|代码审计
阅读量:189|评论数:0

OXO1 序列化介绍

​ 序列化(Serializable)是将数据对象转换成有序的字节流,便于保存在内存、文件、数据库中。而当需要使用数据时通过反序列化(Deserializable)的操作将字节流对象重建。

​ 在Java中序列化使用 ObjectiOutputStream类的writerObject()方法实现,反序列化使用ObjectInputStream类的readObjetion()方法实现。

  • ObjectiOutputStream 对象序列化流
    • writerObject() 序列化
  • ObjectInputStream 对象反序列化流
    • readObjetion() 反序列化
  • Serializable、Externalizable
    • 标记接口,没有方法或字段,一旦实现该接口,标志该类的对象是可序列化

而序列化的目的是为了让java对象脱离java运行环境的一种手段,可以实现网络传输(RMI RPC)对象持久化存储

0x02 序列化漏洞原理

测试代码:通过下面的小栗子来了解序列化

package com.time.Serializable;

import java.io.*;

public class Test {
public static void main(String[] args) throws Exception {
String obj = "初探Java序列化";

//序列化实现代码
FileOutputStream fos = new FileOutputStream("Object");//创建文件流
ObjectOutputStream os = new ObjectOutputStream(fos);//把对象转成字节数据流输出到文件中保存
os.writeObject(obj); //序列化对象,并写入文件
os.close();

//反序列化实现代码
FileInputStream fis = new FileInputStream("Object");
ObjectInputStream is = new ObjectInputStream(fis);

String obj1 = (String) is.readObject();//读取内容,并反序列化

System.out.println(obj1);

}
}

可以看见测试代码中,通过ObjectOutputStream类中的writeObject方法实现字符串的序列化,并写入了Object文件中。

使用xxd来读取Object文件的序列化内容

文件标识头:aced 0005 是java反序列化内容的特征

又通过ObjectInputStream类中的readObject方法实现字符串的反序列化,恢复对象内容,并输出。

0x03 反序列化漏洞之命令执行

在上述小栗子中,我们简单的了解了序列化和反序列化的过程,下面我们通过另外一个小栗子来执行系统命令。

测试代码:

TestDemo.java

package com.time.Serializable;

import java.io.*;

public class TestDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
MyObject mobj = new MyObject();
mobj.cmd = "wget http://localhost:8081/time";//执行的命令

FileOutputStream fos = new FileOutputStream("Object1");//创建文件流
ObjectOutputStream os = new ObjectOutputStream(fos);//把对象转成字节数据流输出到文件中保存
os.writeObject(mobj); //序列化对象,并写入文件
os.close();

FileInputStream fis = new FileInputStream("Object1");
ObjectInputStream is = new ObjectInputStream(fis);

MyObject obj1 = (MyObject) is.readObject();//读取内容,并反序列化

System.out.println(obj1.cmd);
is.close();
}
}


TestDemo文件中的代码和之前的没什么区别,只是修改了字符串,而重点在MyOjbect文件中

MyOjbect.java

package com.time.Serializable;

import java.io.IOException;

public class MyObject implements java.io.Serializable {
public String cmd;

private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException{
//执行默认的readObject()方法
in.defaultReadObject();
//执行命令
Runtime.getRuntime().exec(cmd);
}
}

可以看见MyOjbect类继承了Serializable 接口,标识是可以序列化的,而文件中重写了readObject方法,添加了命令执行代码,在我们调用readObject的的时候,会执行这段代码,执行结果如下。

本地搭建了一个服务器来获取访问信息,可以看见是成功执行了。

通过上述小栗子可以看出反序列化漏洞的危害,后续会更深入的学习反序列的漏洞及,以及反序列化漏洞利用工具-ysoserial中的利用链。

0x04 参考链接

https://mp.weixin.qq.com/s/CbMhYuYafHzglIQ_gogZPg

https://www.freebuf.com/articles/web/266523.html

https://xz.aliyun.com/t/10508#toc-8

https://xz.aliyun.com/t/6787


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK