0×01 前沿* D4 `; Q5 M$ T. U. Q# c6 A" k2 b
3 m) I' L5 X* D X0 i Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。 y2 G1 E2 U: G( k B0 n9 h7 v
# a- \4 ~( h, [# ^& F: c$ h2 y
0×02 写在前面的话
% l4 U& h( }. {
- m7 t! m& W" R. G0 N k phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题
+ D! S$ @7 k. Z7 z; C2 s0 P4 ]$ }8 m: }
这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强
( F" C2 a+ }$ R7 k6 H1 }9 f. I! i) g) h# H" u
这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论
4 g* I" D* P/ n% U _5 s4 x5 n) f% f8 c
0×03 路径? ? ?& G5 r& b* ~; R
9 l, Y( v( w$ P6 V* }
在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件8 o3 q" E3 ^9 X2 y% f d: r; c
1 t+ r% k0 R! b- l
$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])); } % u) O0 N, Y: V9 R; D& k
6 J, \/ N% ]" x- \2 `3 K8 c. l" d这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的) j _+ ~8 `& x) n; u W
7 x1 [$ p0 V+ P9 u
然后就是将我们传进来的参数进行变量化% {. i4 n! h v" I; ^. \1 D6 T0 J
9 m) R: b3 I$ G q; o4 l
这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量7 {* y5 E! u% y& y, p
4 e9 Y6 O* j R1 {; D) c' T; T但是接下来这行呢?
1 a8 G" `! u4 ^0 X2 o( d. Y2 X5 R+ Y0 [, F0 Y, i, w; l
, x6 B/ ~; y# r0 |7 @1 s$ \
6 S/ j& E' }0 v! s7 v: D }7 l; X
if(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); }
7 V j* i2 g! |8 e% }. @$ v6 ]; ?5 ?, ^4 x6 B" a
) {/ w- j( y6 b' `8 B) c
/ d' F' b- G. w- D( o. t3 ?8 N
看看这里?
~# L" S3 t) m5 X" P4 t5 }3 A: Q% ?8 b7 S
这里的QUERY_STRING来自前面. L6 B0 {% w% w$ ]; e/ [
7 f1 E" q9 Z7 [/ e- B
( Z* r/ @7 a5 _) c; y
5 q) D' U" v, o9 s/ x2 O1 Ddefine('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']));" H" q3 t, }1 t
这里有个过滤,但是不影响
( Z3 i* D5 a6 e A& y% S
: q" Q- ^! H. M1 y5 N# z+ g如果我们在这里进行覆盖这个db变量呢
; b/ C9 @! s$ L, x& P0 R9 F1 R* K, e' Y# p
因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));
) f% O. y' X, Z( Q$ O' H/ G" g. u8 x# M- ]
可以将我们传进去的/ - 进行替换; H, R. L6 M+ ^: A
}3 k8 Z0 i* y; c4 a7 `2 i8 e' F7 e所以我们如果提交如下字符
! @' y$ s+ J9 g! G$ j6 P/ u) ^* a: U7 J3 r+ T* z
http://localhost/phpcms/index.php?db-5/gid-xd.html/ N4 G2 y- e3 Y" Y" a
! T9 \+ F3 m j+ S5 k, u他由于这个db被覆盖就会出错,所以物理路径就爆出来了
+ S" y# |" j' l" e; A
* @3 ~4 V% @- u; T5 ?( i$ r% I0×04 SQL注入!!!: K' s- O2 `! D9 l7 ?% ]' y
8 n" n" @1 A4 \8 X3 P8 w5 I
在c.php中0 t) u/ D9 Q/ ~6 H9 R
; Q8 s3 f2 C3 `$ ] ; i; X3 V. b% T2 ]5 i: G
7 B* [8 Q+ K. c! T8 x
<?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']; }
1 W% ?2 B2 b+ \0 F5 }. F8 X5 o9 W
( R# c& W& C8 B$ k) D
( L7 ]2 U5 U; m; v! V; k注意这里的HTTP_REFERER这个常量
) F0 p8 b1 K; k# {2 Y/ b* J8 V- S
4 s2 W4 M: S6 [# H0 N* G这里的常量是通过前面的common.inc.php定义好的* R- o0 R6 A& t! ~
) }$ m9 m2 L+ ^/ W, F2 F& Ddefine(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);
7 I T7 h6 {3 T+ z5 L7 Q1 K0 v8 d& x. G" `* V- L% M% u5 Z
没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我
( d# B- V: F1 X) {5 c0 {( f" l
7 e$ U' f: \9 ?+ U3 B ]. b; I0 Y然后! {% G, u& ?" o" Z) U
9 ]1 F* z2 a. r& x/ `
$db->insert($table, $info);
. u5 B: ~6 _3 }我们来看一下它这里的操作
4 h+ z. y8 A$ T% K+ [) [# F! d1 C5 o5 a- }: d- X8 j; k! K x
function insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); }
" z3 n2 u" i5 q0 l' W5 s8 }) @) V4 }$ Y
所以你懂的
' w/ w) e# P5 k- H! F
# y# F! a M: l4 c& ^
2 a' B+ R9 j+ O1 n/ L/ _. ^$ ]9 ^0 T( L5 ^; X
附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=40456377372 b0 D' [; E# n6 [+ l
' m) K/ {6 n* _3 j. a& ~* T
! R0 b" Y. { e
% w. N8 j, b o' ^' ? |