Print document Edit on github

Java 反序列化浅谈

序列化和反序列化是一种常见的编程思想;

php、python也都存在此种机制。序列化就是将对象转化成字节流,便于保存在内存、文件或者数据库中(保存此对象的状态)。 反序列化就是将字节流转化为对象。

我们来做个简单的小实验: 定义People class -> name、age,在web中很常见:

import java.io.Serializable;

public class People implements Serializable {
    public String name;
    public int age;
    public String getName() {
        return name;}

    public void setName(String name) {
        this.name = name;}

    public int getAge() {
        return age;}

    public void setAge(int age) {
        this.age = age;}
}

调用序列化接口把我们的Java对象转化为byte[]数组,将二进制内容写入People.txt文档:

➜ file People.txt 
People.txt: Java serialization data, version 5
➜ xxd People.txt
00000000: aced 0005 7372 0006 5065 6f70 6c65 4499  ....sr..PeopleD.
00000010: 4080 2db3 403b 0200 0249 0003 6167 654c  @.-.@;...I..ageL
00000020: 0004 6e61 6d65 7400 124c 6a61 7661 2f6c  ..namet..Ljava/l
00000030: 616e 672f 5374 7269 6e67 3b78 7000 0000  ang/String;xp...
00000040: 1274 0008 7869 616f 6d69 6e67            .t..xiaoming

➜ java Test
people对象序列化成功!
#将序列化数据写入People.txt
people对象反序列化成功!
#读取People.txt反序列化从字节流读取Java对象
xiaoming
18

下一步就是模拟反序列化攻击;我们添加以下攻击代码:

public class People implements Serializable {
    //添加以下方法,重写People类的readObject()方法
    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException{
        //执行默认的readObject()方法
        in.defaultReadObject();
        //执行打开计算器程序命令
        Runtime.getRuntime().exec("calc.exe");
    }
}

所以简而言之,web中传入的反序列化RCE的poc必然是传入参数可控。效果:

GKTt6uvjdh1g5QY.png

参考