0×01 前沿% n6 K5 L. Q0 G- z' E" f- h
% a/ V! ^2 m4 b3 m8 x
Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。
5 M: x9 \$ e3 G& C
) F5 e/ R+ z3 l9 `) Y, b0×02 写在前面的话
0 [( w/ w2 D6 w7 m& E4 B5 u9 y! z R) Z$ i9 C% q: l; K; b! {$ g
phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题) i* n0 d1 }; e1 H$ C
: X6 _6 ^& O4 K; ~# w
这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强
0 F) }. d" a6 A3 M1 u/ `; W0 v" U2 W D# _
这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论; j) g% n! w& }6 m; e7 w: v
; R ~% B) H U5 y9 C* p
0×03 路径? ? ?1 |: ^: z% z1 ?* b1 C% [+ B/ @( U: _
' r4 Y% n% W% b7 u 在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件
2 V" g+ ?2 a& X+ C s; j x2 [2 t9 d4 b% Y2 o( |
$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])); } * f5 E' g7 z% `
% T L$ U" e, h# x; u H# A- \这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的
4 K$ d' M. s( d' R4 U! o( X) j* \/ F: \# @7 t3 m* B7 C e* D
然后就是将我们传进来的参数进行变量化3 x; d* j/ c5 F4 {6 Q" ~* S
1 b8 L2 _, w5 T, H这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量
$ ?3 r! z( n3 ]+ I) Y4 b
* I( K/ n' n1 o5 R( \: i% N$ [但是接下来这行呢?9 M" Y4 G% e/ Q
2 n# G7 g1 q; e
# }7 Q: @3 O$ o4 v
8 O2 S1 \2 U# ^- A% R" [. a" bif(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); }
) _+ {& ?1 X P( f' B4 S
% ^+ g% ]3 ?+ v( Z2 z
& @6 {' R i# S7 |' ^" h/ W! U* l5 t8 ]8 L+ u# L
看看这里?
@$ J7 w) F1 {8 _3 h& d7 Y' R, k- ]
1 n+ P9 e V9 v& r, f, g( _这里的QUERY_STRING来自前面9 I0 T) x& |7 m7 h
7 q. s: Y* k0 Q0 a
& q, k. N6 T. S3 K7 q+ T5 \5 f2 M4 ^* [% Q+ Y
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']));; B! | |8 R9 c+ Q) B: E* w
这里有个过滤,但是不影响
# a, ? b6 c( ~- A0 J: E. {
- F1 T2 u" |4 A+ _/ P如果我们在这里进行覆盖这个db变量呢1 I5 F0 n* [4 Q+ x: p
- z9 i: W7 i: I因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));. P U% E; ^2 X+ @" B# e- P
2 V4 @5 A4 E8 k1 Y
可以将我们传进去的/ - 进行替换
6 [: t, p# f$ V6 J% w/ c2 i
- }3 C y- y5 q/ N5 ]所以我们如果提交如下字符
- A( c6 t* J3 U( X3 q
& g7 A4 h1 N4 e. F9 qhttp://localhost/phpcms/index.php?db-5/gid-xd.html
2 C6 y9 S( Z( A) L8 P. G( E, O: J* D& ~& B8 f2 _
他由于这个db被覆盖就会出错,所以物理路径就爆出来了
: U1 j6 p3 f7 ?
, z v2 f% P- T* M- _0×04 SQL注入!!!
* C, ~7 y7 c0 p4 V+ W2 Q
- w; h, w, e- j0 |* e3 | 在c.php中
) s. R. S; W! l1 ^# y( E& r- {" ?* b
- b' e6 N+ _% k8 v8 B H- P0 b3 b$ }# ^$ d$ J0 d# w
<?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']; }
" Q5 l" i! O/ \) x2 P
8 ?* g1 P3 r* Q. `5 R9 ~/ G
" J5 J* Q; X. k8 |" I c" b
4 A& R- u; }1 {" X' Q4 D G注意这里的HTTP_REFERER这个常量: V) j7 C' Q5 k/ f0 b
8 U$ _ i; v4 |/ F& _ F
这里的常量是通过前面的common.inc.php定义好的7 R! _" H9 l! Q' b& G% E# [( O* C
& I& C! E3 m5 g j. }define(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);' M& K( ~3 `/ q% A1 x
# Z6 j! [6 v, x. |0 {, B没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我
0 O: \% \) b+ V( R2 `2 E; Q1 E" L. U( Z4 c" L
然后
& _: q2 n! R: O9 n* \" u
+ R6 a, v: i1 A+ n: V$db->insert($table, $info);" @4 P2 Q1 O: G7 V* U1 c: L: }
我们来看一下它这里的操作
; g6 L6 E5 A* c7 S4 n
" ]* W* I3 c# e- [* M/ A4 Ofunction insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); }
8 Y0 f Z% |- g8 H& p& N" |% j% |) h
# |7 T2 L. t- I4 M5 g! X所以你懂的! K' o; d# G; g( ]/ S
* G* j S, {0 X8 C! B" j N4 R
& V4 G7 i" x2 U! ^3 i
$ C" z2 U' ?# q
附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=4045637737
8 Y6 x9 K, u1 X5 Q* y1 K! c1 S' a' m; q, N* s6 f! x8 a5 d
7 B* g& i2 D) K0 @+ s; C& s2 E L1 ]
( e! P' E$ J- g |