> 文章列表 > JAVA反序列化漏洞基础

JAVA反序列化漏洞基础

序列化是啥?简单概括,就是把保存在文件里的对象“复活”回来。你想想,对象就像个玩具,玩累了保存起来,想玩的时候再拿出来。但是,这个过程可不是简单的存档读档哦!如果不好好处理,可能被黑灰产玩坏!就像有个叫Y serialized的坏蛋,专门拿反序列化漏洞干坏事。比如,如果你不小心让系统执行了这些被“复活”的恶意代码,那分分钟就被Hack了!

为什么transient这个词这么重要?因为它就像一道符咒,阻止变量被序列化。比如age这个属性,虽然在内存里活得好好的,但一旦被打包成序列化对象,它就隐身了!这样虽然安全了,但也带来问题:比如当你需要age的时候,它不在序列化文件里,得手动重新初始化,可就麻烦了!

你好奇为什么说反序列化这么危险吗?因为它就像一个神奇的复活术,能把你对象的所有魔法都唤醒,包括那些隐藏的、没写出来的魔法!比如你定义了一个addressCheck的方法,在反序列化的时候,它可不会因为不在序列化流里就不执行哦!如果addressCheck是个危险的方法,比如删除文件啥的,那中招了就完犊子了!所以,反序列化一定要像防小三一样防,必须验证来源,确保每一步都安全!

还有,你知道吗?很多大厂都因为反序列化漏洞被黑过,比如Apache Struts2的 CVE-2017-5638!所以,下次用反序列化的时候,记得要对数据进行严格的校验,最好使用@Serial注解或者自己实现readObject方法,防止意外情况的发生哦!对了,如果你用的不是必须的序列化方式,尽量别用Serializable,改用Parcelable或者其他更安全的方式,这样就不用担心反序列化漏洞了!

JAVA反序列化漏洞基础

ObjectOutputStream

package com.test;
public class Employee implements java.io.Serializable{public String name;public String address;public transient int age; // transient瞬态修饰成员,不会被序列化public void addressCheck(){System.out.println("Address check : " + name + " -- " + address+" -- "+age);//此处省略tostring等方法}@Overridepublic String toString() {return "Employee{" +"name='" + name + '\\'' +", address='" + address + '\\'' +", age=" + age +'}';}
}
import com.test.Employee;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class SerializeDemo {public static void main(String[] args) throws IOException{Employee e = new Employee();e.name = "zhangsan";e.age = 20;e.address = "shenzhen";
// 1.创建序列化流try(ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("ser.txt"));) {outputStream.writeObject(e);// 2.写出对象}catch (IOException e1){e1.printStackTrace();}
// 3.释放资源}
}

ObjectInputStream

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class DeserializeDemo {public static void main(String[] args) throws IOException,ClassNotFoundException {
// 1.创建反序列化流FileInputStream fileInputStream = new FileInputStream("ser.txt"