0×01 前沿
/ G. C W) g8 @( E: f% Z# m) \
Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。
) u. h6 d$ y t4 ?! u
# n6 Q1 U* v# {. o. n7 p* h0×02 写在前面的话
8 m, ^4 P! d5 Y, [
' B/ Y' a/ u2 X phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题6 J. ^% y: P* M
: Z9 G6 |9 Q. p3 O
这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强
Q% D4 ?( ]: I8 x" J5 r# E3 p) E; r- I4 r
这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论
; t% V/ N6 p/ ~9 |# L; K3 _0 p1 g& f: o0 x4 G
0×03 路径? ? ?0 c7 n4 O# B2 n8 r
$ e+ F4 m& \/ A9 @5 K! ^5 @
在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件
, `, |+ \. U2 w# m2 P Q) [
; t- e; G1 k0 I/ y$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])); } ; j9 `1 j3 C1 P y. M/ {# n
" T5 q6 O# n3 O5 k& L
这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的 z; ^% O. |/ W) L4 w
9 K+ j2 ~ n1 \) [( y
然后就是将我们传进来的参数进行变量化
7 |& ^( ^- E5 A# v1 b) r7 l
9 `. b1 ]+ u5 Q. [" N这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量0 a$ q2 a% P3 K
$ U$ F C* S" Z
但是接下来这行呢?; Z7 H% i/ D7 v( n# Q2 b% V" M; ]
( N4 g+ J. C# A 0 }4 `- Q; O9 n8 c* p z n, B
- K# B9 \8 b0 D* I- l& R
if(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); }
k: H/ y$ K0 Q; } }# m b
& H5 b! B. S0 P" F* S8 E- g6 b
' U. X1 m; I$ S1 v0 N2 _; Z+ v, F
看看这里?
9 H: `. w, e" T7 H" N# x f, A2 Q2 V i% \
这里的QUERY_STRING来自前面5 ~; r/ d9 a9 u; V* ~
; q4 b; [1 g5 ?9 C* B, L) z
9 R; S! e5 u* X1 v& q @2 X3 f& ~9 e# C7 @% d! p, p: T
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']));& W) p' m6 C! g* V
这里有个过滤,但是不影响
" P5 u" p& |( O+ O2 B! }
7 F! y6 V& n4 g如果我们在这里进行覆盖这个db变量呢8 I y2 A6 J/ D( O- l' ^+ h
( u3 |3 w' c9 ] A$ K因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));* K: A6 |( O6 \- i% [7 g
! Z4 m8 A! N, }9 \( c A4 U可以将我们传进去的/ - 进行替换
# @! ~7 _/ F! B W% g, I, n) C, z( V2 p2 T
所以我们如果提交如下字符& f5 {$ S# y" C% K% j! _
8 {& O' Q+ T, L/ X: ^http://localhost/phpcms/index.php?db-5/gid-xd.html
* S( | @5 w4 l
+ s) J1 M- n1 I- o6 A7 k# m他由于这个db被覆盖就会出错,所以物理路径就爆出来了
7 K: [( a, W6 i" n% c& m/ B# D' `4 J7 M Z8 r
0×04 SQL注入!!!
' k) s6 l; p: U1 U9 x. I/ F: g* d. p1 W
在c.php中
- _/ j( y4 {+ g9 q y4 g
/ S4 L- @& n4 y: p 1 P6 [: M0 f+ ?6 Y& J
9 |- L: u2 x; i6 O* y<?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']; }
$ d5 r, l3 i4 s/ }4 s
& e) }( \$ r* J# u" W0 W s0 r* ] 7 S8 X" z0 f0 [& R8 E3 G& M
( s" D- N" v6 h. n# _& D) Q
注意这里的HTTP_REFERER这个常量& l3 e, e! K2 z1 i- B# ^& Y1 T
r6 m) |2 e+ o
这里的常量是通过前面的common.inc.php定义好的
. M7 X3 c2 T6 X* X; y# h- O5 O
/ N+ H7 k5 L$ a6 Y3 \define(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);
! T/ {. q" Z2 v7 O3 ~' ^5 F8 d# |7 {( h0 r7 n" e; ~
没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我
$ m3 W6 z) F% h8 \, o/ [
5 E: q p. U& v) W b/ c1 b5 L8 }然后+ m/ i+ \! M! A* N3 I) [( I
" ~, C r I4 q1 p; N8 m2 i$db->insert($table, $info);
% S" s# n5 Y7 O1 I9 h3 m8 R/ _我们来看一下它这里的操作# M3 j* ?1 V% r
7 ?" F. }/ D0 k7 g) f) }& k: ifunction insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); }
+ {4 h! T( Q$ z6 _& [) B0 z# ~' ^" ^# q
所以你懂的
: u3 O4 \9 `3 X% {% G8 K! K: V- X# ]1 U7 u) T
( R( r( t! u) _" z+ Z+ L" V
( U2 X `) H! f- s- W. N! _
附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=4045637737$ Z* h8 A& D: M5 H
- w* Z9 m8 ]- o( s
& b% a7 i: V1 {9 ?7 m1 X* B; z- L) [! M) P: O5 B- Y( }
|