freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

JAVA反序列化漏洞剖析
2021-10-25 17:06:54

本文主要讲解反序列化漏洞方面的基础知识

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()方法中的命令。实则不是。

1635126586_61760d3a8fc3584f946ec.png!small?1635126599089

但是当我代码稍作改进,当执行readObject之后,在调用Run方法,就成功弹出计算器,因为这里已经进行了反序列化并在执行该方法1635126807_61760e17c8b3696cdf227.png!small?1635126820237

而当重写了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方法1635126955_61760eab5b51ef745458d.png!small?1635126967995

如果证实这个说法呢,下断点追了过来,果然跑到了类内的readObject

1635127052_61760f0c5c349efa461b5.png!small?16351270648331635127073_61760f210c09495d2ffc7.png!small?1635127085355

而重写的前提就是,在该方法内,要继续执行默认的readObject

如果没有执行in.defaultReadObject()

那么可以看当反序列化输出name的时候,为null1635127149_61760f6d0beae0c9a3350.png!small?1635127161666

写上之后,说明默认的readObjcet已经进行了反序列化

1635127326_6176101e9d696e7684736.png!small?1635127338921

可以看到此时的name已经被反序列化读取成功

3.结尾

本文主要讲解反序列化漏洞以及一些常见的"坑"

# web安全 # java反序列化 # Java反序列化漏洞分析
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录