### 简要描述: 二次注入第二枚,这个点的注入内容至少进出数据库6次才最终到达了注入结果页面,当然全程可控。 ### 详细说明: 先上注入结果图: [<img src="https://images.seebug.org/upload/201306/210728063b9659aa00cecbb4beb74a8e72fe8434.png" alt="3.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201306/210728063b9659aa00cecbb4beb74a8e72fe8434.png) SQL注入流程: 1.插入注入代码(goods_attr)至订单商品(/wholesale.php可以插入,即商品批发页面,这里的goods_attr和 [WooYun: ecshop最新版本前台二次注入系列(1)](http://www.wooyun.org/bugs/wooyun-2013-026421) 里goods_attr_id是不同的,之前的漏洞即正常在商品页面加入购物车是不能控制goods_attr的,当时goods_attr从数据库商品属性表读取)。 [<img src="https://images.seebug.org/upload/201306/21072906cd43d1d4627d257052252577a50f18bc.png" alt="2.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201306/21072906cd43d1d4627d257052252577a50f18bc.png) 2.将1生成的订单在用户中心订单查看页执行“放回购物车”操作。 [<img src="https://images.seebug.org/upload/201306/210733585e877aedbc8811362ea3c2097950961d.png" alt="4.png" width="600"...
### 简要描述: 二次注入第二枚,这个点的注入内容至少进出数据库6次才最终到达了注入结果页面,当然全程可控。 ### 详细说明: 先上注入结果图: [<img src="https://images.seebug.org/upload/201306/210728063b9659aa00cecbb4beb74a8e72fe8434.png" alt="3.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201306/210728063b9659aa00cecbb4beb74a8e72fe8434.png) SQL注入流程: 1.插入注入代码(goods_attr)至订单商品(/wholesale.php可以插入,即商品批发页面,这里的goods_attr和 [WooYun: ecshop最新版本前台二次注入系列(1)](http://www.wooyun.org/bugs/wooyun-2013-026421) 里goods_attr_id是不同的,之前的漏洞即正常在商品页面加入购物车是不能控制goods_attr的,当时goods_attr从数据库商品属性表读取)。 [<img src="https://images.seebug.org/upload/201306/21072906cd43d1d4627d257052252577a50f18bc.png" alt="2.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201306/21072906cd43d1d4627d257052252577a50f18bc.png) 2.将1生成的订单在用户中心订单查看页执行“放回购物车”操作。 [<img src="https://images.seebug.org/upload/201306/210733585e877aedbc8811362ea3c2097950961d.png" alt="4.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201306/210733585e877aedbc8811362ea3c2097950961d.png) 3.查看购物车页面,注入代码执行 [<img src="https://images.seebug.org/upload/201306/210728063b9659aa00cecbb4beb74a8e72fe8434.png" alt="3.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201306/210728063b9659aa00cecbb4beb74a8e72fe8434.png) 代码分析: 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方式可以将数据库内容查询出来显示到页面上 } } ``` 2. /wholesale.php 160行起(将商品提交到购物车,实际上是提交到了$_SESSION) ``` /*------------------------------------------------------ */ //-- 加入购物车 /*------------------------------------------------------ */ 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]; //可控,可以参考我在截图里构造的提交数据 } … ``` 3./wholesale.php 380行起(act=='submit_order'), 将$_SESSION里的数据写入订单 ``` /* 插入订单商品 */ 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); ``` 4.到3为止,已经可以将注入代码写到订单商品表(order_goods)里了,接下来就是进入购物车数据表,在用户中心查看订单时有个"放回购物车"操作,可以将订单商品放到购物车数据表(cart)里,然后在查看购物车页面/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 ); ... ``` ### 漏洞证明: [<img src="https://images.seebug.org/upload/201306/21072906cd43d1d4627d257052252577a50f18bc.png" alt="2.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201306/21072906cd43d1d4627d257052252577a50f18bc.png) [<img src="https://images.seebug.org/upload/201306/210728063b9659aa00cecbb4beb74a8e72fe8434.png" alt="3.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201306/210728063b9659aa00cecbb4beb74a8e72fe8434.png)