XXXDISK网盘系统[简称:XXXDISK],是国内最大的网络存储、云存储系统开发及服务提供商,长期专注于网络存储系统开发,是一套采用PHP和MySQL构建的网络硬盘(文件存储管理)系统,可替代传统的FTP文件管理。友好的界面,操作的便捷深受用户的欢迎。
她是一套可用于网络上文件办公、共享、传递、查看的多用户文件存储系统。广泛应用于互联网、公司、网吧、学校等地管理及使用文件,多方式的共享权限,全方位的后台管理,满足从个人到企业各方面应用的需求。
最新版的下载地址为:
http://bbs1.phpdisk.com/thread-5384-1-1.html
之所以审计这套系统,是因为学校用的就是这个,在用历史漏洞拿下之后,学校给打上了补丁。但是,后来看着乌云上雨师傅、P牛等都审计出不少洞,想着如果我也审计出几个洞,是不是也能在几年之后变得那么强。于是就杠上了这套系统了。最后,在Windows平台的GBK版本上,挖掘到了一个无需登录的前台Getshell。
至于如何查看是啥版本,查看返回包的charset就行了。这里不多说,具体的瞅一眼代码就行。
本系统默认情况下的所有限制后缀都是通过黑名单的,此前也缝缝补补过好几个任意文件上传漏洞,但是作者忽略了或者说根本不了解Windows下的NTFS ADS流的trick。来看看此程序上传部分的逻辑。
所有文件上传操作都被封装在upload_file
函数中。
看看有哪些文件上传的地方:
总共有两处调用:第一处就是网站核心功能的文件上传,而第二处是给C/S客户端使用的,但是由于之前此处出现过很多次文件上传问题,已经被处理的没有办法使用了。
具体问题就是,默认此功能被修改成关闭了,原来雨牛挖掘的绕过签名,已经没办法使用了:
elseif(!$settings[open_phpdisk_client]){
$str = '总之就是没办法用了';
if(is_utf8()){
echo convert_str('utf-8','gbk',$str);
}else{
echo $str;
}
exit;
所以我们来看看第一处的文件上传, 位于modules/upload.inc.php
。
使用get_real_ext
函数处理了后缀。
get_real_ext
通过黑名单filter_extension
对后缀进行修改添加.txt
防止解析。
此处很明显可以绕过,如果我们控制文件名为1.php:$data
的话就可以绕过此处限制了。
不过此处还存在两个需要解决的问题,一个就是文件真实名称是强随机生成的,以及需要找到无需登录的上传利用点。
此程序为网盘程序,所以自然而然的需要用户登录才能上传。但是,来看看程序逻辑mydisk.php
:
需要经过phpdisk_core::user_login();
,才能包含upload
模块,上传文件。
我们来看看这个类方法的逻辑。
居然认证没通过只是302,并没有exit,所以此处可以无授权访问上传功能。
组合起来利用,构造文件上传包:
可以看到成功上传了。
但是还需要解决获取真实文件名的问题。这里有三种思路:
index.htm
,达成目录遍历我太菜了,这里只找到了几个sql注入,后面两种都没有实现。
此程序分为两个版本utf-8与gbk版,所以难免会有一些编码转换的地方,所以也难免发生不小心没有注意的地方。这里封装了一个编码转换的函数convert_str
,大多数编码转换都是使用使用的这个函数,但是这里都做了多次转义。搜索一下iconv
,会找到几处宽字节注入的。有一个是在UTF-8版本下的,但是位于客户端部分,需要开启了客户端才行。。。所以这里也限制了缺省条件下必须使用GBK版本。
这里利用的是位于ajax.php
的一处宽字节注入:
由于这个系统有全局过滤,所以想找到注入还是比较困难的,这里存在一个$file = unserialize(base64_decode($data));
,$data
是我们输入的,绕过了过滤。
将我们的输入base64解码后,反序列化成数组对象,最后传入sql语句。
$db->query_unbuffered(is_utf8() ? $sql : iconv('utf-8','gbk',$sql));
最后执行语句的时候存在一处编码转换,也是这里直接导致了注入。
并且是个比较好的利用点,这里是insert语句,存在回显,不用写脚本盲注。
最后,我们将这几个串联起来,就成了一个无需登录的Getshell,整条漏洞利用链为:
in_share
设置为1,这样就能未授权访问文件相关信息了。并且需要挑选足够合适的回显位。file_name
以及file_description
两个字段,其他字段长度都是不够存放回显的。这里我使用file_name
作为注入点,一开始偷懒想直接使用mysql的强制类型转换(select ''+hex((select user))
),把hex数据取出的,但是长度过长,精度丢失了...所以老老实实用file_description
传出数据吧。注入成功
获取回显
注入成功后,就需要想办法获取回显了,想要查看文件信息,需要获取文件ID。
这里其实如果你有账号的话(默认有测试账号并且允许注册),可以自己上传一个文件获取file_id,然后减1就是上个文件的file_id了。不过这里我们是无账号的前提条件,所以可以通过爆破,也挺快的。通过最近上传获取到位置靠后的文件,然后爆破一下file_id就行了。
最后找到了正确的文件id,访问即可在访问处获取真实文件名了。
getshell
最后这个程序已经停止更新维护了,所以发出来仅供学习参考。审计了几天,有点疲软,最后学校的那套系统不知道什么毛病,数据库一直报错,也没能利用成功2333。