java反序列化学习与复现
0x00 前言
最近面试被问到了,学长说那位是大佬,还问了二进制(好久没学了突然问二进制,没准备只能知道啥答啥了qaq,怕是寄了),奈何自己一直没去了解java反序列化,虽然挖到过shiro反序列化,但是没有去详细了解,不过我呢要学就是那种详细了解的,最近一直在学红队的技术(内网渗透,还看了冰蝎的魔改,frp的魔改,确实大佬们挺强),和实战挖洞,不多说先实际操作。
0x01 基础知识(参考各种博客)
漏洞原理
当开发者自定义实现Serializable、添加自己的readObject()方法时,若readObject()方法内代码逻辑存在缺陷,则可能存在Java反序列化漏洞的风险。如果此时Java服务的反序列化API允许外部用户使用,则会导致攻击者使用精心构造的payload来利用反序列化漏洞达到任意代码执行的目的。
Java反序列化操作
实现方法
1.java.io.ObjectOutputStream
2.java.io.ObjectInputStream
序列化:ObjectOutputStream类 --> writeObject()
1 2
| 该方法对参数指定的obj对象进行序列化,把字节序列写到一个目标输出流中 按Java的标准约定是给文件一个.ser扩展名
|
反序列化: ObjectInputStream类 --> readObject()
1
| 该方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
|
感觉和php也有些相似hhhh
0x02 实验测试
1.简单实验
做一个简单的java反序列化实验,代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package java_Serializable;
import java.io.*;
public class Java_Test{
public static void main(String args[]) throws Exception { String obj = "zwz12138"; FileOutputStream fos = new FileOutputStream("1.txt"); ObjectOutputStream os = new ObjectOutputStream(fos); os.writeObject(obj); os.close();
FileInputStream fis = new FileInputStream("1.txt"); ObjectInputStream ois = new ObjectInputStream(fis);
String obj2 = (String)ois.readObject(); System.out.println(obj2); ois.close(); }
}
|
,说起来我也就学过假的java(手撕代码背书的那种),不过看着也还行,想起来某个文章说的
众所周知,Java代码开发与Java代码审计,并不是充分必要条件。
你问我懂不懂Java,那我当然是不懂的。
你问我能不能搞Java代码审计,其实也不是不能搞。
有一说一,好像确实hhhh
试了试,成功输出zwz12138
十六进制看了看1.txt,十六进制编码长这样
2.readObject()方法重写测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| package java_Serializable;
import java.io.*;
public class Main { public static void main(String[] args) throws Exception { Evil evil=new Evil(); evil.cmd="calc";
byte[] serializeData=serialize(evil); unserialize(serializeData); } public static byte[] serialize(final Object obj) throws Exception { ByteArrayOutputStream btout = new ByteArrayOutputStream(); ObjectOutputStream objOut = new ObjectOutputStream(btout); objOut.writeObject(obj); return btout.toByteArray(); } public static Object unserialize(final byte[] serialized) throws Exception { ByteArrayInputStream btin = new ByteArrayInputStream(serialized); ObjectInputStream objIn = new ObjectInputStream(btin); return objIn.readObject(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| package java_Serializable;
import java.io.*;
public class Evil implements Serializable{ public String cmd; private void readObject(java.io.ObjectInputStream stream) throws Exception { stream.defaultReadObject(); Runtime.getRuntime().exec(cmd); } }
|
这里我看也看明白了,就是原先定义的evil对象中cmd值为calc,但是在反序列化中调用重新定义的readObject()方法,把cmd的值直接执行了,结果就是调起了windows的计算器,可见攻击要点就是这个反序列化方法
0x03 结合CTF题复现分析
这里准备结合一道java反序列化的题目进行研究,搭建环境复现,后续写。