something about Pikachu - PHP serialize

pikachu

pikachu => 备份地址

PHP反序列化

概述

php中的serialize()unserialize()函数,可以将一个对象转变成可传输的字符串,以及从字符串 转换回对象。类似于javascript中的JSON.stringify(obj)JSON.parse(str)函数的功能。

PHP中的serialize规则:

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
// 有以下类:
class S{
public $paramA = "valueA";
public $paramB = "valueB";

function funA(){
echo "function A";
}

function __destruct(){
echo $this->paramA;
}
}

$obj = new S();
$objStr = serialize($obj);
echo $objStr;

// 序列化后的结果为
// O:1:"S":2:{s:6:"paramA";s:6:"valueA";s:6:"paramB";i:2;}

// O: 代表object; 1: 代表类名长度为1; "S": 类名为"S";
// 2: 代表类中有2个变量
// 变量一:
// s: 代表数据类型(变量名)为字符串; 6: 代表变量名长度为6; "paramA": 代表变量名为"paramA";
// s: 代表数据类型(变量值)为字符串; 6: 代表变量值长度为6; "valueA": 代表变量值为"valueA";
// 变量二:
// s: 代表数据类型(变量名)为字符串; 6: 代表变量名长度为6; "paramB": 代表变量名为"paramB";
// i: 代表数据类型(变量值)为数值型; 2: 代表变量值为2;

unserialize就是serialize的反向操作。
unserializeserialize本身没什么问题,但是当反序列化的内容受用户控制时,可能会造成 不正当使用,特别是后台使用了一些魔法函数时。

常见魔法函数如下:

  • __construct()

    对象被创建时被调用

  • __destruct()

    对象被销毁时被调用

  • __toString()

    当一个对象被当作一个字符串使用时被调用

  • __sleep()

    对象在被序列化之前被调用

  • __wakeup()

    当一个对象在被序列化之后被调用

例如上述class S{},可以构造对应payload使其具有恶意行为。

1
2
3
4
5
6
// 此时转义符号
// payload 为 O:1:"S":2:{s:30:"<script>alert('bad');</script>";s:6:"valueA";s:6:"paramB";i:2;}
$objStr = 'O:1:"S":2:{s:30:"<script>alert(\'bad\');</script>";s:6:"valueA";s:6:"paramB";i:2;}';
$obj = unserialize($objStr);
// 由于后序对$obj没有使用,垃圾回收时会销毁对象,因此调用`__destruct()`函数。
// 从而执行恶意代码

PHP反序列化漏洞

构造对应对象字符串:

1
// payload 为 O:1:"S":1:{s:4:"test";s:30:"<script>alert('bad');</script>";}