0×01 前沿5 `0 h; [5 o: x) o
- t7 S2 ?3 f6 M* \ Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。: }! Z, {7 ?/ _- w
" d" X9 T( A# u, a4 m- U, {2 r. F+ X0×02 写在前面的话
3 n9 E! N& ?% Y& Q; t8 ~& U7 S9 d! Y3 O1 T3 D$ `
phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题% E( t2 e4 ^. s, K& l1 G1 G
0 [( e- f5 ~( o& [( B$ x
这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强
* Q4 `8 J( x% h" o5 \. Y; W! K$ u5 o j7 J
这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论% F- D8 d; P7 { |. g
9 R, `: h+ D! H+ i- H
0×03 路径? ? ?0 W" ]/ p2 Y/ s7 z
' K% z% I6 o* y9 ~ 在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件
- y5 ?, o: f* T3 G0 |& ~" C8 j0 e5 P. k4 g6 @& H, }" e
$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])); }
3 X+ p4 Z; Y( w- ?
0 m' n) f) r8 v$ L2 N这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的# Z* ^9 m+ O0 G% z$ Y& a, r
6 C+ t1 X/ ~. `" ?, @- L; ]4 V5 w- S然后就是将我们传进来的参数进行变量化
: K! Y- j9 B1 y% P+ @" d' h4 L# I; h/ u7 X4 b5 q3 H1 V' g0 b4 s
这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量3 S. c6 e; y3 s# P" X ^
1 p( w Q) g! c但是接下来这行呢?
: ~% r6 O! v- C' L$ y) y% k' j: o
: t+ T" x1 p7 H, U1 l) u4 f
' C9 t% H# U7 ]% }% R: oif(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); }
9 O$ P0 x- [2 b8 I6 m
+ l. \; E6 a& s/ H
2 X$ X, ^7 W; w# ~% j: F" g$ C
+ L+ F/ j4 v/ F' K2 L- x. l! N看看这里?/ F$ s0 e* G2 k% \+ L; W: | D
4 I/ y, V5 h5 R
这里的QUERY_STRING来自前面) p8 H$ o$ G7 \9 J
' P! [4 z( ?- q) O8 V1 U 9 ? K' N2 A: ?( t
. @6 v+ H& v" s- }7 t5 Gdefine('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']));. D' T$ M8 N9 y/ W6 F2 Z
这里有个过滤,但是不影响
/ g! V3 |/ V( {, ]7 p* Q! c) Z% `" S" _" u& T
如果我们在这里进行覆盖这个db变量呢
. T' ] c* \- B4 M9 N" B
8 Y, X% N% ?5 d因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));1 c3 I! G* }. k! A3 M5 v: x
9 t$ \$ z/ M/ E$ X, O: Y- a
可以将我们传进去的/ - 进行替换
7 N/ F7 ]" S c9 x6 }! K1 s$ K/ {1 S ^
所以我们如果提交如下字符
5 Q% h# {& i) u$ K0 E2 I& G7 W. r S) Z N6 _+ s6 f
http://localhost/phpcms/index.php?db-5/gid-xd.html
/ }- h' |( D) m7 q. S! s( x |" |$ D
他由于这个db被覆盖就会出错,所以物理路径就爆出来了- |2 M/ @0 u4 S; W6 C1 K- n% e
7 X& {) x N6 h; l" j `0 G: j3 V: @6 f
0×04 SQL注入!!!' x9 x5 q% G* d
9 c8 ^5 P! y+ ?1 L% T 在c.php中9 {* b. C5 i' n
# d }# j- E& C: X7 \0 ? w9 v7 S # N8 b5 Q1 H5 A5 \! d1 y* X2 i) s
$ e+ @( C7 J) c- L# |0 ?
<?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']; } % B$ G; g; A* z( B
3 Y8 {0 y. Z2 I7 F
& o" T6 r; ~0 C* q; i) {
* D T/ ~3 D: _* b @! A; |3 \2 S注意这里的HTTP_REFERER这个常量. ^$ l$ E) \* h6 I
$ q2 W! @$ `8 P9 z6 L
这里的常量是通过前面的common.inc.php定义好的
3 @9 Y1 G0 l3 l9 Q& Y! D, }- u5 N, h2 ?, B# w) W
define(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);
$ M; n: o3 I# h9 \) C4 b3 Y
. F# Q# r. e$ I3 g没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我2 d( {# }: `4 }
; L8 ~7 a/ A. m, j0 f% ]然后
- P) B- _ |- Q+ B2 E$ ~- M T0 K' T3 ?
$db->insert($table, $info);
D# p9 R+ S# [" c: {% Z$ S( J6 x, Z我们来看一下它这里的操作! u4 I8 z' b1 N8 }
8 k1 I9 U( o& y* sfunction insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); }
$ |3 p2 {* p8 e+ ~
' j2 Y' k3 | y. _0 d所以你懂的
9 g6 e" {# }6 f: [
5 z) z8 P' V2 f $ I% r) Z; O" [* N. f: ]$ z
9 x- S+ n( _7 j" g; r4 y9 M8 {
附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=4045637737+ c( G# o0 c, o3 g2 Z7 x
( I+ {7 b* h8 n% a9 b: K6 ?; n * S$ `% M, B, U2 K
+ d% k/ U R8 C) }* P, i( Y
|