微擎cms整理
又是一次失败的rce审计
最新痴迷与找cms的反序列化漏洞,相对于框架而且,cms的难度大了许多,重要的是就算有反序列化的触发点,也不一定有反序列化的利用链
而且,在框架二次开发的cms中,利用链随随便便用,但是在单一cms,就需要特定的条件
微擎cms中site的entry的访问机制
听说之前存在未授权的,现在不得行了
model的获取是根据数据库ims_modules的那么参数获取的
这个时候如果存在direct变量就可以绕过登录检查
1 2 3 4 5 6 7 8 9 10 11 12
| if (!$entry['direct']) { checklogin(); $referer = (url_params(referer())); if (empty($_W['isajax']) && empty($_W['ispost']) && empty($_GPC['version_id']) && intval($referer['version_id']) > 0 && ('wxapp' == $referer['c'] || 'site' == $referer['c'] && in_array($referer['a'], array('entry', 'nav')) || 'home' == $referer['c'] && 'welcome' == $referer['a'] || 'module' == $referer['c'] && in_array($referer['a'], array('manage-account', 'permission')))) { itoast('', $_W['siteurl'] . '&version_id=' . $referer['version_id']); } ... }
|
但是这个是访问addons下的模块并创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| if (!defined('IN_MOBILE') || !class_exists($classname)) { $classname = "{$name}ModuleSite"; if (!class_exists($classname)) { $file = IA_ROOT . "/addons/{$name}/site.php"; if (!is_file($file)) { $file = IA_ROOT . "/framework/builtin/{$name}/site.php"; } if (!is_file($file)) { trigger_error('ModuleSite Definition File Not Found ' . $file, E_USER_WARNING);
return null; } require $file; } }
|
没有的话就放弃吧,我本来是以为可以未首权访问当前site模块下的任意方法,其实不是
微擎cms的加载机制
load方法
- load()->model() //加载模块
- load()->func() //加载方法
- load()->class() //加载类
- load()->library() //加载类库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| function load() { static $loader; if (empty($loader)) { $loader = new Loader(); }
return $loader; } ... ...
private $libraryMap = array( 'agent' => 'agent/agent.class', 'captcha' => 'captcha/captcha.class', 'pdo' => 'pdo/PDO.class', 'qrcode' => 'qrcode/phpqrcode', 'ftp' => 'ftp/ftp', 'pinyin' => 'pinyin/pinyin', 'pkcs7' => 'pkcs7/pkcs7Encoder', 'json' => 'json/JSON', 'phpmailer' => 'phpmailer/PHPMailerAutoload', 'oss' => 'alioss/autoload', 'qiniu' => 'qiniu/autoload', 'cosv5' => 'cosv5/index', 'sentry' => 'sentry/Raven/Autoloader', );
|
之前的研究中,确定guzzlehttp第三方类库是存在完整的反序列化利用链的
在微擎cms中cosv5引用了此类库
要想利用反序列化利用链,需要查找,在什么地方调用了此类库
在系统定义的file_remote_upload方法中调用了此类库

在调用file_remote_upload的方法中有一处调用了file_delete方法

简单跟了下file_delete方法,以及其调用的过滤方法,对phar没什么影响就是不能使用../跳转目录了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| function file_delete($file) { global $_W; if (empty($file)) { return false; } $file = safe_gpc_path($file); $file_extension = pathinfo($file, PATHINFO_EXTENSION); if (in_array($file_extension, array('php', 'html', 'js', 'css', 'ttf', 'otf', 'eot', 'svg', 'woff'))) { return false; }
$uni_remote_setting = uni_setting_load('remote'); if (empty($uni_remote_setting['remote']) && empty($_W['setting']['remote']['type'])) { if (file_exists(ATTACHMENT_ROOT . '/' . $file) && file_is_uni_attach(ATTACHMENT_ROOT . '/' . $file)) { file_change_uni_attchsize(ATTACHMENT_ROOT . '/' . $file, false); } } if (file_exists($file)) { @unlink($file); } if (file_exists(ATTACHMENT_ROOT . '/' . $file)) { @unlink(ATTACHMENT_ROOT . '/' . $file); }
return true; }
|
然后悲催的事情发生了,$file[‘path’]不可控,其他调用的地方均不可控,遂放弃
被阉割的ssrf
file控制器中的fetch操作

进入了ihttp_get方法

复现,访问一个存在的端口

不存在的端口会出错

历史漏洞
文章地址:https://pan.baidu.com/s/1FQ_QnQ019yPAyjbt_Pqgbw
提取码:qius
经过测试,新版本中sql执行的功能已被删除

不存在run操作了,只是前端页面没有删而已,而且还不能访问
微擎中的$_GPC接收参数,对参数进行了转义实体编码等等
底层在对处理update、delete、save等方法时,又做了预处理,然后id类的参数全被加上了单引号,变成了字符型,所以常规从前端传入的,哪怕没有intval过滤,也是不存在注入
寻找注入的方式
在editor下面有个uc方法本以为通过多重编码可可以绕过,没想到,在底层又把所有的参数给转义了一遍,苟啊!!下面代码是对应截图的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| if ($do == 'uc') { if (!empty($_GPC['wapeditor'])) { ... $data = array( ... ); ...
$nav = json_decode(ihtml_entity_decode($_GPC['wapeditor']['nav']), true); $ids = array(0); if (!empty($nav)) { foreach ($nav as $row) { $data = array( 'uniacid' => $_W['uniacid'], 'name' => $row['name'], 'position' => 2, 'url' => $row['url'], 'icon' => '', 'css' => iserializer($row['css']), 'status' => $row['status'], 'displayorder' => 0, ); if (!empty($row['id'])) { print_r($row); table('site_nav') ->where(array( 'id' => $row['id'], 'uniacid' => $_W['uniacid'] )) ->fill($data) ->save(); } else { $data['status'] = 1; table('site_nav')->fill($data)->save(); $row['id'] = pdo_insertid(); } die('aaaaa');
|
可以发现,已经绕过了$_GPC的过滤,进入底层的处理函数
