0×01 前沿9 h. M5 O0 v$ m* t
( }! p1 U, Y& @6 F8 k# ]8 [2 R
Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。' Y0 K$ q7 I, y% a7 |* R- [0 `( q
1 k+ o1 a* U% j9 m
0×02 写在前面的话
: j9 R, T# j6 r7 d, [7 n2 l+ y; U/ w, }) j8 e2 z* u- v
phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题- Q' k x7 ^( P8 }6 o- J7 H
; M# y" l9 `; ]; K# g2 p2 V这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强
# h& {# g+ U7 m. [* f) V: }" A2 t: J1 o
这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论# M& R: l9 f, R7 p+ X, b9 C
' [% C& b, f9 ]% b6 d2 v1 r0 O4 X0×03 路径? ? ?6 w' k7 |, g2 \/ B
5 g1 K, W' n; v- b( h" T 在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件
: M# } v* V: K8 L, R% L7 e. ~. c
$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])); }
% ?. V& {0 ~. e. [& e4 X8 v; I! s6 s6 g# o: d) A
这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的
~0 B2 z+ L0 y Q4 Q
' X% L) @5 \# w: H+ c8 C: K然后就是将我们传进来的参数进行变量化
2 V( y, ~# ?! {$ P1 ?- M% F/ w: U$ \* X5 C# E( V. O
这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量4 k& W) V& {# L9 X% w
5 Q }9 P, r g& x8 q6 A. ]但是接下来这行呢?
' X; B8 e5 S; a" J5 _3 y& ]$ \% u+ I6 t" C* N
8 m9 x! r% c2 }' f; D) v( k8 f4 U
) {# X2 s' Y' e6 u" m. L4 @+ B
if(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); }
, c( B+ R7 y7 O$ `: i* M$ c! m i& b# j& Z
" Y5 g; P# f3 j2 Z* E
& G" \' c' K5 L5 n看看这里?
( u& A; f% A* y# e7 J% ~, N, ]1 n) t4 M7 z
这里的QUERY_STRING来自前面2 O1 ^0 e- M* W C
( P+ t/ K, C. \, B3 H/ L. K8 x" ~
3 z6 E, P) r; o- t
, Z4 O: d3 c: r) s* ?9 f# \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']));
8 ~# j" W' T" K这里有个过滤,但是不影响' S& D0 }$ X; c$ e
9 @* c1 r, n1 m7 S1 g! M
如果我们在这里进行覆盖这个db变量呢- m8 B) e9 J3 a( i) f# l% y
s7 X5 f# @- C b因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));; L; F; G# z5 z% F3 c1 f
6 v3 w7 c9 I6 z
可以将我们传进去的/ - 进行替换
" Y$ }- t9 n* H3 t: A* V. Y. ]1 B& O) M+ f- K% y. H% u
所以我们如果提交如下字符) f) J5 _3 U% S& Y
# \ m2 |$ h; d3 Q) _6 p
http://localhost/phpcms/index.php?db-5/gid-xd.html
9 y& [0 E5 S+ T) Z) |6 z
/ s! V# F. L/ {4 U7 |; E他由于这个db被覆盖就会出错,所以物理路径就爆出来了/ [' R0 Y* T1 i$ n# M
9 v- Q: b3 [9 X. A8 c" ^ ^$ y0×04 SQL注入!!!% T8 N- _3 L' G0 N4 T- T# n1 _
# N6 O0 V/ J r" E I 在c.php中
* J+ T- i3 }& U# \' c& z P: J% y- v1 b( m# R
! n+ @3 f% q4 n& {5 ~, y/ e9 S0 L6 I; f5 H: X, Y
<?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']; } 3 [# Y4 n& A/ ?3 G1 B) k2 y
/ _+ a- u2 b7 f7 l1 V) q) V) g 7 r9 s' V" {) p& M, r! R
! \1 ~3 H2 y# C3 W4 [! f
注意这里的HTTP_REFERER这个常量
4 v0 W' T3 ^& d- B" C
. ]" P8 c1 C2 _+ S这里的常量是通过前面的common.inc.php定义好的& ]2 Q6 K% S! H- l' \* U9 x
4 Y: [" l, J w7 S* B
define(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);( z: G6 k7 u* u5 \/ m
/ d- _0 V9 l& H8 L8 c1 P
没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我
2 w+ t' G. r4 R3 P5 X$ h
, o( X. p8 N6 A- o% C, A然后' j; g. a+ @# w u" F* s$ }
# W6 K% _3 p/ x1 a: p) d0 U
$db->insert($table, $info);/ ~' r- c+ [/ X: u9 b$ f# ^
我们来看一下它这里的操作
* S2 Q: O8 e9 L+ k8 A2 `! l/ G6 K u- z5 I$ ~
function insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); }
5 T; x: T) P; g: M- O/ ?, w7 F
$ G) D0 E' r9 I' g* N: t所以你懂的
' z" A* ~' u6 h5 ?; z. ]
0 ]4 {' H1 R8 f) \ k) j5 _
. Y9 r: o6 b# p8 U, \6 `/ t
+ A0 D R+ S- P( _- U附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=4045637737
% l! X* U' T- L& T4 l5 P2 D" c0 \- [4 ^% m
. r) Z( |; c- \4 y f
6 x9 l# `6 |, z& l/ `: w
|