一:goods_attr_id的二次注入
![ecshop的goods_attr和goods_attr_id两个二次注入漏洞]()
注入利用过程:
1.添加商品到购物车时,写入注入代码到商品属性id
http://localhost/test/ecshop/flow.php?step=add_to_cart
1 |
POST: goods={ "quick" :1, "spec" :[ "163" , "158'" ], "goods_id" :32, "number" : "1" , "parent" :0} |
注意,需要spec有两个或以上id
2.在查看购物车页面,点击更新购物车,执行注入代码(二次注入嘛,单引号可用了)
代码分析
1./includes/lib_goods.php 942行
1 |
function spec_price( $spec ) |
5 |
$where = db_create_in( $spec , 'goods_attr_id' ); //这里是注入位置,能控制$spec就可以了 |
7 |
$sql = 'SELECT SUM(attr_price) AS attr_price FROM ' . $GLOBALS [ 'ecs' ]->table( 'goods_attr' ) . " WHERE $where" ; |
8 |
$price = floatval ( $GLOBALS [ 'db' ]->getOne( $sql )); |
2./includes/lib_common.php 2266行get_final_price有spec_price的调用
3.再看get_final_price方法的调用 在ecshop/flow.php flow_update_cart方法,2272行
4 |
$attr_id = empty ( $goods [ 'goods_attr_id' ]) ? array () : explode ( ',' , $goods [ 'goods_attr_id' ]); //看,$attr_id是读取的购物车商品的goods_attr_id字段,所以只要在添加商品到购物车时写入注入代码就可以了 |
5 |
$goods_price = get_final_price( $goods [ 'goods_id' ], $val , true, $attr_id ); |
7 |
$sql = "UPDATE " . $GLOBALS [ 'ecs' ]->table( 'cart' ). |
8 |
" SET goods_number = '$val', goods_price = '$goods_price' WHERE rec_id='$key' AND session_id='" . SESS_ID . "'" ; } |
二:good_attr的二次注入
1.插入注入代码(goods_attr)至订单商品(/wholesale.php可以插入,即商品批发页面.
![ecshop的goods_attr和goods_attr_id两个二次注入漏洞]()
2.将1生成的订单在用户中心订单查看页执行“放回购物车”操作。
3.查看购物车页面,注入代码执行
![ecshop的goods_attr和goods_attr_id两个二次注入漏洞]()
代码分析:
1./includes/lib_order.php get_cart_goods()方法(读取购物车的商品),1626行起
2 |
if (trim( $row [ 'goods_attr' ]) != '' ) |
4 |
$sql = "SELECT attr_value FROM " . $GLOBALS [ 'ecs' ]->table( 'goods_attr' ) . " WHERE goods_attr_id " . |
5 |
db_create_in( $row [ 'goods_attr' ]); //goods_attr是购物车商品的属性,所以只要能控制注入代码进入购物车商品就ok了,这是二次注入的原因 |
6 |
$attr_list = $GLOBALS [ 'db' ]->getCol( $sql ); |
7 |
foreach ( $attr_list AS $attr ) |
9 |
$row [ 'goods_name' ] .= ' [' . $attr . '] ' ; //union select方式可以将数据库内容查询出来显示到页面上 |
2. /wholesale.php 160行起(将商品提交到购物车,实际上是提交到了$_SESSION)
1 |
/*------------------------------------------------------ */ |
3 |
/*------------------------------------------------------ */ |
4 |
elseif ( $_REQUEST [ 'act' ] == 'add_to_cart' ) |
7 |
$act_id = intval ( $_POST [ 'act_id' ]); |
8 |
$goods_number = $_POST [ 'goods_number' ][ $act_id ]; |
9 |
$attr_id = isset( $_POST [ 'attr_id' ]) ? $_POST [ 'attr_id' ] : array (); |
10 |
if (isset( $attr_id [ $act_id ])) |
12 |
$goods_attr = $attr_id [ $act_id ]; //可控,可以参考我在截图里构造的提交数据 |
3./wholesale.php 380行起(act==’submit_order’), 将$_SESSION里的数据写入订单
2 |
foreach ( $_SESSION [ 'wholesale_goods' ] as $goods ) |
5 |
if (! empty ( $goods [ 'goods_attr_id' ])) |
7 |
$goods_attr_id = array (); |
8 |
foreach ( $goods [ 'goods_attr_id' ] as $value ) |
10 |
$goods_attr_id [ $value [ 'attr_id' ]] = $value [ 'attr_val_id' ]; |
12 |
ksort( $goods_attr_id ); |
13 |
$goods_attr = implode( '|' , $goods_attr_id ); |
14 |
$sql = "SELECT product_id FROM " . $ecs ->table( 'products' ) . " WHERE goods_attr = '$goods_attr' AND goods_id = '" . $goods ['goods_id '] . "' "; |
15 |
$product_id = $db ->getOne( $sql ); |
17 |
$sql = "INSERT INTO " . $ecs ->table( 'order_goods' ) . "( " . |
18 |
"order_id, goods_id, goods_name, goods_sn, product_id, goods_number, market_price, " . |
19 |
"goods_price, goods_attr, is_real, extension_code, parent_id, is_gift) " . |
20 |
" SELECT '$new_order_id', goods_id, goods_name, goods_sn, '$product_id','$goods[goods_number]', market_price, " . |
21 |
"'$goods[goods_price]', '$goods[goods_attr]', is_real, extension_code, 0, 0 " . |
22 |
" FROM " . $ecs ->table( 'goods' ) . |
23 |
" WHERE goods_id = '$goods[goods_id]'" ; |
4.到3为止,已经可以将注入代码写到订单商品表(order_goods)里了,接下来就是进入购物车数据表,在用户中心查看订单时有个”放回购物车”操作,可以将订单商品放到购物车数据表(cart)里,
然后在查看购物车页面/flow.php即能看到注入结果了(见1的代码分析)
/includes/lib_transaction.php return_to_cart方法 854行起
4 |
'goods_id' => $row [ 'goods_id' ], |
5 |
'goods_sn' => addslashes ( $goods [ 'goods_sn' ]), |
6 |
'goods_name' => addslashes ( $goods [ 'goods_name' ]), |
7 |
'market_price' => $goods [ 'market_price' ], |
8 |
'goods_price' => $goods [ 'goods_price' ], |
9 |
'goods_number' => $row [ 'goods_number' ], |
10 |
'goods_attr' => empty ( $row [ 'goods_attr' ]) ? '' : addslashes ( $row [ 'goods_attr' ]), //看过来,重点在这,$row是订单商品,虽然addslashes了,但这是二次注入,最终会从数据库里再出来进入查询(见1的代码分析) |
11 |
'goods_attr_id' => empty ( $row [ 'goods_attr_id' ]) ? '' : $row [ 'goods_attr_id' ], |
12 |
'is_real' => $goods [ 'is_real' ], |
13 |
'extension_code' => addslashes ( $goods [ 'extension_code' ]), |
16 |
'rec_type' => CART_GENERAL_GOODS |
漏洞作者:BLUE
评论