代码审计 xxxdisk前台Getshell

2019-07-08 约 103 字 预计阅读 1 分钟

声明:本文 【代码审计 xxxdisk前台Getshell】 由作者 lz1y 于 2019-07-08 09:10:00 首发 先知社区 曾经 浏览数 191 次

感谢 lz1y 的辛苦付出!

0x0 xxxdisk

XXXDISK网盘系统[简称:XXXDISK],是国内最大的网络存储、云存储系统开发及服务提供商,长期专注于网络存储系统开发,是一套采用PHP和MySQL构建的网络硬盘(文件存储管理)系统,可替代传统的FTP文件管理。友好的界面,操作的便捷深受用户的欢迎。

她是一套可用于网络上文件办公、共享、传递、查看的多用户文件存储系统。广泛应用于互联网、公司、网吧、学校等地管理及使用文件,多方式的共享权限,全方位的后台管理,满足从个人到企业各方面应用的需求。
最新版的下载地址为:
http://bbs1.phpdisk.com/thread-5384-1-1.html

0x1 起步

之所以审计这套系统,是因为学校用的就是这个,在用历史漏洞拿下之后,学校给打上了补丁。但是,后来看着乌云上雨师傅、P牛等都审计出不少洞,想着如果我也审计出几个洞,是不是也能在几年之后变得那么强。于是就杠上了这套系统了。最后,在Windows平台的GBK版本上,挖掘到了一个无需登录的前台Getshell。

至于如何查看是啥版本,查看返回包的charset就行了。这里不多说,具体的瞅一眼代码就行。

0x2 Windows文件上传绕过

本系统默认情况下的所有限制后缀都是通过黑名单的,此前也缝缝补补过好几个任意文件上传漏洞,但是作者忽略了或者说根本不了解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的话就可以绕过此处限制了。
不过此处还存在两个需要解决的问题,一个就是文件真实名称是强随机生成的,以及需要找到无需登录的上传利用点。

0x3 权限绕过

此程序为网盘程序,所以自然而然的需要用户登录才能上传。但是,来看看程序逻辑mydisk.php

需要经过phpdisk_core::user_login();,才能包含upload模块,上传文件。
我们来看看这个类方法的逻辑。

居然认证没通过只是302,并没有exit,所以此处可以无授权访问上传功能。

0x4 未授权上传

组合起来利用,构造文件上传包:

可以看到成功上传了。

但是还需要解决获取真实文件名的问题。这里有三种思路:

  • 找到sql注入,注入出真实文件名
  • 删除index.htm,达成目录遍历
  • 使用Windows下的部分PHP函数的正则匹配(案例:DEDECMS寻找后台)

我太菜了,这里只找到了几个sql注入,后面两种都没有实现。

0x5 宽字节注入若干

此程序分为两个版本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语句,存在回显,不用写脚本盲注。

0x6 最终利用

最后,我们将这几个串联起来,就成了一个无需登录的Getshell,整条漏洞利用链为:

  1. 上传文件

  1. 通过注入获取文件真实名称(其实也能直接注入获取管理员密码(md5),然后把黑名单修改一下)
    这里需要注意的是,为了获取回显,需要在insert中将文件属性in_share设置为1,这样就能未授权访问文件相关信息了。并且需要挑选足够合适的回显位。

    除了file_name以及file_description两个字段,其他字段长度都是不够存放回显的。这里我使用file_name作为注入点,一开始偷懒想直接使用mysql的强制类型转换(select ''+hex((select user))),把hex数据取出的,但是长度过长,精度丢失了...所以老老实实用file_description传出数据吧。
    payload:

注入成功

  1. 获取回显
    注入成功后,就需要想办法获取回显了,想要查看文件信息,需要获取文件ID。

    这里其实如果你有账号的话(默认有测试账号并且允许注册),可以自己上传一个文件获取file_id,然后减1就是上个文件的file_id了。不过这里我们是无账号的前提条件,所以可以通过爆破,也挺快的。通过最近上传获取到位置靠后的文件,然后爆破一下file_id就行了。

    最后找到了正确的文件id,访问即可在访问处获取真实文件名了。

  2. getshell

结语

最后这个程序已经停止更新维护了,所以发出来仅供学习参考。审计了几天,有点疲软,最后学校的那套系统不知道什么毛病,数据库一直报错,也没能利用成功2333。

关键词:[‘安全技术’, ‘漏洞分析’]


author

旭达网络

旭达网络技术博客,曾记录各种技术问题,一贴搞定.
本文采用知识共享署名 4.0 国际许可协议进行许可。

We notice you're using an adblocker. If you like our webite please keep us running by whitelisting this site in your ad blocker. We’re serving quality, related ads only. Thank you!

I've whitelisted your website.

Not now