请勿截屏传播

反序列化漏洞

反序列化又叫对象注入,序列化在内部没有漏洞,漏洞产生是应该程序在处理对象、魔术函数以及序列化 相关的问题导致的 当传给 unserialize()的参数可控时,那么用户就可以注入 payload,进行反序列化的时 候就可能触发对象中的一些魔术方法。

1.反序列化漏洞原理

反序列化又叫对象注入,序列化在内部没有漏洞,漏洞产生是应该程序在处理对象、魔术函数以及序列化 相关的问题导致的 当传给 unserialize()的参数可控时,那么用户就可以注入 payload,进行反序列化的时 候就可能触发对象中的一些魔术方法。

2.如何判断是否为反序列化漏洞

1.定位反序列化入口点(Source)

首先,查找程序中所有进行反序列化的函数调用,这是漏洞的起点。

  • Java:重点关注 ObjectInputStream.readObject() 及其封装方法。
  • PHP:重点关注 unserialize() 函数。
  • Python:重点关注 pickle.loads() 等。
  • .NET:重点关注 `BinaryFormatter.Deserialize()。

2.追踪数据流(Sink)

确认反序列化的数据是否来自用户可控的输入,如 GET/POST 参数、Cookie、请求头、上传文件等。如果数据完全来自可信的、不可篡改的内部来源(如本地配置文件),风险会低很多。

3.寻找"Gadget 链"(Sink)

反序列化本身无害,危险在于后续被触发的代码。需要寻找程序中是否存在可利用的"代码片段链条",这条链最终会导向能执行危险操作的函数(Sink),如执行系统命令(Runtime.exec(), system())、读写文件等。这通常需要分析类中的魔术方法(如 PHP 的 __destruct()__wakeup(),Java 的 readObject()),它们会在反序列化过程中自动被调用。

3.反序列化里的魔法函数(PHP)

__construct() 当一个对象创建时被调用 __destruct() 当一个对象销毁前被调用 __sleep() 在对象被序列化前被调用 __wakeup 将在反序列化之后立即被调用 __toString 当一个对象被当做字符串使用时被调用 __get(),__set() 当调用或设置一个类及其父类方法中未定义的属性时 __invoke() 调用函数的方式调用一个对象时的回应方法 __call 和 __callStatic 前者是调用类不存在的方法时执行,而后者是调用类不存在的静态方式方法时执行

4.序列化字符串格式详解

每一种 PHP 数据类型在序列化后都有固定的表示格式。理解这些格式是读懂 payload 和后续手动修改序列化字符串的基础。

类型字母含义格式举例
s字符串s:长度:"内容";s:5:"admin";
S二进制字符串S:长度:"内容";\x00 写作 \00S:7:"\00*\00name";
i整数i:值;i:123;
d浮点数d:值;d:3.14;
b布尔数b:1;(true)或 b:0;(false)b:1;
a数组a:长度:{键;值;...}a:2:{i:0;s:1:"a";i:1;s:1:"b";}
O普通对象O:类名长度:"类名":属性个数:{...}O:4:"User":1:{s:4:"name";s:5:"admin";}
C自定义序列化对象C:类名长度:"类名":数据长度:{数据}实现 Serializable 接口的对象
N空值N;N;
R指针引用R:序号;R:2;(指向序列化中第 2 个对象)
r值引用r:序号;r:1;(指向序列化中第 1 个值)
Git 基础知识
PHP面向对象基础

评论区

评论加载中...