0×01 前沿
# I2 i$ Z" n2 T# B- F1 O2 i7 E4 f! b9 N0 h4 B* Q H
Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。
. V7 J' ~; @7 \% E+ f2 w
D' G" o( o. n# y) d7 Z0×02 写在前面的话/ t4 I5 F" c' \4 w, C
3 e9 u$ J' p- {8 m: s phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题
( }8 c. h g, ?3 f3 h: [ J
1 T6 ?7 W6 J! | Z7 K7 w这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强4 Q+ \1 X4 V' Y5 z
2 n# D6 @' X8 a* _2 D) G! n
这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论
; B' m' g1 Y, I& J6 ?" K3 [5 `: g4 }- d( H# E% p8 A
0×03 路径? ? ?% M, ]$ J0 N1 v- l4 f# W9 g
8 ~6 `1 z& b% j; P
在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件
8 G. A* {8 L: j# T0 ]) @9 e! t) g7 F$ D
$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])); }
; h7 A, k5 ~7 Q% T/ h& D' o0 A
这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的
' f9 p9 Q. M* e$ N9 K- R- ?3 f- q; J/ Z- o% |/ R& M$ N
然后就是将我们传进来的参数进行变量化
; i6 g! `. m1 I! M7 g8 B* K) D: ` }. A. k; e- d: S
这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量
8 t+ C+ ?3 K+ k/ F2 d1 I, e2 v; x. Z4 r+ \" x# r- \
但是接下来这行呢?- M- w5 K b8 O/ H' q) P$ ~
, B% s" G2 h5 m; g) |+ v& V 8 _. s6 F% I8 }! Y2 O: a; |
$ W% S; R" F3 C; x& c
if(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); } 6 O$ L/ k' I8 t1 L( |
: Y6 ]7 V6 f; {& V& k ( J* T2 d; `, `/ S) l
* {% W! W" y+ A' J3 g
看看这里?
m' m$ Q# Q) L; R0 \- N8 _, c# W
! B) B, O( V' j _2 i+ P3 ?这里的QUERY_STRING来自前面3 H! i5 s$ p! B0 [
9 C9 c3 t/ Z4 g; S# S, L
, T* k( y9 X- y, N3 n! P6 t- _' o: s6 [+ T% _% H7 K1 w
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']));
) R0 W7 ?& |" H0 @$ n! w. P' z& o$ Q这里有个过滤,但是不影响
, s4 F8 V' I, Y7 Q/ f0 k, H: T; j, h" K
如果我们在这里进行覆盖这个db变量呢, Y' }! c" m. ^) J) \; R
# J9 R" g) B4 [
因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));* K4 B- I5 ^% M0 l3 f- `
3 g3 J- x5 Y5 u8 T6 S* u可以将我们传进去的/ - 进行替换) u; G+ @. \7 F* ~+ ^ f0 O
( L/ s5 f/ h6 Q所以我们如果提交如下字符3 W$ F$ g* u* x: U2 k& U4 d
) |9 n# R* [1 X& x. L. C
http://localhost/phpcms/index.php?db-5/gid-xd.html: {1 n) J! @' U! M! U7 g9 l
/ x, i. M |; Y/ t他由于这个db被覆盖就会出错,所以物理路径就爆出来了
5 h9 O+ L# X$ J) S" t3 }# r8 l; g; h; ^. W7 [8 ]) |4 J# K
0×04 SQL注入!!!
; B2 Z; _5 B. } O/ e$ N7 S. Q+ C( \
在c.php中3 l3 N# |. Q- C/ j, I. T! X' F
Q/ U' x, P6 S7 ?
4 X" i: E1 ^. M+ J* g+ c8 b" a8 ~! r- O ]& M
<?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']; }
L ~/ T- p: v9 ?- p- a+ s' t5 h1 r" d
! B1 S/ ?- `/ q2 K1 T+ W6 @( _; w, P& J
注意这里的HTTP_REFERER这个常量
. n6 Z* b3 @7 l- {' T/ ]* { o* f7 _* D- {0 {
这里的常量是通过前面的common.inc.php定义好的: T" L( e8 O9 q) |( y" b6 c8 h8 W
# m' P8 D& i; h* t- w2 B
define(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);1 P l6 w+ U6 E7 X" x: ?5 C
9 R& h: L0 V# x9 O+ Z# x
没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我# i- j+ D( a* r7 n
# m0 l) }7 n1 M0 o7 N, s5 w然后; ]# Q5 F7 R) ~& N( V
" L! t( m: `2 A' K" q
$db->insert($table, $info);9 C3 b1 P) r( {3 K) C
我们来看一下它这里的操作) K/ W% a, S. m
" H# u" `$ I, L1 G4 q3 d# P$ H. Wfunction insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); } 3 Q, @1 I2 ?' c4 K- b4 _
- C/ u+ b+ V, `$ ~7 P$ h' \
所以你懂的) x; d/ Y' l. `) P
; I0 b9 B6 L' y. T3 M9 I4 r
+ Z3 a. _6 E0 N2 h6 T- \" G9 v& O. }3 Q/ P" M& G7 X
附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=4045637737
! b# K+ U4 k3 D1 `% a; L
8 o4 D3 k1 b3 P7 e7 v + n( e" O/ t' q/ t7 ~! N% a
4 L& w8 z( i. c0 @ |