反序列化存在的意义是为了数据传输,类是无法直接进行传输的。通过序列化后转换为字符串格式或者JSON格式进行传输。
序列化与反序列化
-
seriallization 序列化 : 将对象转化为便于传输的格式, 常见的序列化格式:二进制格式,字节数组,json字符串,xml字符串。
-
deseriallization 反序列化:将序列化的数据恢复为对象的过程。
PHP反序列化漏洞
PHP反序列化
-
serialize()将对象序列化成字符串。
-
unserialize()将字符串反序列化回对象。
序列化
-
对象转换成字符串
-
方便传输
反序列化
-
字符串转换成对象
-
O:object
<?php
//创建类
class Stu{
public $name;
public $age;
public $sex;
}
//创建对象
$stu1 = new Stu();
$stu1->name = "wuhu";
$stu1->age = 18;
$stu1->sex = true;
var_dump($stu1);
echo "<hr />";
echo serialize($stu1);
?>
类中的魔术方法,在特定情况下会自动调用。即使魔术方法在类中没有被定义,也是真实存在的。
两个下划线:
- __construct():在创建对象时自动调用。
- __destruct()::在销毁对象时自动调用。
- __wakeup():unserialize()时会自动调用这个函数。
- __sleep():serialize()时会自动调用这个函数。
以_开头的函数,是PHP中的魔术方法,是为了更快的响应。__wakeup()和__sleep()方法在互联网上会被频繁调用。
反序列化漏洞不能通过黑盒测试来查找漏洞。只能通过白盒测试,也就是代码审计。
反序列化漏洞攻击者是不可控的,因为功能代码全是开发者自己写的。
<?php
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);
?>
什么是反序列化漏洞?
序列化和反序列化本身是为了实现数据在网络上完整高效的传输,但是由于反序列化过程中,对象的魔术方法会自动调用,魔术方法本身调用了别的方法,最终呈现一种链式调用,直到执行任意的代码或者命令。并且危险函数的参数可控。
修改序列化后的数据,目的是什么?
为了满足一定的条件以后实现链式调用。
Java反序列化漏洞
序列化:
ObjectOutputStream --> writeObject()
反序列化:
ObjectInputStream --> 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();
}
}
注意:想让某个类执行序列化或者反序列化必须实现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();
}
}
}
序列化后的字符串
说明:不同的编程语言的序列化和反序列化后的数据格式不一样。
那么漏洞点在哪里?
将Person类中的readObject方法注释了执行的时候,输出结果就是输出了反序列化后的结果。
那么如果重写readObject方法后,在方法中添加一个Runtime.getRuntime().exec("calc");
这行代码使用 Java 的 Runtime
类执行操作系统命令,即在 Windows 系统上运行计算器应用程序(calc)。执行结果如下:
在实际的开发环境中,需要重写readObject()方法,例如:从前端传递的值是base64编码的,而系统的方法不识别base64,所以需要在重写的readObject()方法中先解码,将解码完的对象再去调用系统的方法。
漏洞成因
Java反序列漏洞的成因是函数的链式调用,满足链式调用的全部条件,并且参数可控制。以及重写了readObject()方法,才能造成Java反序列漏洞。(条件苛刻)。当然如果没有重写readObject()方法,执行的就是系统的反序列化方法,也就没有了反序列化漏洞了。
什么是反序列化漏洞?
PHP的反序列化和java的反序列化是两种不同的类型,序列化和反序列化本身没有漏洞点,只是为了实现数据的完整高效的传输。
PHP反序列漏洞是由于类里面的魔术方法调用了某个函数,该危险函数又调用了别的函数,最终执行到了危险函数的位置。
JAVA反序列化漏洞是由于开发者重写了readObject方法,该readObject方法方法调用了别的方法,最终执行到了例如Transfrom方法的危险方法(链式调用)。文章来源:https://www.toymoban.com/news/detail-732146.html
shiro :爆破密钥,找寻CC利用链文章来源地址https://www.toymoban.com/news/detail-732146.html
到了这里,关于Java反序列化和PHP反序列化的区别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!