0×01 前沿$ E3 P# ~1 u# C7 R6 R8 i1 N; X+ |
4 m6 P H& A7 n( r2 q
Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。
1 `# m+ ^* m o( ^+ e4 g
* T2 y; z% m5 F( @% h, j2 m7 y, X) H* q0×02 写在前面的话$ V+ x' O6 K9 l u/ ^
; ~0 j1 ]) R- k: l: Y
phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题# h r1 ]& w0 U
) V% J0 {8 ^ I! }
这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强
& F- R, W4 Z6 B7 d. ]6 N) e* G; O& h8 I. F+ j( b* x
这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论
( c s3 r- @4 \- W+ X, q' p& R, K
) t9 s. [1 x, l' j( S; m# D0×03 路径? ? ?
+ a. m6 `9 a3 f/ g; {! b9 |
) i, [4 u3 n" B! A. I8 H 在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件
1 k7 t1 W7 V% `. b, `6 C7 F1 ?% p% Z+ v
$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])); } & R% k$ |+ M8 P1 J/ D
/ E3 D/ n3 ]5 Y9 r& r# {' y这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的
7 a5 r. o& ?: m4 D* a- a. P/ Q+ H G9 a7 e9 ^1 a$ i+ m) K- z0 u
然后就是将我们传进来的参数进行变量化3 t) G6 L+ C% x8 H' P2 u9 ^. m
1 _7 p- A8 Q! B7 Q; D) C这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量
2 v { |/ p; Y! Y4 O+ e& E/ k p Q0 p9 m& J& [6 [- o( K
但是接下来这行呢?/ D l9 q6 h. |9 N) n! x2 B
- ?0 I9 w. s1 P. T; o! A
; Z& k/ I* w& j9 `4 v
* j3 p- N$ ^/ s3 C5 r1 d+ K4 Nif(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); } * w1 v. t' V. R) z: g$ [+ O
, @. f# n9 | L6 s
8 }4 A' p; U( x/ i$ D k+ T
% N& K9 ]. |- m( w9 T看看这里?
& W( F/ s) ?& ?4 Q- Z0 s) m+ Y5 {' Y& `- y
这里的QUERY_STRING来自前面$ s5 W0 f. k ~
7 K+ l2 [) F2 ~ . P: ~2 D. M( m6 {8 S7 e9 U$ U
3 P3 e0 j# G1 ~! [
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']));
5 z) {) P- P2 a% h, q( A/ F这里有个过滤,但是不影响
( i2 f0 q# ~3 H1 i) I9 e$ L4 a. S: [( C( w8 ~
如果我们在这里进行覆盖这个db变量呢
# T; p; _) r# _" ?* K
9 P4 z Q0 H6 j( z% t因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));% w2 B8 s7 S- U% e
- _4 x9 n% o& W
可以将我们传进去的/ - 进行替换
# L. a" ^& U& e7 ]! v) H
- ]. A$ e( L6 V! w* r$ y* r/ x所以我们如果提交如下字符
; m$ m9 b5 y( X# }- I4 u
7 _" T. k, H. Ehttp://localhost/phpcms/index.php?db-5/gid-xd.html; M& W* p; F8 w" P) g8 Y
( j& |7 j7 w) d- ~7 G7 y& q他由于这个db被覆盖就会出错,所以物理路径就爆出来了; O! v T, Y8 J; }
e5 ?0 P. y9 t3 @! T* F0×04 SQL注入!!!. h; _. j6 M& C9 X: W# y% N5 k
* I1 |, T, P: l. B x 在c.php中! _5 |& `# _9 V9 y
; U& U( `2 H7 W, t* s$ @( f" i/ F
8 Z& ? I8 f' q4 ]- E! s" v) X+ }6 E5 K* c: w) K4 i) V
<?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 C& y6 t! i5 B
4 C, X& d5 U% y' ]; [% ^1 Q! T7 J6 L
/ x) o# A& W) M# Y
* \4 U& z! z0 O* V/ t% j R注意这里的HTTP_REFERER这个常量
2 \( o: T* a! q1 N! Q& D7 }
3 j, V% |, T1 f$ A, B. F这里的常量是通过前面的common.inc.php定义好的& D. m6 H O. u! O3 y
+ w3 h5 m+ O' W I
define(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);9 C k7 `' m4 E( h: {# b1 l |
3 ?% {7 i' F, D8 B
没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我 N: C2 J, i1 @8 S- P% S7 D
, @2 \$ y8 d( W! P然后
5 _ v$ @( l2 p: P0 Y( t
4 T8 q9 C Z& R) Y0 M2 F$db->insert($table, $info);
0 b$ ?2 j# r9 c) y# Z0 T* d; [, t我们来看一下它这里的操作
8 u5 N" f7 r7 _$ J! G) x$ C4 {2 X; n* A) B4 V" H
function insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); }
' h6 q7 u }2 [$ Q
& \7 I, d) R" j& }( X) F F: A3 K所以你懂的$ i5 Y) u3 T1 m% x
# D- k, g4 o' E5 J
0 a$ a$ L: c) }( X7 r% r! S9 H5 q& g
附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=4045637737! t1 I6 Z0 `: r7 Z7 k
, r! v, d4 p |: w; c
+ A' A- x; `. w# E+ ?1 u( }
/ m- H( d0 e" U3 g! Q( H
|