序列化与反序列化

PHP反序列化漏洞

序列化与反序列化

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

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

PHP反序列化

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

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

序列化

对象转换成字符串

方便传输

创建类

class Stu{

public $name;

public $age;

public $sex;

public $score;

}

创建对象(序列化)

$stu1 = new Stu();

$stu1->name = "xiu";

$stu1->age = 18;

$stu1->sex = true;

var_dump($stu1);

echo "<hr />";

echo serialize($stu1);

反序列化

字符串转换成对象

O:object

672163af60044e1faaa00e5131bde6ee.png

反序列化漏洞

以 __ 开头的函数,是PHP 中的魔术方法。

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

两个下划线

__construct() 在创建对象时自动调用

c3a09e174daf460b88999d7def85a8b3.png__destruct() 在销毁对象时自动调用

84a95a578e9241f3810cbef3539d18b4.png

__wakeup() unserialize()时会自动调用这个函数

32c5d05cbd4141a69a415bbde5ac7cdd.png

__sleep() serialize()时会自动调用这个函数

65b48b0da5df452ca19c8e2479acffd6.png

例子

<?php

class animal{
	public $name;
	public $age;
	
	public function __sleep(){
	if(@$_GET['cmd']=="xiu"){
		system('calc');
	}
	}
	
}

$an1=new animal;

$an1->name="dog";
$an1->age=3;

//var_dump($an1);

@serialize($an1);

?>

序列化和反序列化的作用

保证数据在互联网上完整高效的传输

什么是反序列化漏洞?

序列化和反序列化本身是为了保证数据在网络上完整高效的传输,但是由于反序列化过程中,某些函数会被自动调用,这个函数满足一定的条件前提下,去实现一种链式调用,最终调用到存在任意代码执行或者任意命令执行的恶意的函数的地方。

php反序列化漏洞

是由于他的魔术方法自动调用造成了一个链式的利用

java反序列化漏洞

是由于子类再重写父类的时候,造成了代码链式调用

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

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

JAVA反序列化漏洞

idea

aaf8db23ddcd46a4a4fd15b797274de3.png

类继承

子类自动继承了父类的所有公共成员属性和方法,主要是避免重复编写类似的代码。在Java中,一个类可以通过关键字extends继承自另一个类,成为其子类。被继承类称为父类。

public class Person {
    public int age;
    public String name;
    public void talk(){
        System.out.println("Person 说话了");
    }
}

定义一个类Person,里面添加了属性
    public :的意思是所有的类可以访问它
    整数型age年龄    
    字符串name姓名
    给它定义一个talk方法,实现输出一行字符

public class Student extends Person{

定义一个类Student这个类继承于Person这个类
    extends用于声明一个类指定他的父类

public class Test {
    public static void main(String[] args) {
        Student stu1 = new Student();
        stu1.talk();
    }
}

定义一个类Test,
    创建了一个名为stu1的student对象
    stu1.看对象有哪些属性,然后stu1调用了talk方法

5f62f4d1f4a847a2a6dad6c8915a86bd.png

e7d3c354da8349369f0cb09b3fd4df08.png

8d563d9f1c7b40df869afc4ccea256ae.png

05dbfda4ab0b49649c551f8fe8aafc80.png

类重写

重写是指子类中定义一个与父类中名称相同、但行为不同的方法的过程,也称为方法覆盖。重写的方法必须具有与父类方法相同的名称、参数列表和返回类型,且不能缩小或增加其访问权限。子类重写一个某个行为是为了实现自己特定的需求,即子类本着"用一种特殊的方式处理方法中的代码"的原则对父类的方法进行修改,以便更好地适应于子类自身的特殊要求

public class Person {
    public int age;
    public String name;
    public void talk(){
        System.out.println("Person 说话了");
    }
}

定义一个类Person,里面添加了属性
    public :的意思是所有的类可以访问它
    整数型age年龄
    字符串name姓名
    给它定义一个talk方法,实现输出一行字符

public class Student extends Person{
    public int score;
    public void talk(){
        System.out.println("Student 说话了");
    }
​
}

定义一个类Person,里面添加了属性
    public :的意思是所有的类可以访问它
    整数型score分数
    给它定义一个talk方法,实现输出一行字符

public class Test {
    public static void main(String[] args) {
        Student stu1 = new Student();
        stu1.talk();
    }
}

定义一个类Test,创建了一个名为stu1的student对象 
    stu1.看一样对象有哪些属性,调用了talk方法

5f62f4d1f4a847a2a6dad6c8915a86bd.png

6c5ad7cd7fef48559cd33b348b033824.png

8d563d9f1c7b40df869afc4ccea256ae.png

cc5455b28677485b89299f83d37bf000.png

数据前五个字节

rO0AB java序列化base64编码数据

aced 16进制java序列化序列化:
ObjectOutputStream --> writeObject()
反序列化: 
ObjectInputStream --> readObject()  

反序列化漏洞

编写JAVA反序列化的代码实现序列化与反序列化

定义了一个

person

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
​
public class Person implements Serializable {
public int age;
public String name;
}

定义一个Person的类,实现了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="xiu";
​
        serialize(p,"xiu.bin");
​
​
        System.out.println("反序列化结果:" + deserialize("xiu.bin"));
    }
//serialize接受两个参数,一个对象,一个文件路径,把序列化后的obj对象,储存到filePath指定的文件路径里
    public static void serialize(Object obj, String filePath) throws IOException {
        try (FileOutputStream fileOut = new FileOutputStream(filePath);
             ObjectOutputStream objectOut = new ObjectOutputStream(fileOut)) {
            objectOut.writeObject(obj);
        }
    }
//给deserialize一个文件路径,该函数会把这个文件的内容反序列化回对象。
    public static Object deserialize(String filePath) throws IOException, ClassNotFoundException {
        try (FileInputStream fileIn = new FileInputStream(filePath);
             ObjectInputStream objectIn = new ObjectInputStream(fileIn)) {
            return objectIn.readObject();
        }
    }
}
创建一个Person类和对象p,给对象设置属性,调用serialize方法将该对象序列化到指定的文件路径"xiu.bin"中。接着,调用deserialize方法,从刚才序列化的文件中读取数据,并将其反序列化为对象,并输出反序列化后的结果。

09a00d66747745e08baaa292e03a209e.png

126fa5640d7d4bdd8795ba5fcfec6540.png

6605436563ee4cccbc1444035f03f5f7.png

079a4659c68548aeadfe35cec96a0cc9.png

反序列化漏洞

重写readObject方法调用计算器,实现反序列化漏洞的原理

定义了一个

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();
    }
}
​
​

定义一个Person的类,实现了Serializable的接口,标识一个类可以被序列化(Serialized)和反序列化(Deserialized)
    里面有两个属性一个年龄一个姓名   
定义了一个ObjectInputStream的变量,变量里面包含readobject的方法,用于对象的反序列化
     Runtime.getRuntime().exec("calc");会在winodws中启动计算机程序

定义了一个

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="xiu";

        serialize(p,"xiu.bin");


        System.out.println("反序列化结果:" + deserialize("xiu.bin"));
    }
//serialize接受两个参数,一个对象,一个文件路径,把序列化后的obj对象,储存到filePath指定的文件路径里
    public static void serialize(Object obj, String filePath) throws IOException {
        try (FileOutputStream fileOut = new FileOutputStream(filePath);
             ObjectOutputStream objectOut = new ObjectOutputStream(fileOut)) {
            objectOut.writeObject(obj);
        }
    }
//给deserialize一个文件路径,该函数会把这个文件的内容反序列化回对象。
    public static Object deserialize(String filePath) throws IOException, ClassNotFoundException {
        try (FileInputStream fileIn = new FileInputStream(filePath);
             ObjectInputStream objectIn = new ObjectInputStream(fileIn)) {
            return objectIn.readObject();
        }
    }
}
创建一个Person类和对象p,给对象设置属性,调用serialize方法将该对象序列化到指定的文件路径"xiu.bin"中。接着,调用deserialize方法,从刚才序列化的文件中读取数据,并将其反序列化为对象,并输出反序列化后的结果。

创建一个Person类和对象p,给对象设置属性,调用serialize方法将该对象序列化到指定的文件路径"xiu.bin"中。接着,调用deserialize方法,从刚才序列化的文件中读取数据,并将其反序列化为对象,并输出反序列化后的结果。

b608aa1d487d4bfead736d100533c6b4.png

32f881e1e16a4565b996bc1c2cd732f8.png

e9aef1d499ee4fa08bdd1131c836714b.png

962db16d8f39428c8cf1af9d02e3425f.png

什么是反序列化漏洞

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

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

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Adler学安全

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值