• Java反序列化和PHP反序列化的区别



    反序列化存在的意义是为了数据传输,类是无法直接进行传输的。通过序列化后转换为字符串格式或者JSON格式进行传输

    序列化与反序列化

    • seriallization 序列化 : 将对象转化为便于传输的格式, 常见的序列化格式:二进制格式,字节数组,json字符串,xml字符串。

    • deseriallization 反序列化:将序列化的数据恢复为对象的过程。

    PHP反序列化漏洞

    PHP反序列化

    • serialize()将对象序列化成字符串。

    • unserialize()将字符串反序列化回对象。

    序列化

    • 对象转换成字符串

    • 方便传输

    反序列化

    • 字符串转换成对象

    • O:object

    
        //创建类
        class Stu{
            public $name;
            public $age;
            public $sex;
        }
    	
    	//创建对象
        $stu1 = new Stu();
        $stu1->name = "wuhu";
        $stu1->age = 18;
        $stu1->sex = true;
        var_dump($stu1);
        echo "
    "
    ; echo serialize($stu1); ?>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    image-20230915193800754

    类中的魔术方法,在特定情况下会自动调用。即使魔术方法在类中没有被定义,也是真实存在的。

    两个下划线:

    • __construct():在创建对象时自动调用。
    • __destruct()::在销毁对象时自动调用。
    • __wakeup()unserialize()时会自动调用这个函数
    • __sleep()serialize()时会自动调用这个函数

    以_开头的函数,是PHP中的魔术方法,是为了更快的响应。__wakeup()和__sleep()方法在互联网上会被频繁调用。

    反序列化漏洞不能通过黑盒测试来查找漏洞。只能通过白盒测试,也就是代码审计

    反序列化漏洞攻击者是不可控的,因为功能代码全是开发者自己写的。

    
    
        class animal{
            public $name;
            public $age;
    
            public function __sleep(){
                if(@$_GET['cmd']=="abc"){
                    a();
                }
            }
    
        }
    
        $an1=new animal;
    
        $an1->name="dog";
        $an1->age=3;
    
        //var_dump($an1);
    
        @serialize($an1);
    
    ?>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    image-20230915095903605

    什么是反序列化漏洞?

    序列化和反序列化本身是为了实现数据在网络上完整高效的传输,但是由于反序列化过程中,对象的魔术方法会自动调用,魔术方法本身调用了别的方法,最终呈现一种链式调用,直到执行任意的代码或者命令。并且危险函数的参数可控

    修改序列化后的数据,目的是什么?

    为了满足一定的条件以后实现链式调用。

    Java反序列化漏洞

    序列化

    ObjectOutputStream --> writeObject()
    
    • 1

    反序列化:

    ObjectInputStream --> readObject() 
    
    • 1

    实验

    Person类

    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.Serializable;
    
    public class Person implements Serializable {
        public int age;
        public String name;
    
        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
            Runtime.getRuntime().exec("calc");
            // 默认的反序列化操作
            in.defaultReadObject();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    注意:想让某个类执行序列化或者反序列化必须实现Serializable接口。

    Test类

    import java.io.*;
    
    public class Test {
        public static void main(String[] args) throws IOException, ClassNotFoundException {
            Person p=new Person();
            p.age=18;
            p.name="wuhu";
    		
            //将Person这个类的对象序列化后存放到wuhu.bin文件中
            //没有指定路径就表示存放到当前路径中
            serialize(p,"wuhu.bin");
    
    
            System.out.println("反序列化结果:" + deserialize("xiu.bin"));
        }
    	
        //序列化
        public static void serialize(Object obj, String filePath) throws IOException {
            try (FileOutputStream fileOut = new FileOutputStream(filePath);
                 ObjectOutputStream objectOut = new ObjectOutputStream(fileOut)) {
                objectOut.writeObject(obj);
            }
        }
    	
        //反序列化
        public static Object deserialize(String filePath) throws IOException, ClassNotFoundException {
            try (FileInputStream fileIn = new FileInputStream(filePath);
                 ObjectInputStream objectIn = new ObjectInputStream(fileIn)) {
                return objectIn.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
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    序列化后的字符串

    image-20230915200923576

    说明:不同的编程语言的序列化和反序列化后的数据格式不一样。

    那么漏洞点在哪里?

    将Person类中的readObject方法注释了执行的时候,输出结果就是输出了反序列化后的结果。

    image-20230915201540400

    那么如果重写readObject方法后,在方法中添加一个Runtime.getRuntime().exec("calc"); 这行代码使用 Java 的 Runtime 类执行操作系统命令,即在 Windows 系统上运行计算器应用程序(calc)。执行结果如下:

    image-20230915201716681

    在实际的开发环境中,需要重写readObject()方法,例如:从前端传递的值是base64编码的,而系统的方法不识别base64,所以需要在重写的readObject()方法中先解码,将解码完的对象再去调用系统的方法。

    漏洞成因

    Java反序列漏洞的成因是函数的链式调用,满足链式调用的全部条件,并且参数可控制。以及重写了readObject()方法,才能造成Java反序列漏洞。(条件苛刻)。当然如果没有重写readObject()方法,执行的就是系统的反序列化方法,也就没有了反序列化漏洞了。

    什么是反序列化漏洞?

    PHP的反序列化和java的反序列化是两种不同的类型,序列化和反序列化本身没有漏洞点,只是为了实现数据的完整高效的传输。

    PHP反序列漏洞是由于类里面的魔术方法调用了某个函数,该危险函数又调用了别的函数,最终执行到了危险函数的位置。

    JAVA反序列化漏洞是由于开发者重写了readObject方法,该readObject方法方法调用了别的方法,最终执行到了例如Transfrom方法的危险方法(链式调用)。

    shiro :爆破密钥,找寻CC利用链

  • 相关阅读:
    二、Prometheus常用exporter安装详解
    selenium 网页自动化-在访问一个网页时弹出的浏览器窗口,我该如何处理?
    动态主机配置协议(DHCP)解密:网络自动化与管理的关键
    wps卸载和重新安装
    [CCS][sysconfig] 图形化工具的使用说明
    miniconda设置清华源
    研究人员在宜家智能照明系统发现漏洞,攻击者可以利用这些漏洞导致灯泡闪烁恢复出厂设置
    OpenTiny Vue 支持 Vue2.7 啦!
    Java工具库Guava的不可变集合和新集合类型Multiset、Multimap、BiMap、RangeSet、RangeMap等的使用示例
    JS原型之属性设置和屏蔽,你能想到吗?
  • 原文地址:https://blog.csdn.net/weixin_58783105/article/details/132975714