序列化(serialize())与反序列化(unserialize())
平时zuoCTF题很多都会遇到序列化的问题,因为已经遇到过好几次了,所以打算写下来,就当作记录吧!忘了就来看看
0x00
序列化(serialize())
定义:序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。
作用:在序列化期间,将对象当前状态写入到临时或持久性存储区。也就是将对象转化为2进制字符串进行保存。
序列化的对象:可以是class也可以是Array,string等其他对象。
漏洞:~
代码实列
实例
<?php
$sites = array('Google', 'Runoob', 'Facebook');
$serialized_data = serialize($sites);
echo $serialized_data . PHP_EOL;
?>
输出结果为:
a:3:{i:0;s:6:"Google";i:1;s:6:"Runoob";i:2;s:8:"Facebook";}
0x01
反序列化(unserialize())
定义:反序列化是将存储好的或者进行传递的序列化后的字符串转化为对象,然后在用于对象的操作,是序列化的逆过程。
作用:恢复原本对象,用于程序或代码的各种操作。
反序列化的对象:序列化后的二进制字符串。
漏洞:unserialize()函数的参数可控。如果反序列化对象中存在魔术方法(特别的函数),而且其代码或变量用户可控,就可能产生漏洞,根据反序列化后不同的代码可以导致各种攻击,如代码注入、SQL注入、目录遍历等等。
color
PHP的类中可能会包含一些特殊的魔术方法,魔术方法命名是以符号__开头的。有以下的魔术方法:
__construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set(), _state(), __clone(), __debugInfo() 等等
代码实列
实例1
<?php
$str = 'a:3:{i:0;s:6:"Google";i:1;s:6:"Runoob";i:2;s:8:"Facebook";}';
$unserialized_data = unserialize($str);
print_r($unserialized_data);
?>
输出结果为:
Array
(
[0] => Google
[1] => Runoob
[2] => Facebook
)
当程序试图写入一个不存在或者不可见的成员变量时,PHP就会执行__set()方法。
__set()方法包含两个参数,分别表示变量名称和变量值,两个参数都不可省略。
实例2:
<?php
class SportObject{
private $type='';
public function __get($name){
if(isset($this->$name)){
echo'变量'.$name.'的值为:'.$this->$name.'<br>';
}else{
echo'变量'.$name.'未定义,初始化为0<br>';
$this->$name=0;
}
}
public function __set($name,$value){
if(isset($this->$name)){
$this->$name=$value;
echo'变量'.$name.'赋值为:'.$value.'<br>';
}else{
$this->$name=$value;
echo'变量'.$name.'被初始化为:'.$value.'<br>';
}
}
}
$MyComputer=newSportObject();
$MyComputer->type='DIY';
$MyComputer->type;
?>
例1 输出结果为:
变量type赋值为:DIY
变量type的值为:DIY
0x02
某魔术方法漏洞实列:
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
?code=
魔术方法_wakeup()存在漏洞,最后页面上输出的就是XCTF对象的一个序列化输出:
0:4"xctf":1:{s:4:"flag";s:3:"111";}
其中在XCTF类后面有一个数字1,整个1表示的就是XCTF类存在1个属性。
wakeup()漏洞就是与整个属性个数值有关。当序列化字符串表示对象属性个数的值大于真实个数的属性时就会跳过wakeup的执行。
当我们将上述的序列化的字符串中的对象属性个数修改为2,变为
0:4"xctf":2:{s:4:"flag";s:3:"111";}
这样就可以跳过了wakeup()方法的执行。
上一篇: C程序 ----求素数之和