0×01 前沿
1 Q4 r: \' r6 I, {9 B4 F9 R' b4 m ^2 q/ Y) d, R! |
Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。; O$ L" C/ t( Y! U! J
8 |3 _2 O% y5 ~6 A. V' Z5 {5 A7 p* Y0×02 写在前面的话
+ C9 a! K7 q8 O8 W) v/ n* a4 Y+ p- M0 Z W, Y
phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题" _' s- o4 C, M3 A6 S, Y2 `
U L$ o; n) R, W/ E% y
这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强
% y2 K' r" v6 h; O6 M1 d$ K# a' C) Z' x m; E8 K( r6 x% d: i
这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论0 E, L& m G. e5 t" O b, H
! [( i0 t" G$ r+ ]- L, \( {) a$ n
0×03 路径? ? ?
6 ^2 [. p$ C6 J" X' A8 [0 ~8 V5 s) L: C8 j/ \/ [: n
在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件+ i& U2 q8 N: Y3 a6 E; F
6 u2 j. ~6 A( h# G$dbclass = 'db_'.DB_DATABASE; require $dbclass.'.class.php'; $db = new $dbclass; $db->connect(DB_HOST, DB_USER, DB_PW, DB_NAME, DB_PCONNECT, DB_CHARSET); require 'session_'.SESSION_STORAGE.'.class.php'; $session = new session(); session_set_cookie_params(0, COOKIE_PATH, COOKIE_DOMAIN); if($_REQUEST) { if(MAGIC_QUOTES_GPC) { $_REQUEST = new_stripslashes($_REQUEST); if($_COOKIE) $_COOKIE = new_stripslashes($_COOKIE); extract($db->escape($_REQUEST), EXTR_SKIP); } else { $_POST = $db->escape($_POST); $_GET = $db->escape($_GET); $_COOKIE = $db->escape($_COOKIE); @extract($_POST,EXTR_SKIP); @extract($_GET,EXTR_SKIP); @extract($_COOKIE,EXTR_SKIP); } if(!defined('IN_ADMIN')) $_REQUEST = filter_xss($_REQUEST, ALLOWED_HTMLTAGS); if($_COOKIE) $db->escape($_COOKIE); } if(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); } ( J$ x& W& v5 G! d
* h0 Z5 R% t2 T5 {# Q" g
这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的
' h6 d1 [1 w6 S* D9 K6 f7 y! |
) d2 R* p0 T3 b P0 e6 t2 [然后就是将我们传进来的参数进行变量化+ H* H5 i* J l0 M6 L: ?1 v# j8 g
; Y* T5 H1 ~% A s这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量
7 [* n+ T5 t; f: ]3 _6 q( a0 d4 m
但是接下来这行呢?
# h+ ?0 C2 I3 |# ~# C. H! T
3 G) I3 Q# [3 t6 _) w2 s$ E" r 9 j( r: n. B. c* }! _$ @8 w
6 Y8 s/ u _$ l4 Rif(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); } " f) F9 `/ E x" A$ z: R
+ S9 P* N6 g3 t, r
: t+ `" M* W0 c$ M2 [) y/ F- A9 h
9 h! ?, f: u3 f! V8 H看看这里?: s3 v9 Z0 g8 M' S6 }
0 s3 Y1 V4 B: }9 N: o5 z这里的QUERY_STRING来自前面7 \- f+ \& n# h. h, q
9 Z6 y7 d5 Q% g2 Z/ S9 L) H
0 U+ q! j6 f" Q1 o9 m. ^# A4 @) U4 \6 a
define('IP', ip()); define('HTTP_REFERER', isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''); define('SCRIPT_NAME', isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : preg_replace("/(.*)\.php(.*)/i", "\\1.php", $_SERVER['PHP_SELF'])); define('QUERY_STRING', safe_replace($_SERVER['QUERY_STRING']));* i) h4 o0 d. Q7 e
这里有个过滤,但是不影响
( y" R8 x0 w$ Q/ T& ~
y% a5 \& w% g& ~; y; h如果我们在这里进行覆盖这个db变量呢- ^) s6 d: b) v3 n
' f+ x d5 ^# d+ Y
因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));
6 u( s+ K7 q$ G
. _ J% a; s L. @可以将我们传进去的/ - 进行替换
- ]' @+ `. c8 W, y7 q5 u$ J( S8 A" B5 M6 M+ g4 @
所以我们如果提交如下字符% ~( a' t! l0 E. Z6 O, Y
4 ~' p) D: v- B" n; @
http://localhost/phpcms/index.php?db-5/gid-xd.html u: N g, a$ N* _4 O" c: f+ x
, ] w( H- N( C3 F他由于这个db被覆盖就会出错,所以物理路径就爆出来了9 K$ _- q6 m; z9 e5 N
6 X( V: g6 j9 R! r ~3 M
0×04 SQL注入!!!0 z0 y" J. b* W! ^
" q; [' z1 E4 V; K k) @ 在c.php中
# Q8 h y/ u* M: N9 s# [: J% T, \
5 d3 E* h7 F; O9 `* G9 a' C7 \
" E$ |1 b; k' ~5 D
0 [: i7 q# z9 s9 ]3 D9 C<?php require './ads/include/common.inc.php'; $id = intval($id); $ads = $c_ads->get_info($id); if($ads) { $db->query("UPDATE ".DB_PRE."ads SET `clicks`=clicks+1 WHERE adsid=".$ads['adsid']); $info['username'] = $_username; $info['clicktime'] = time(); $info['ip'] = IP; $info['adsid'] = $id; $info['referer'] = HTTP_REFERER; $year = date('ym',TIME); $table = DB_PRE.'ads_'.$year; $table_status = $db->table_status($table); if(!$table_status) { include MOD_ROOT.'include/create.table.php'; } $db->insert($table, $info); $url = strpos($ads['linkurl'], 'http://')===FALSE ? 'http://'.$ads['linkurl'] : $ads['linkurl']; }
0 l0 |) v9 \2 Z' ~- ^: |2 G1 B. m& ~7 w$ T4 D* N$ U
& O0 ^% Y1 q9 Q9 H+ C! s1 [, f, g& c+ u6 u3 D/ z+ I9 u, b L
注意这里的HTTP_REFERER这个常量1 _. \8 ], z/ R9 x
4 r7 ?$ S! e/ V" k0 g# u
这里的常量是通过前面的common.inc.php定义好的. [( n9 D) @0 \* S2 P# |5 @
; e$ u% y* V- ~ ^) `define(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);
. l# @( g) A1 }% H& k% F3 r. R l" ~5 z
没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我
: \( U/ h8 w9 i! z, M2 r5 x- e) K; S
( V% ?$ p P! J3 ?, Y( Y: v然后9 N- Y; M4 _9 F+ c6 F( q( C; [' Y
9 {( b& K, ]7 y! a
$db->insert($table, $info);
3 M6 }/ g9 d2 H) i: k. n% t我们来看一下它这里的操作3 P' ?. g% x. y$ s( v5 v# h
$ J( n/ t+ L/ T" Hfunction insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); } ) R# @) k! _* E% Y% C( j8 J
" ~! Z* o' v$ J+ p7 H6 n8 A
所以你懂的. b, p$ y- w1 u/ P) E+ H8 i1 o
7 v+ ^3 {4 } L0 i0 {/ L8 [% H5 {
4 g" \; z: d: B
3 J. t% M- l* [8 L3 w6 t% y* P0 T5 |2 I附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=4045637737% H( e/ [5 G$ [) S
" V: v! d7 b. J# m+ P/ T2 N& W; U! r
& V7 V$ d. o4 A; m" H
0 T/ o6 b0 C' c8 |5 Q: E$ i5 D
|