0×01 前沿
1 A3 @$ T) ^+ n( q- n# o" L1 L8 r" v$ H
Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。5 P% Y" C4 |" B3 c
( H) i) R9 f B1 ^4 t1 a5 T$ i: f# b0×02 写在前面的话
0 [* v7 J1 ^5 I3 w; {$ G2 t
0 z8 y/ p1 q7 A4 Y* P6 @/ P" O phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题4 w2 h' }8 H! x, w# }
3 m' n6 {; g/ R# _这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强
8 A5 @% ]9 h$ I I! o% Y/ m4 I$ S% h
这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论
- X& Q: m4 C' R9 P8 u" i& n# D7 ]+ d! K
0×03 路径? ? ?
3 a/ S" \8 s6 ]
! C1 _6 |0 M& ]0 G! e 在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件% X4 @- ^/ K# [" D3 N% j7 ^
9 {8 b7 H# j) X" K
$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])); } ) R& @0 J i' z+ u
9 r/ j ?: i. Z8 j" j
这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的
& B( _, r+ S$ B
$ d- Y$ Z" ~8 }) b( i" g* a6 i然后就是将我们传进来的参数进行变量化9 i9 C) R; D6 o+ L! ]6 j! D5 U
6 k+ V# e. y0 r5 C
这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量! ?5 U5 Z+ U+ `, I/ T- s
. @: c1 [9 r m2 ^$ K6 @但是接下来这行呢?8 G5 M' j2 A a7 k# M
4 d4 p8 b0 o }) i; }: `0 G 0 h" F6 W) n5 T: N' R' `
7 G% s c+ f9 V( T8 i: a
if(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); } " h+ V% _' T; l% h; |
' ]3 b# d. X* W s+ x; o# t5 R ! U9 ~& O }3 @, {' r
$ |; n+ E4 y4 C: c) ^: |( A0 J9 x看看这里?
( g( g: h- p8 }4 k/ k. H# Q% Y! [) s. H8 Z9 I* a
这里的QUERY_STRING来自前面, X' u$ C+ v8 _: C, y
. q) X2 Z, }3 v" R- n: q; t
8 ^5 x* z9 b2 I- e+ t8 |. }' b% z
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 D5 V; I% R0 H0 L
这里有个过滤,但是不影响4 s' w1 d) h$ v
( w) r9 I* E3 `4 ?* D* F4 K如果我们在这里进行覆盖这个db变量呢
( A$ a' N9 Q( Y5 W/ Y' Y) m; _ l A! Z4 V0 i4 E
因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));
- T2 m0 A! V d2 G+ u4 T& h
' A* Q7 \4 X6 [) X0 W可以将我们传进去的/ - 进行替换
+ n- x, H" n) d+ s7 U
1 _: d! e- l4 O3 e; J* q6 R所以我们如果提交如下字符) I& e& p2 t6 U' H* @; y& r
_2 n& G6 X. t8 r& M! \4 Hhttp://localhost/phpcms/index.php?db-5/gid-xd.html4 ?, ]2 b- K: l0 @0 D
& L# U2 w1 |8 K1 _) z% m4 X
他由于这个db被覆盖就会出错,所以物理路径就爆出来了
4 X, t& {5 q$ ?8 Z9 w9 I0 u
/ T2 v7 ?- H( _: f0×04 SQL注入!!!4 f/ V2 [$ q( d
$ \! h, }2 V: U- e" X8 Y" q 在c.php中3 |. X6 K7 h/ f& b' ~ P
3 _ I5 S% s. c2 L0 Y+ i
4 p% F C2 F( W8 Y5 f2 s4 N7 F2 |9 D- u9 X4 n
<?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']; }
' ~& R2 M5 e: o" l7 b! ^- W$ C9 [5 o$ \% f2 Y% B. P
; ]' J5 i% ^5 U- f& D r6 Q8 J
注意这里的HTTP_REFERER这个常量4 W3 I }) u( d7 }& s
3 a" ?; I) g Q
这里的常量是通过前面的common.inc.php定义好的4 j5 v* j. |4 ], S. d
- M% x3 N* D5 H- q2 _0 Y2 a
define(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);; B# i( m% L6 [7 i
! r" j. u& e. G% U, t$ K/ L7 X没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我
0 G$ M/ M; S/ H, ]8 O. D! G% `) a& h1 u8 ?! ^$ v5 t5 H
然后
6 m, T) Q- z+ m
; v3 O) t8 f2 C$db->insert($table, $info);$ ^* U( B8 J" q3 g
我们来看一下它这里的操作: I2 L0 ~7 {; v, C8 ?# F2 A
6 @: A1 a% Z+ q. O- Y( s# t# P/ B! t
function insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); }
/ {7 d( G0 i3 Q! y+ i: D9 y- s. q" i0 }4 I( q, {
所以你懂的6 @; P/ C6 q6 R8 W! d& Z0 x+ \
+ L9 [* W% P7 S4 t. }. Q" i& K
2 C$ ?. L/ D% y6 E8 h" n
* a0 m) f' K6 d- h: Q& q附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=40456377374 n5 v V/ L0 k+ _% V' @; Y
. a% K) z3 x! W/ ~4 i
( _( b" e& T: K2 d- {, y( r, E5 [& v& z, A7 S
|