0×01 前沿
; X' i: O( a" T# s2 ~, t& C; h+ g& l6 {+ a& C2 R2 h) f3 \
Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。7 t/ f n) j1 t
) T$ N) W8 S: ]2 r. F A0×02 写在前面的话( @. w' ]4 v9 ]7 L
0 {# E- L5 R- f# b% s phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题& M% M n6 L3 A; r, M
, f+ n5 r/ _6 g* g% k! x; R0 B8 C
这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强
7 i! a- e" J$ O f* E8 n
' @+ ^( s$ C! L3 _+ Q这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论
) b6 s+ d5 ]- b8 p5 G) L& J7 N6 x2 ?- v
0×03 路径? ? ?& U: M, t ^! t8 Z* y! l: L
- p; I2 O/ s; {; K; m8 [ 在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件 p$ o3 j/ ?! V, T. ^4 P& o2 H7 r
4 S1 c5 H& U4 F8 t9 @& {3 { k( j" {
$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 w5 t3 Q1 D! j& e+ Z6 N H( R/ Z# e8 g) X- ]5 y0 @" x
这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的
' ^' G' |" i, b% g( r3 f) @6 |' |8 Q& s" ~4 K! T7 t# z
然后就是将我们传进来的参数进行变量化2 f( Q8 L4 n9 N+ ^0 y" Z+ B
6 K) [* c1 y& z# x0 Z1 ~
这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量
- ?* x+ w, O5 c5 w* C' B$ T" F1 W! K7 j
但是接下来这行呢?
9 V" e( v7 x3 z; s3 t
; W, h& F: M9 H1 {, S: z+ x
3 W. y U0 S9 {' \ E) ?6 U
& ?) m, T' d- q* ]if(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); } ; e. p: [2 h9 e& s' I$ |0 d7 @( t, k
, l3 T5 U# Z E5 B. t
$ l/ }7 y4 h' ^! v: d) r
. d9 q9 V M# Z( i3 f看看这里?
1 b6 b/ V; p4 f x1 b! |: T$ U: n7 n/ U1 b+ g
这里的QUERY_STRING来自前面% \4 d' c5 d6 I7 R* Y; h0 P3 ]0 q
4 b) r: a% Z6 d1 d4 x8 T, |' _
$ I, l: G8 C& D6 r: x7 N
) ?/ z. u" @( y% \9 O: `- \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']));
+ G- k r6 j& W0 i( J这里有个过滤,但是不影响3 r9 Z+ e! N2 |$ m( }5 d
+ q4 R# i) |" J: Q0 L! P如果我们在这里进行覆盖这个db变量呢
1 U- U" l9 s- c1 E; {1 V; F
& R" O) `8 C1 B" q9 j6 n! w% y因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));
: Q" N' W2 G; q2 X, C
p6 Q: G# j# x( \3 n可以将我们传进去的/ - 进行替换
. W# T# w, K/ T0 P5 B
8 J/ Z$ ~0 z# H f' q, }& m8 e所以我们如果提交如下字符0 z0 A2 o9 Y1 H7 I( \. O6 j1 s
1 n' r' M6 u( [0 i) R3 _http://localhost/phpcms/index.php?db-5/gid-xd.html( z; x6 c+ X# J4 g5 M( g
% s, |/ r* n$ X) {他由于这个db被覆盖就会出错,所以物理路径就爆出来了
: G O- H0 l/ X! l5 Y4 I t
( T4 [) Y( T" `9 k' u. a7 w0×04 SQL注入!!!1 P6 \' E7 [+ P( \: u
% T$ ^/ {3 E( B8 } 在c.php中
$ V' K1 T' a+ Q8 w3 u
: E# R1 j: `" w2 Y, ^9 \* V) M. I
4 Q/ L0 F* O U. t: Y; g0 F% ~- Y# M2 {1 R U1 T
<?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']; } 6 ]2 K. s0 w8 F; U6 g3 A
7 Y+ H+ R, y$ Y+ z9 w1 z# k
( D- ]9 C A5 |/ d& z( ?) A7 B0 ~3 L$ q# y( ^! F
注意这里的HTTP_REFERER这个常量
8 a' L+ r% t+ @% ~: p0 v; C/ ]" r' w* _2 k. W
这里的常量是通过前面的common.inc.php定义好的! e7 [8 O! g; H6 x
8 R1 [- P; I/ {
define(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);" o% b5 z; f* ? m9 y7 N* X/ f
4 h- v: i7 |( a( u; y
没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我/ d5 Z0 g5 t" ^% H: R) j* i
" { J8 c9 R1 c' J+ @ U然后
8 J. Q" K8 `$ w" s G3 n: | c% p8 i& W. o v
$db->insert($table, $info);
5 a/ W( L7 P/ c6 Q: T我们来看一下它这里的操作
+ U3 v5 t: S) a" ]9 I; X& ` {' |5 p% C4 s1 w
function insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); }
- {2 p( z3 _' H* {) j6 J
0 g- Z& g+ A( T3 Q所以你懂的
+ u/ }3 ^) k# P7 h- M
3 m( T' m* s. g1 @/ n6 Y4 w3 ]
* P! ]! R' p0 |/ P) P4 y" u+ n1 R5 S& r" b* @
附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=4045637737
# h: E. n: ~9 H7 y8 z) e' b. i
1 u2 `" D, Q. d( ~. Z
2 s1 }* @! \) [2 j |