0×01 前沿
6 D) a5 }6 b$ u: k+ }2 x
% n# ]6 q. ?2 p Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。: G, g. r! E; w! y. A; `
1 }' B" O* C* S6 Z% o0×02 写在前面的话7 I" Q# s5 L( i0 l- o/ r4 Y
" `$ O7 O/ k$ ^6 D* E
phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题
% o+ L9 ?: J; ~1 ?& U" y V1 S
2 @" u Y) b6 j% g3 W& q0 N; r W这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强# |' D& C' V- R0 _" K
$ Q3 `5 s& N i* Q) |1 h; m
这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论! _, ^% T5 T3 r; y( a
( O5 K# p! Q0 ^: N6 F4 s0×03 路径? ? ?
" U* p: P5 e# h- S
; z2 e# n" L0 N2 d( O s+ B 在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件
1 p2 H: O# q* t; R1 k) R2 n
+ ?, l0 X0 w$ O' k& R2 f$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])); } : g3 H% W0 Z1 i+ }" e
( \% \, l: c" `+ {8 S这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的/ Q, l% _5 i3 t$ c& [7 `- G/ ~
/ N5 p! E& U# o4 S! E. K
然后就是将我们传进来的参数进行变量化
- S4 W8 Q2 l& f0 r/ @
5 l: z$ M/ j* S这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量8 ^1 V9 R! L! r! {* q7 m
) p. q4 d5 f* F1 X1 w1 k
但是接下来这行呢?" x8 m1 E* b, v
! s) `/ e, F) w1 O5 ?+ x3 M4 O ) c3 R% H4 a# e# ]
. A) E7 Y. ?% Q* s( H) ~
if(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); } / v% C q8 G* C& E6 d: I2 B
- A) d- l3 |% |" G% R2 ]4 h% a
& v/ r7 r; _+ `! j- S+ j2 u/ d. G( F
看看这里?
, |9 P* g1 Q9 l. _6 d
$ b7 W6 B. }" j. E R8 G这里的QUERY_STRING来自前面
: Y& H2 w: O8 N6 }* J" ]% ^6 t* w
$ U& ~: N0 l7 n' [
. f/ W) D7 L0 ?+ x( O$ F4 n- E) O" q
) f6 W: F ~$ r/ K& v* adefine('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']));
( P7 _ g# A( ^这里有个过滤,但是不影响
% n( ^( Q e2 E1 W0 V
$ p. t+ n5 A6 ^4 [如果我们在这里进行覆盖这个db变量呢: u& F9 C4 r$ x) K0 o4 }
# S' Q4 H5 ]2 O$ \因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));1 V; U- ~( D& P4 N
4 U; K0 C" W* B* I可以将我们传进去的/ - 进行替换
# y0 c+ C! {/ M, H6 D* \( ?6 N( V. Z+ o8 g9 t
所以我们如果提交如下字符
" G( t( q! p% \! s) v
, O" g- z2 H, U" s/ T2 Q) Ihttp://localhost/phpcms/index.php?db-5/gid-xd.html2 M! A# p/ Y% @3 m9 _
5 I3 C* V" s+ F% |: w" T他由于这个db被覆盖就会出错,所以物理路径就爆出来了% H* l. V5 U0 P& I/ w) A7 Q
- H# ~/ X6 ]3 Y) w
0×04 SQL注入!!!$ B6 ]: b6 O& I# w
+ C2 {5 G" c: d& d" _7 ^' U$ D
在c.php中& \3 D2 }+ W/ E4 e
/ n7 O6 B' R* ]( q% t# I) k
/ D. e. E1 z- ~9 G' ^/ V
1 s; c8 c( j& U# \- H<?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 `. z6 E5 S8 X6 }$ w7 V2 c8 e$ ^
7 G9 t8 Q/ C( i
6 g9 G3 _( Z2 w/ d- i: T
) T' |/ I0 `. I5 \注意这里的HTTP_REFERER这个常量2 Q( x4 F4 ?' @
1 g& B3 s8 y8 K6 d, ^这里的常量是通过前面的common.inc.php定义好的+ b. y% P( l; ^. F
& K7 g3 E3 n! o6 {+ c* Q
define(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);
9 a' _8 _( n+ h3 t- H' |+ S
( {+ S$ ?+ I' C" U2 _& Y7 f没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我
: Q" j4 |! l# R2 y/ i" S: W: B- g. f. x
然后
2 @& o; {! D: ^. e5 A3 ?" _2 t6 h& U% J& ]
$db->insert($table, $info);* K+ [& l; r( L$ O2 p
我们来看一下它这里的操作% T2 N& C( T$ c" b) T6 @% k
5 N X% L* B; S7 l' w- y/ x6 Efunction insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); } % ~4 Q; p' R1 j3 c
& }5 z5 N6 W; Y
所以你懂的
7 T/ [9 a" F9 v8 b, _: T0 y }* k, V) _# F; d' u6 y
$ ^) ?' C1 A- W% S' T
# F" @+ b, R) D9 d K1 L附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=4045637737
6 E( N- h( ]1 v D
5 h9 k9 h0 C, i4 t0 v, ] & ~* f3 r* u" n) R
' g2 O0 T" P# j- A( P
|