0×01 前沿
' l6 u8 p' t) U# W) Y7 W( }0 i
~! R0 r8 V3 O6 B' G. F& w; _ Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。
6 T* P, Q; s& c1 e; K0 f! r
4 I& k& C% q. w$ X$ k0×02 写在前面的话
3 ?0 O1 K1 b3 L9 Q1 m; |! ^" e/ a3 w* l& J" a
phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题% ]/ Y4 }9 G |6 o6 l
1 x# @- q. J! E3 z- R! D' d$ b
这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强
3 h5 Y# s N9 ^5 T) U* \: ]2 B4 X. E
这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论. D$ _9 l8 a: l8 d7 ^; L
- u8 k4 q1 |; f3 T
0×03 路径? ? ?$ ^9 j' _$ w6 e( G# w6 ^
' V" w/ p' `, V, v+ h; s 在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件" Q& m* G) C6 B/ S0 Z8 J
9 Y* x& v9 o4 W$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])); }
# n U5 Q" J3 [% ]1 |- j: N T4 }6 ]% t8 Z
这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的
: {2 a4 E" L4 b: w! g3 d. [7 d1 q. m# N$ A' {
然后就是将我们传进来的参数进行变量化4 P: G) L) [2 k7 I- x: v
, H) ^ I5 c q( N. {这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量
- ?+ ]( A" v' @/ _9 ?3 ?0 Q0 {; x/ ~+ F; j6 v6 B2 w$ r z
但是接下来这行呢?" K- s! W N8 H
% C; Q7 v% E1 r; W( L' i+ X( I, w
5 k" Z8 K( ^! d/ G
9 |, ?* d: b6 L$ N; g3 qif(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); }
1 N8 I# G7 F+ J+ {: G8 b
0 b8 {6 g% r0 e, y
' w' Q) e$ S0 f$ f2 z* R* E9 C$ s m- b
看看这里?
% Z2 T8 N( }/ w# w# g% p" |( Z9 ]- f
I0 g2 C. U% s c这里的QUERY_STRING来自前面
" S& z9 K( I6 }8 t3 ?, i# D0 h# `2 `" x' p( P6 d3 l
+ a% h H1 q$ e9 U* x- [; e9 M( i
3 Q, x$ O" b6 u0 D3 v* H/ }
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']));6 Y7 @# W0 T: L7 j
这里有个过滤,但是不影响
8 {+ i3 J- S$ R: X L h4 y8 Y+ M. V
如果我们在这里进行覆盖这个db变量呢; M( o- g' d) r, K# @0 p
# F* M& t& D* j" T+ l5 l8 L8 L" z因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));+ o0 f: ?8 T5 D5 P# _; m
5 a; ^1 A W$ }$ ?5 ^* [
可以将我们传进去的/ - 进行替换6 V. N' x5 @: Y% |0 [ s( f8 K. ~
% T- f- T+ L' U) [+ Y1 `: t' }所以我们如果提交如下字符1 O% D% Y" Z \% t
0 u" k; q2 J7 d7 b: Q
http://localhost/phpcms/index.php?db-5/gid-xd.html/ m0 n& M( ~ Y* l1 p$ ]. e4 H2 g
- n. b! X m& A' e$ B2 M他由于这个db被覆盖就会出错,所以物理路径就爆出来了- y2 g3 w, L' i" U4 ?- n4 n
( P7 G- \+ d# r$ \% Y
0×04 SQL注入!!!/ p9 y7 `: P' d7 i$ i# c) j
4 F6 A4 _$ ~! `7 j7 |0 A* c 在c.php中# }8 T& n `- P/ q& J6 |( o
+ I3 P5 } F" T( f' r M
( W1 e% a7 D4 Z
0 D8 u* l. X1 U: ^& M# l" L* j$ 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']; } $ P+ y/ @- v# m$ P7 u
6 H+ J# r; S3 I. D; K/ N
- o9 |/ ]6 ~, J0 G2 p2 b, s
5 y2 z/ t1 G0 g: m注意这里的HTTP_REFERER这个常量
! f q8 _. S; Y, V# S8 H
3 @. J& _* _& |4 s5 v3 k8 L这里的常量是通过前面的common.inc.php定义好的
4 K& X$ e2 c* C
: I; P9 {: C* Z1 {' ] wdefine(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);
( S- M3 Z. d! R" {+ p3 A
; [# a! M6 b2 @3 c2 R6 W, H没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我
5 J7 `; @: F y% T8 n3 ^
4 Y. z# O- r% \. N) v- i然后
l+ h7 t( \; H2 k% R7 g' E& q( |" \+ V I# s7 k4 @
$db->insert($table, $info); t9 u% i' m- k7 Y% [1 x
我们来看一下它这里的操作
: M7 F% w" j' f; u
& a0 a" S& Z$ B+ V. t& ufunction insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); }
7 G! H" H6 n! Z$ T
! P1 x% ?7 k1 G5 o. F2 Z所以你懂的 U7 s% a8 R7 O4 b( o5 h2 N( A
- ?4 T I8 i5 y. e
% r* R8 C* i2 D# V3 V
) e; d1 x% H/ |+ z) e/ T) A2 `/ l: n* `附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=4045637737! ^/ F6 f' _; _1 x. d3 s! d$ T
~3 l1 g5 g; e+ p5 L
. f# n3 x6 g* v6 z% L" Z( k' ~! ?" p" y; Y& h. n
|