0×01 前沿
$ {; |/ z5 |) L2 u3 R! C4 p& Q8 Y' l; f; a p) B3 q6 @" f8 _
Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。
, a, z" q/ `3 s, |8 C) t3 U
9 b! P$ A$ c6 G* Q6 Y0×02 写在前面的话5 g5 u" Y! y9 N* _) g( Z. d
+ V) ]7 C& p* t+ c( X/ P- H phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题9 d9 @7 Y8 _* j* `
1 D, s: `8 {# \) |) G0 b* Q这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强
- n* | r! F+ ]1 R- \3 F# I* _9 w C6 f+ G; I+ @ l1 {4 c
这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论4 B; f8 h% {" P5 v/ G* j2 E
/ Q( J; R) y% ?
0×03 路径? ? ?
( G6 q( e! V' |# o& d
& I8 y6 |5 @. ?/ }1 }' l% \% @7 @ 在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件
$ p4 T3 W6 ~* Z$ c
* A9 K: y5 q2 w7 w2 E$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])); } 6 m! q; f* Z9 H- }6 R
a5 ]; i, v0 S) y# n4 Q* h
这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的
1 A: p& c; j! f) z7 g
: P8 Y5 U( m, I& W; G然后就是将我们传进来的参数进行变量化: G8 `' N$ q0 |
, n9 X% g" e I6 j) j! @8 E( B' {这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量' W, C, J g( ?' H
- c+ E. x1 U% N( P( P9 |! s/ c
但是接下来这行呢?
- \) _- i; k$ @" E' R5 c7 u( ]1 e8 f: A6 T F6 O; A0 M1 ^
J) J$ x& K7 F; X" Y. {
* M; w& Z& A# J' i% hif(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); } # V" f d# e! c# I0 ~
& R$ m' X* L7 B* Q% b( }
% l I1 q4 F; J) e. C
( T0 M; M& U+ j _7 |看看这里?
5 Q- C) n# @: n' v/ E( s& T/ @4 \6 y- H
这里的QUERY_STRING来自前面
0 r' A" s' q/ w i
4 p( t; X: F( a: B; S
7 b+ p8 O! a! l* S9 c% k: X; _! f/ \' U- @9 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']));& a+ v9 S; j4 O4 w0 K
这里有个过滤,但是不影响
- i$ v- m/ Y. Q' {
1 c/ ~% s* P7 U1 n1 |( j如果我们在这里进行覆盖这个db变量呢2 ~) x. A7 I: E" Y' g
, r& g) E3 u4 N因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));& r( n' t4 D* I$ [/ j: n% r
' G+ ]9 U* w+ X1 G, \$ o S
可以将我们传进去的/ - 进行替换# R, l+ Y9 e% n! p. A
" p! k+ u6 G7 d9 Z3 C& ~$ r0 V+ ^
所以我们如果提交如下字符1 W/ g. {8 }( e
7 J/ @8 r0 c% ~2 S* Whttp://localhost/phpcms/index.php?db-5/gid-xd.html0 \$ z! p# Z1 k* \+ N
- Q& ?, {, [2 W& R" A他由于这个db被覆盖就会出错,所以物理路径就爆出来了
. J* a; k6 T2 ]% G4 `
% o* A3 U# v' z0 m+ ~; E0×04 SQL注入!!!
2 G9 a7 X: u: w+ K" b+ p& t* p7 @& I) y+ h! c
在c.php中
+ S$ b0 X# s0 q, r4 `& B# K7 ~- l
& e' V4 f! N9 e7 b' V! s5 B* C1 e3 F) ]( o1 ~
<?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']; }
- I5 e: D9 l; l7 ]/ w! K R
( f, C U9 L. k2 \, B/ ?& I % H4 X0 Q! t% x1 E# J G& U- }
* _1 R9 y/ L/ F) V. p2 q5 o* {' c
注意这里的HTTP_REFERER这个常量& m8 `, X1 N# O4 V; D
# r2 G' B! j' N2 _
这里的常量是通过前面的common.inc.php定义好的# d0 d9 Z7 Z% |$ P8 f. p, z
' r7 A8 X( f3 x; N
define(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);
4 F+ q& _2 g; }! [' y3 O
& J0 t$ L; l: n, h没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我4 ~% }( U0 L) J) S1 z
1 U% }# |7 O$ b/ F" @6 E2 i5 @4 `$ A
然后& _5 p% S; N; R8 b
3 y) S8 z. j. [7 {/ R8 u* y# S
$db->insert($table, $info);
& C2 K2 G; N; @4 q; Q7 v! l我们来看一下它这里的操作* U' x: B5 K m. W! e4 F1 a
4 U! y. `5 u% i% U: @8 V$ afunction insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); }
, |6 ]0 ^/ c9 A, a" ~
1 O4 Q) T. \! ]5 o8 \所以你懂的
# n! D X: U5 Q6 W- e8 d' ^% k: H5 n9 _) I( z# |* K5 n/ L
6 ~6 n: g. y- g( `( h; f
9 O2 ?( S# Y# g5 i' I$ x+ s附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=4045637737
( I& n; q5 C5 B& U; _/ m* ~0 K* s+ p" A- T1 U3 ]
! ^! `* c3 U% z) x3 }: Q8 _1 E: P4 V+ f$ ^
|