0×01 前沿
+ x; ^: K* b7 U9 v' v9 Y8 X8 z4 c5 T* T. Z$ T& Y) e# A. [' d+ J7 R* B
Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。
3 _ t( C0 @7 v) u2 i, O
& n5 d( e. h- ` {$ E. e) g" H0×02 写在前面的话
8 K: n) E. a5 w+ u0 s1 w& E9 J4 B* Z" x# y" ?
phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题
) h& D/ |7 d% Y7 a
( h' ~& o7 o4 d: m8 B' C5 G" j' d这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强# _- {3 R+ Y: W2 d) _3 Y8 v) p
' R9 X! \' T5 Q2 D
这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论
- @# {, X7 o0 x8 i1 w; l; Y4 K0 |! W4 @/ \! \( f
0×03 路径? ? ?. ~2 E- X$ G: }2 g- A6 t
1 Q2 k$ f+ k0 f# \+ _! A
在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件- {5 N v4 n4 V& e
7 t G2 @% x$ m2 S" z% d# Y. Y* R
$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])); } 9 ^( _1 l/ f: u) z# O0 y0 O
( F& k* X+ g; u( y8 r8 T" V这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的& W' w. G( d/ w( c8 o4 K
' s: A5 |0 O! B0 Z1 B3 \
然后就是将我们传进来的参数进行变量化$ d+ r+ C1 f c
% ?% I C1 ^8 v) @ A这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量
! O1 O/ A+ T, X0 t+ D3 a% f# u% V6 M$ q* n+ g+ |4 T; A
但是接下来这行呢?2 F% O% w2 f$ ?1 s: l
' @8 ?! W. W6 }! l3 ~9 t: a1 w' R3 e
$ W5 n! f$ {4 w5 W: r; g; y8 w7 I* T- }3 Z% z& @9 c ~2 u
if(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); } . ^, P) T0 Y; H# H) U
6 T2 Q8 Q5 H* a% `
0 O% w! N9 a" b* X- ^
}4 c6 X# m: [+ t* I看看这里?
9 W% d9 t! N0 y% v& r: k# w7 V2 L7 c+ W. x2 t! X
这里的QUERY_STRING来自前面3 F9 N4 l4 o# _+ C! c
$ H& M* i8 n( { K* o
+ e' t# m, }! _3 ]' r+ D( h9 \
0 M4 D, `3 Y8 w* t5 ^9 O3 }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']));
9 v! }: o) J8 m' E这里有个过滤,但是不影响
, b+ V6 ?6 ?8 B- d4 @% d4 Z# e2 v# s0 `6 A* S' U
如果我们在这里进行覆盖这个db变量呢) x# L9 _( c- |1 p, _
! u9 o- ]* c1 \! h/ D# o% R
因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));; M* |7 u6 @2 P3 P3 ^, u
" F+ E. S7 H& z& }, y4 A' G$ n
可以将我们传进去的/ - 进行替换' T! C! c' ~/ I3 \7 e- q
% c1 G1 Z) h( Q/ ~! }% a所以我们如果提交如下字符" u Z8 M# _, [5 N. e
* J. V* r1 c8 P4 D: W
http://localhost/phpcms/index.php?db-5/gid-xd.html6 k7 @3 D+ @3 ~0 C
6 f! t% K3 K+ {* m
他由于这个db被覆盖就会出错,所以物理路径就爆出来了
0 Z% g/ O* R' ] X1 f4 v8 C: ^2 X- i" p& S5 V
0×04 SQL注入!!!
0 B) E. d5 t5 Y
$ D; }6 I, p2 P 在c.php中
( d: t6 D' f0 `1 {+ c* ?, R9 T
% ^6 o3 o* k1 o: Q7 S6 f7 c& l
/ o$ Z7 C- c: p X' Q3 F! r. z4 E; v/ T) F5 c9 i
<?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']; } 3 j) h9 h4 h/ g D5 p* f4 I
9 j2 ?0 x* u- c % f6 u# M$ D3 l" R \
7 S% x/ f8 u: b
注意这里的HTTP_REFERER这个常量5 D8 S: {5 |. W- J$ G8 W6 \8 U
8 Y- J$ U/ Q. }' K& `0 V
这里的常量是通过前面的common.inc.php定义好的
* H' D p0 c5 x. d
* M$ _$ }; _7 R, p. m( f* vdefine(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);3 q' L7 Y5 M+ _, Q6 n
N2 ^5 j4 t! p3 Z
没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我$ T/ o8 y$ t! m7 Z
9 X1 l" H/ U) j1 ^# Q( g然后
8 K! E; Z/ l( g' H7 J
7 A% O3 Q, f0 }1 m' A* i5 L7 t3 X$db->insert($table, $info);/ ]8 k+ u( S3 w9 ~" `: k& L3 n+ R9 D
我们来看一下它这里的操作0 j. V% m, C7 V7 [% ~" F
" Q3 _0 M! n$ o# ^- D5 Ifunction insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); }
+ A& o4 }& L5 s# x: V1 \7 J! K0 `7 C' ^" z+ P. [, U# d; L( g2 `
所以你懂的
5 r6 _- e) |/ l& ^/ b. d
4 ~. q4 z, ^, C" Q
3 B" x5 I- i% y$ [4 d( |& w: N) g& a+ c0 _& E
附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=4045637737$ x' h" B) \' Z. q/ Y
" y( j( I2 P0 q4 P9 z! Z0 y
7 W& l5 O* U Q9 A& D# z8 k
+ T; P; p8 J& g r; h) P3 W& s
|