0×01 前沿
4 @; ?9 N) g0 b; L' O6 Z5 l3 o& }3 c) [4 O8 i" v
Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。! k3 e- z, [$ j7 h6 r$ K
+ [1 {3 _5 T0 V. D0×02 写在前面的话
+ |' l' U) K+ g, a/ Y
3 H3 J& i7 f% I; B" s% m0 U phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题
% O+ ?$ m" N. y# _% ]
. a' t* O7 g; K* M5 H- q2 K这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强$ R5 m, q8 p) ]# ^ H* X
6 H2 f( K" H# Q' a' k; b0 T这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论6 S5 w7 D8 j+ q. A5 `
6 \: t C }; S k
0×03 路径? ? ?" i; H( i# K( q& D! Y
& m1 X, l3 ?1 o9 h. D+ e
在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件
& j* D7 B e$ `
. \ J7 v) C; Q( ~/ V5 F+ 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])); } 9 s# y. K6 F9 Y. S
* t9 V4 I2 s+ i9 z! D8 h6 G这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的% W" l6 `3 C! p9 Z5 [
8 ~+ z3 d) S3 _& o& M6 f/ w
然后就是将我们传进来的参数进行变量化
: m' ^$ {- B: B$ ?1 @% o
1 Z1 ]# K" a6 f% C这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量
8 B/ R) Z1 R% z& i3 x% F: N4 |4 H
$ _7 E$ r# v$ m2 y2 g# h) H但是接下来这行呢?
' b6 F [: \; `3 \8 [0 t; E" Q/ a; i+ @
' K+ @9 p' N8 P. o 3 S5 R; } Y/ [. b! e" e* X( H
: E9 H r' w6 w) @if(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); }
/ X' }: d6 a7 l# _# s
# G5 n; z$ z8 L% ~. h9 [- o3 U4 W
3 _+ ^ k/ i' e7 b# z
+ ~0 i7 D. e* u! V看看这里?
) t( [' S1 Z5 P2 j2 j
, R; n+ j! q5 }& ]这里的QUERY_STRING来自前面3 f5 d( P2 b/ b) @% K# e" E1 T8 O
7 p) r% o. O* B- ~
- }) k: H" H' s2 d
0 \, U9 @, g9 ^. {+ mdefine('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, m! t' w, p
这里有个过滤,但是不影响. J: e6 [+ z3 _! n U# X
$ K/ V0 ~2 c) D. Y: v( a如果我们在这里进行覆盖这个db变量呢0 f6 S, @- o9 l+ N! C0 s2 n
5 ]8 a4 N9 Z8 J# K! Q, G+ y3 P/ x. Y+ ?因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));7 I2 M; ?, u3 X+ Q! X+ T- X: I
0 B, A' B( {" A8 T, V( m4 Z可以将我们传进去的/ - 进行替换
/ ?/ v) Z, ~# s
* j0 W4 ^) A8 J& n/ P. s所以我们如果提交如下字符
1 \. K8 d$ x- W/ `- D/ Q/ c! B h. x# g! L- Y6 U1 j
http://localhost/phpcms/index.php?db-5/gid-xd.html
' O" P* {) n) Z, U+ B! U% g# x
2 i/ s+ X. E& V% g% g他由于这个db被覆盖就会出错,所以物理路径就爆出来了
5 ^5 ~5 a2 O% \; w
% ^( d7 n$ @! b! V; t. a5 ~" M& H0×04 SQL注入!!!# R. A/ H& S# K) k
) w* h+ z7 h( ?) \; j7 c 在c.php中3 @8 w) I/ ?8 p* G
3 ~$ q% C; P- M' A/ ^
) s K9 L; s1 Y9 `
2 k0 m5 T. L, T* y, e<?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']; }
* }% K$ X, J: h! V$ T2 @, ]8 m1 z0 b# Z$ n8 ]. Y1 |+ N
+ c/ @# f6 P& z/ o) Z7 @4 [! N( K. K: n' d
注意这里的HTTP_REFERER这个常量5 t0 ~( j7 R" ^6 J3 }$ d8 c; k
# Q7 O3 g/ d1 s' q$ L9 P这里的常量是通过前面的common.inc.php定义好的* [- |, P. U$ q- s& T3 x
1 r1 y- n2 e8 z5 h: m7 d2 z( T- g
define(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);
( b6 T$ e4 \8 A4 @$ Y3 F
% X* V- D) A6 ]- Z1 D# |0 E% g没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我' W) q: w. q) G
6 t l0 z4 [ E) |$ o) V然后) {4 U* p4 R `, X# K
" G! X5 K) G$ V: M0 V$ Q$db->insert($table, $info);
7 k# w4 T% @* w6 k* |, @' y我们来看一下它这里的操作
/ `' V, W$ A* l6 o+ Y$ e
: g+ z1 p) E1 I+ @! S4 G3 ^, u3 ffunction insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); } 3 r E8 U }. f! S4 X0 H
* ^8 A0 H7 [& \
所以你懂的" l. {; n; b/ L3 e# @$ U2 [
9 s3 C* M- a- s# {9 G) s( a
t' Z3 U" R& Z8 j* H! }& t" _
- ^0 Q; T. h5 Q+ N) E5 X附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=4045637737
' R" R5 L. N( m, |% `3 [* t- L; U# ^2 s3 k6 J$ k9 p
' l. X/ B0 j0 U7 `
; p& F8 E+ C/ T8 Q: c5 s- h$ H5 `
|