0×01 前沿
5 m* x5 H; s$ o5 Z
! ~/ A9 K5 W% B- l9 c Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。7 G ~+ h$ O6 k% g4 c
7 L3 }8 U0 K/ l; t/ F0×02 写在前面的话
`& ~' a3 J& S( z* e7 F, y1 o* V L- m! [
phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题# n& w s, F3 r/ w
5 S3 c! G' c# u这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强
' P) Y0 m! q% P: J* U
8 p# g- w T3 l$ T. @, O这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论: v/ N4 P# v" `! L/ X/ z( P) O
- Z6 T& V4 u" {$ ~, i+ x0×03 路径? ? ?
9 g. P+ M. ~: K# e8 F$ X u$ ^5 U$ Y, L1 }1 \, o7 K
在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件
; L* E6 I, n+ Y- O% h5 t; }8 R: n* z* 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])); } # M" k: d9 r% s9 n( b* N. U
* I" t% @0 x6 i
这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的1 l* Q1 P' S; N8 v& y- J) J% G
7 f7 O* A4 D9 E. b0 \然后就是将我们传进来的参数进行变量化 W8 n& k% b: G7 i# o; a7 Y
9 h0 U0 v1 q+ ~6 O! @9 N2 Z$ J
这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量9 {- P+ {) c4 C6 R" P
- [. r. w. s; y- T( k: ^. N但是接下来这行呢?, b* J8 p* E T
. y9 m9 G* \9 w+ d# x( M
; e2 ~! L7 n4 a' n1 p. i$ C& ~$ Z7 h/ Y2 u) z) O
if(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); }
P7 S3 _. u9 d1 e: |0 X' F3 M9 O% D
! k% b0 x E& O) ^& ?* V5 ~
- `( I5 R. N2 Q- p; L/ h: v' h看看这里?
; K: s) X& W' c9 U4 }* ? X; s; D# m# e$ k) t8 Q) I9 w4 v7 t
这里的QUERY_STRING来自前面
9 w6 \( C8 Q1 I8 E
+ c5 ]1 {0 ?6 _ 6 L$ M* z" ?2 z9 |* J9 [
6 F% D( h# z: W7 T2 f
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']));% U9 y0 j$ R) X( G. w9 ~; b# E
这里有个过滤,但是不影响
0 w* u7 ^! ]2 _/ G) k; X8 N; E( h. K" u% K. |4 a& Q o
如果我们在这里进行覆盖这个db变量呢
: ~+ A0 P4 |" s( m6 k1 P7 f3 g# H% q \, ^' `9 ^6 A5 S
因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));0 n, _3 |( r" j, N: c! l
1 G( t$ ?) S2 g5 O) v
可以将我们传进去的/ - 进行替换% V8 p* Z( `' z; t
; g5 p% O) `; G( @+ T9 x所以我们如果提交如下字符
8 X) W ?5 [8 s
8 e2 |$ A1 r! chttp://localhost/phpcms/index.php?db-5/gid-xd.html/ W2 T; x* w X( l
/ Z1 X, q/ O* V! N4 H( }他由于这个db被覆盖就会出错,所以物理路径就爆出来了
) s+ G" n. P3 C# D1 [) c+ Q1 J; e! [% ~$ F' m) j+ S
0×04 SQL注入!!!) V9 Y0 }2 t2 [0 U# }% y( h
/ J6 s- P0 g2 O6 \: @" B! y3 p 在c.php中
5 @% l- u( y% |8 T: ?/ a/ n% m2 x, W( t6 r: J
" G6 R( D/ e+ ^: R( B$ l/ ^
2 _: f$ i9 Z. v5 q6 t; u<?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']; } ) u, w4 U, \- k' O! O4 ]: u6 v
( v2 ]! O/ b. \
8 t# j. _; Y) [- \9 T% H
/ u J0 k7 A# o: G! _" k s* L$ V
注意这里的HTTP_REFERER这个常量5 J) a9 O. _7 B" v2 D
* x7 [# u# |. F4 u4 ~" Q这里的常量是通过前面的common.inc.php定义好的
3 k v, E% L5 ^1 q8 L
, j: [; H0 k3 ^9 f. X8 ddefine(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);+ }0 \* Y% d1 K2 Q( l
; `* v- C( c7 C: w
没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我
" j1 V. |! P* t, v/ y# |/ V! l/ j1 D
+ z" }! | @- A. _/ J0 ?4 g然后' v- ~; N# s) c9 y
+ |' W$ E2 f0 O0 \. F
$db->insert($table, $info);" \, C4 S, Z' R6 `& | ?2 F
我们来看一下它这里的操作; Y7 ~1 G" F/ p+ w5 T6 A5 ]. S
( \3 }1 n5 c- g) o' sfunction insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); }
0 q! ?+ {# L) O
0 {1 e+ }' h! [! m, N- L4 \9 ]所以你懂的
% J. X% x, c3 K
2 V. E, G2 [- d/ W; `! w- ~
) h" E; l4 @) s" J: E' D. f% I. _1 e( K& v* j
附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=4045637737
6 S; H0 ]' F& c! `1 c! m% p- |: ^: g( h# m1 n- t. s3 |
) U* g$ b. ~9 Y9 Z3 @
/ w0 F% \+ y' ]7 R |