0×01 前沿
( N& ?3 g- k, C7 C9 ~
% \$ D8 s, |( H8 l7 a" \. o Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。! X4 F: s% j/ Z# c0 E; J, n- _
, v' x3 o8 m# S, G
0×02 写在前面的话$ n% ?* e" k/ _- J0 v: q
2 P" x4 J# }6 s ^! w) @5 S
phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题
' Z7 b' {+ b3 Z/ h# ^6 v! F
1 j9 l1 `6 I3 B( \0 h这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强
- q: ^* L1 x s
1 f8 ?: Q H2 T6 d0 A. G2 G这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论
8 O. O- Q. @* n% A8 F: [, M8 u* m, E3 v9 ~/ O) A1 B; d
0×03 路径? ? ? r5 h3 I, X& F
2 E! Y9 g9 V5 D* c7 [
在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件4 C+ D6 z& Y, y" C6 |1 t6 p
# D8 t- W( Z+ b5 D# q7 g. a& H
$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])); }
0 q" ?" W$ S: k/ ]
) ^* E* @: i% M" W( D这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的( P0 @& [7 H& |/ N2 ~+ Z2 Z2 v9 ^% V
7 `: n+ w9 h1 `9 c6 a; y然后就是将我们传进来的参数进行变量化
8 t' @2 V9 L$ F% X4 ^
+ `1 a/ B' T3 Y* q; ~这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量
9 a5 z3 m- g0 u3 z$ j: E/ ^. z. P8 I# C$ e
但是接下来这行呢?
6 k5 \& `& ]$ H% c2 P) J& a% T" F/ R4 E( {- h8 U
# m3 n- T/ N8 f& y1 \
* i" n8 T/ |( _) K m0 aif(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); } A6 L: M" q. @( q- C% r
6 N+ h" z' o+ W9 U
" }& p o! {! A- V. U
R" p( T2 U; g9 _$ W) ^看看这里? e' [9 z* Y: e/ a3 U# U& l
9 W+ A0 F4 f& w4 n* W& b5 l6 ]# p- }这里的QUERY_STRING来自前面
8 x8 @9 Z! D/ A% R; z8 \# H- c0 f) k p1 i
5 I8 L3 g2 H& ], n. d4 H
) v/ J$ e( V1 N8 N: rdefine('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 ~- T7 b2 z+ o! ~7 }) i+ d4 z
这里有个过滤,但是不影响0 p/ Q" J6 u$ K3 H
5 I+ x t* c7 J W: k
如果我们在这里进行覆盖这个db变量呢3 |9 S7 |! K" I0 T& r
( N5 A8 m3 _7 r! d) D因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));. }7 ?1 @) B; N7 Y: W- K
/ M# m! n5 H% z/ i" ^可以将我们传进去的/ - 进行替换
# I9 f5 h7 r7 \' G
& h6 l, ]/ z8 }1 \8 Z" F) I' V所以我们如果提交如下字符
8 L' v6 Z8 J; ? k0 Z/ w- W3 ?0 A
http://localhost/phpcms/index.php?db-5/gid-xd.html2 U/ Q5 y; k/ w& D
# m) h1 D% i9 s8 I! D# U, A
他由于这个db被覆盖就会出错,所以物理路径就爆出来了1 R/ K/ q& E: a: o
: \" c- w# U. F% \- O Q0×04 SQL注入!!!
?7 U/ G" E! J3 H$ X
2 X, R( ^! D* x. |7 a8 \ 在c.php中
6 n. C" \; e$ W0 h" e4 G
: u d/ [6 ~0 Q# M) ]
8 }! `1 N" @9 Y- S- [7 d
8 `9 f* x; k0 o# {' ~<?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']; }
' ~% Q; e) ~3 e i# j( l: M$ v4 c# s; `8 o# `. d0 S
[) I* c, C$ h6 Y/ D
. z' Q [% N2 }7 X' q( i4 u8 a
注意这里的HTTP_REFERER这个常量
$ ]2 W1 G- |, c
& k# v* |* [7 T: T8 C7 `; G这里的常量是通过前面的common.inc.php定义好的
# b9 q. ~1 a+ o6 j! @" m+ ^7 T9 w- G: ^' ^3 ~ g7 X; U
define(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);
! ~4 L6 U: S/ I; B: b0 D2 r G& T( i! ?0 G1 ]' p
没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我
6 J% N) P* z4 u4 c) u% |/ O; q0 O6 W. X# R* }. b; T) H
然后2 a( q/ u8 H0 d; B, j( W
0 k) B3 Z9 P z: U$db->insert($table, $info);
9 l$ a% b. h: x: ]我们来看一下它这里的操作) r3 W7 E) S" w+ S+ l* }+ [
& |/ i% f- I$ a- v; x2 x% |
function insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); } 1 X; |8 I4 a$ j$ Z5 Y. n
! y( i4 S7 U [! P' o4 t所以你懂的4 ~; b( U" ^6 M# k0 E& X; w- Z
1 B$ f! N2 D8 J5 P % |$ f# U( R9 a1 H* p
$ K1 T5 s$ y+ i% O1 Q附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=4045637737
4 B$ t2 C4 m% W
# }9 ]7 R+ P: i- {8 p
p' }" b" ?7 _
- o, }- W) J2 b3 T |