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

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

缺陷编号:wooyun-2015-0145307

漏洞标题:iwebshop最新版注入

相关厂商:www.jooyea.cn

漏洞作者: 路人甲

提交时间:2015-10-14 14:44

修复时间:2016-01-13 15:38

公开时间:2016-01-13 15:38

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:16

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-10-14: 细节已通知厂商并且等待厂商处理中
2015-10-15: 厂商已经确认,细节仅向厂商公开
2015-10-18: 细节向第三方安全合作伙伴开放(绿盟科技唐朝安全巡航
2015-12-09: 细节向核心白帽子及相关领域专家公开
2015-12-19: 细节向普通白帽子公开
2015-12-29: 细节向实习白帽子公开
2016-01-13: 细节向公众公开

简要描述:

SQL。

详细说明:

问题出现在classes\order_class.php 的updateStore函数
具体代码如下:

public static function updateStore($orderGoodsId,$type = 'add')
{
if(!is_array($orderGoodsId))
{
$orderGoodsId = array($orderGoodsId);
}
$newStoreNums = 0;
$updateGoodsId = array();
$orderGoodsObj = new IModel('order_goods');
$goodsObj = new IModel('goods');
$productObj = new IModel('products');
$goodsList = $orderGoodsObj->query('id in('.join(",",$orderGoodsId).') and is_send = 0','goods_id,product_id,goods_nums');
foreach($goodsList as $key => $val)
{
//货品库存更新
if($val['product_id'] != 0)
{
$productsRow = $productObj->getObj('id = '.$val['product_id'],'store_nums');
$localStoreNums = $productsRow['store_nums'];
//同步更新所属商品的库存量
if(in_array($val['goods_id'],$updateGoodsId) == false)
{
$updateGoodsId[] = $val['goods_id'];
}
$newStoreNums = ($type == 'add') ? $localStoreNums + $val['goods_nums'] : $localStoreNums - $val['goods_nums'];
$newStoreNums = $newStoreNums > 0 ? $newStoreNums : 0;
$productObj->setData(array('store_nums' => $newStoreNums));
$productObj->update('id = '.$val['product_id'],'store_nums');
}
//商品库存更新
else
{
$goodsRow = $goodsObj->getObj('id = '.$val['goods_id'],'store_nums');
$localStoreNums = $goodsRow['store_nums'];
$newStoreNums = ($type == 'add') ? $localStoreNums + $val['goods_nums'] : $localStoreNums - $val['goods_nums'];
$newStoreNums = $newStoreNums > 0 ? $newStoreNums : 0;
$goodsObj->setData(array('store_nums' => $newStoreNums));
$goodsObj->update('id = '.$val['goods_id'],'store_nums');
}
//更新销售量sale字段,库存减少销售量增加,两者成反比
$saleData = ($type == 'add') ? -$val['goods_nums'] : $val['goods_nums'];
$goodsObj->setData(array('sale' => 'sale + '.$saleData));
$goodsObj->update('id = '.$val['goods_id'],'sale');
}
//更新统计goods的库存
if($updateGoodsId)
{
foreach($updateGoodsId as $val)
{
$totalRow = $productObj->getObj('goods_id = '.$val,'SUM(store_nums) as store');
$goodsObj->setData(array('store_nums' => $totalRow['store']));
$goodsObj->update('id = '.$val);
}
}
}


注意:

$goodsList     = $orderGoodsObj->query('id in('.join(",",$orderGoodsId).') and is_send = 0','goods_id,product_id,goods_nums');


$orderGoodsId无单引号保护,如果传输的参数未经过滤则造成SQL注入,来跟踪一下:
此函数有三处引用,直接来看这个有注入的地方:
classes\order_class.php sendDeliveryGoods函数
部分代码如下:

public static function sendDeliveryGoods($order_id,$order_goods_relation,$sendor_id,$sendor = 'admin')
{
$order_no = IFilter::act(IReq::get('order_no'));
$paramArray = array(
'order_id' => $order_id,
'user_id' => IFilter::act(IReq::get('user_id'),'int'),
'name' => IFilter::act(IReq::get('name')),
'postcode' => IFilter::act(IReq::get('postcode'),'int'),
'telphone' => IFilter::act(IReq::get('telphone')),
'province' => IFilter::act(IReq::get('province'),'int'),
'city' => IFilter::act(IReq::get('city'),'int'),
'area' => IFilter::act(IReq::get('area'),'int'),
'address' => IFilter::act(IReq::get('address')),
'mobile' => IFilter::act(IReq::get('mobile')),
'freight' => IFilter::act(IReq::get('freight'),'float'),
'delivery_code' => IFilter::act(IReq::get('delivery_code')),
'delivery_type' => IFilter::act(IReq::get('delivery_type')),
'note' => IFilter::act(IReq::get('note'),'text'),
'time' => ITime::getDateTime(),
'freight_id' => IFilter::act(IReq::get('freight_id'),'int'),
);
switch($sendor)
{
case "admin":
{
$paramArray['admin_id'] = $sendor_id;
$adminDB = new IModel('admin');
$sendorData = $adminDB->getObj('id = '.$sendor_id);
$sendorName = $sendorData['admin_name'];
$sendorSort = '管理员';
}
break;
case "seller":
{
$paramArray['seller_id'] = $sendor_id;
$sellerDB = new IModel('seller');
$sendorData = $sellerDB->getObj('id = '.$sendor_id);
$sendorName = $sendorData['true_name'];
$sendorSort = '加盟商户';
}
break;
}
//获得delivery_doc表的对象
$tb_delivery_doc = new IModel('delivery_doc');
$tb_delivery_doc->setData($paramArray);
$deliveryId = $tb_delivery_doc->add();
//订单对象
$tb_order = new IModel('order');
$tbOrderRow = $tb_order->getObj('id = '.$order_id);
//如果支付方式为货到付款,则减少库存
if($tbOrderRow['pay_type'] == 0)
{
//减少库存量
self::updateStore($order_goods_relation,'reduce');
}


可以看到变量来自函数参数,再进行函数跟踪:

[@@5P0KZRHV($)O~0JWS4QJ.png


此处有两处,第一个是后台就不看了,直接看seller.php

public function order_delivery_doc()
{
//获得post变量参数
$order_id = IFilter::act(IReq::get('id'),'int');
//发送的商品关联
$sendgoods = IFilter::act(IReq::get('sendgoods'));
if(!$sendgoods)
{
die('请选择要发货的商品');
}
Order_Class::sendDeliveryGoods($order_id,$sendgoods,$this->seller['seller_id'],'seller');
$this->redirect('order_list');
}


$sendgoods = IFilter::act(IReq::get('sendgoods'));
直接获取,未经过滤,造成注入。
来实际操作一下:
注册前台用户,商家账号各一个,前台用户购买商品选择货到付款。

0TQDP4V{)A`NS$(580F0JI7.jpg


选择立即发货

YTRBI(_7RM2{OF5TS[4JBY8.png


勾选要发货的商品,填写订单号,然后确定,抓包
插入自己的注入语句

_H@E~PR}4G3~VIDMMUDWPLL.png


成功注入延时:

V}B{{3T~H}MF@RKMAVDT$@X.png


漏洞证明:

如上。

修复方案:

过滤。

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


漏洞回应

厂商回应:

危害等级:中

漏洞Rank:8

确认时间:2015-10-15 15:37

厂商回复:

商家后台管理发货功能参数过滤

最新状态:

暂无