Met32
- 关注
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9

本文主要讲解反序列化漏洞方面的基础知识
1.什么是反序列化
在此之前,首先先简单说明一下,什么是反序列化
Java 序列化是指把 Java 对象转换为字节序列的过程;
Java 反序列化是指把字节序列恢复为 Java 对象的过程;
看完上面的简述,可能很多人似懂非懂。那就大白话说明一下...
比如你现在写一个项目,该项目有一个登录功能。该功能每次登录都需要从指定文件txt中读取账号密码进行登录。那么该文件内账号密码为明文的状态,肯定是不安全的。所以这个时候就用到了序列化与反序列化。当把账号密码序列化之后,里面的账号密码就会变成字节形式。当有人打开也会看不懂。只有进行反序列化才能恢复原样。
2.反序列化漏洞实例
首先看下面这段代码,如果在没有重写readObject的情况下,看一下会不会产生漏洞
public class MyObject implements Serializable { private String name; public void Run() throws IOException { Runtime.getRuntime().exec("calc.exe"); } } public static void main(String[] args) throws IOException, ClassNotFoundException { MyObject my = new MyObject(); ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("obj")); os.writeObject(my); os.close(); ObjectInputStream ins = new ObjectInputStream(new FileInputStream("obj")); MyObject obj = (MyObject)ins.readObject(); System.out.println(obj); ins.close(); }
很明显是不会产生的,这里是一个错误点,很多小伙伴都以为在readObject读取的时候,就会执行Run()方法中的命令。实则不是。
但是当我代码稍作改进,当执行readObject之后,在调用Run方法,就成功弹出计算器,因为这里已经进行了反序列化并在执行该方法
而当重写了readObject方法之后,就会产生漏洞
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException{ //执行默认的readObject()方法 //in.defaultReadObject(); Runtime.getRuntime().exec("calc.exe"); System.out.println("readObject重写调用"); }
从object文件中恢复对象的时候,就会调用类内的readObject方法
如果证实这个说法呢,下断点追了过来,果然跑到了类内的readObject
而重写的前提就是,在该方法内,要继续执行默认的readObject
如果没有执行in.defaultReadObject()
那么可以看当反序列化输出name的时候,为null
写上之后,说明默认的readObjcet已经进行了反序列化
可以看到此时的name已经被反序列化读取成功
3.结尾
本文主要讲解反序列化漏洞以及一些常见的"坑"
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)