序列化
serialize()
:用于序列化数组或对象,并返回一个字符串。把一个对象变成可以传输的字符串。
- 数组序列化
<?php
$arr = array('a', 'bb', 'ccc');
$serialized_arr = serialize($arr);
echo $serialized_arr;
?>
输出如下:
O
表示存储的是Object
对象,a
表示array
数组,s
表示string
字符型,i
表示int
数字型- 3代表有3个变量
- 花括号内:
i:0
表示index
为0,s
表示string
字符型,1
表示变量名的字符长度,a
表示变量名
a:3:{i:0;s:1:"a";i:1;s:2:"bb";i:2;s:3:"ccc";}
# 格式化
a:3:{
i:0;s:1:"a";
i:1;s:2:"bb";
i:2;s:3:"ccc";
}
- 对象序列化
<?php
class name1 {
var $test1;
var $test2;
}
$test3 = new name1;
$test3->test1 = 'hi';
$test3->test2 = 'fun';
echo serialize($test3);
?>
输出如下
O:5:"name1":2:{s:5:"test1";s:2:"hi";s:5:"test2";s:3:"fun";}
# 格式化
O:5:"name1":2:{
s:5:"test1";
s:2:"hi";
s:5:"test2";
s:3:"fun";
}
反序列化
unserialize()
- 数组反序列化
<?php
$arr = array('a', 'bb', 'ccc');
$serialized_arr = serialize($arr);
$unserialized_arr = unserialize($serialized_arr);
print_r($unserialized_arr);
?>
输出
Array
(
[0] => a
[1] => bb
[2] => ccc
)
- 对象反序列化
<?php
class temp {
var $test1;
var $test2;
}
$test3 = new temp;
$test3->test1 = 'hi';
$test3->test2 = 'fun';
$serialized_obj = serialize($test3);
$unserialized_obj = unserialize($serialized_obj);
print_r($unserialized_obj);
?>
输出
name1 Object
(
[test1] => hi
[test2] => fun
)
危险魔法函数
- 构造函数
__construct()
:当new
创建对象时会自动调用。但在unserialize()
时不会自动调用 - 析构函数
__destruct()
:当对象被销毁时会自动调用 __wakeup()
:当调用unserialize()
函数时会自动调用__sleep()
:当调用serialize()
函数时自动调用
漏洞原理
- 正常调用反序列化
<?php
class temp{
var $test = '123';
}
$obj = 'O:4:"temp":1:{s:4:"test";s:3:"123";}';
print_r($obj);
echo "</br>";
$un_obj = unserialize($obj);
print_r($un_obj);
echo "</br>";
?>
输出:
O:4:"temp":1:{s:4:"test";s:3:"123";}</br>
temp Object(
[test] => 123
)</br>
- 而假如在类中重写了危险的魔法函数,则可能存在漏洞
<?php
class temp{
var $test = '123';
function __wakeup(){
echo "【Wakeup】";
echo "</br>";
}
function __construct(){
echo "【construct】";
echo "</br>";
}
function __destruct(){
echo "【destruct】";
echo "</br>";
}
}
$obj = 'O:4:"temp":1:{s:4:"test";s:3:"123";}';
print_r($obj);
echo "</br>";
$un_obj = unserialize($obj);
print_r($un_obj);
echo "</br>";
?>
输出:为了方便观察,这里将输出格式化了一下,分成4个部分
- 先输出
print_r($obj)
部分 - 然后下面反序列化
$obj
并赋值给$un_obj
时,因为调用了反序列化函数unserialize()
,因此也调用了__wakeup()
函数 - 输出
print_r($un_obj)
的内容 - 最后类销毁时调用了
__destruct()
函数
O:4:"temp":1:{s:4:"test";s:3:"123";}</br>
【Wakeup】</br>
temp Object(
[test] => 123
)</br>
【destruct】</br>
漏洞利用
举个别人的例子:
<?php
class A{
var $test = "demo";
function __destruct(){
echo $this->test;
}
}
$a = $_GET['test'];
$a_unser = unserialize($a);
?>
- 假如构造payload:
http://www.xxx.com/?test=O:1:"A":1{s:4"test";s:5:"hello";}
,就能控制echo输出的变量
版权属于:Naraku
本文链接:https://www.naraku.cn/posts/20.html
本站所有原创文章均采用 知识共享署名-非商业-禁止演绎4.0国际许可证 。如需转载请务必注明出处并保留原文链接,谢谢~