0×01 前沿$ Y: Q6 ~9 ?- A& u
* ]8 D- q! M* H V% D! G
Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。( O6 p1 Z- `( P5 r0 N6 S
0 `, x O/ p) _, C+ f- ]
0×02 写在前面的话9 K2 j" G) u9 H- ?) ~
' B9 q& w, p5 J7 Q phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题
. y1 M& f9 t/ w0 I# x- e' f
7 v" O0 C- s. z. _" ^0 Q这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强6 j1 K1 a2 e' `& ] s
8 { A8 k' _8 m+ l2 f6 n7 O
这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论
$ b, T/ [3 X7 }1 ?6 W) Z" W
1 l3 o7 m9 ^0 @) k+ {. D2 b, n0×03 路径? ? ?7 H1 u. T8 v4 z K- R7 U
( k: o0 O- j, Z6 g6 x) A* Z* O
在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件
, l F* X3 C4 c, ^/ y+ b6 u% w3 |6 i8 w! H( U0 E3 w$ Y9 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])); } + {2 s) R- }9 I& {' b" w
E9 v, s9 \9 X0 U( d7 s1 J
这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的
@1 i$ @7 ^8 | r/ L* z# ?+ S$ E7 m, W# ]( J- U
然后就是将我们传进来的参数进行变量化: a9 A1 k9 a+ ~( A {
* r. Z4 D% u5 N7 ?7 U这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量2 Z6 e. O8 P' P" E/ _* l1 q9 X D4 Q
+ a* K1 l+ e: g+ i
但是接下来这行呢?
; G" j# F* b( K' V4 z3 Y2 z
$ `% Z) n& d" f A: W/ G) {6 ~, h ! Z' M# H, v7 Y7 a( i' m6 q$ k' ^
( S% _: B( `9 j8 v5 f! A: n
if(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); }
5 v9 p% G/ V& u1 P- p% t; q( ~9 d0 O6 U9 P- m* I+ Z) a' Y! n" z* Y* O
" d& u" o* u9 F' _, j3 C
+ T3 H0 I# ~9 O; e% L
看看这里?* \8 k @) `) z, b9 B7 n
8 G# R1 a5 u2 c# U7 O( E; R这里的QUERY_STRING来自前面
( G. M; S( W% B; m' T% }
~3 x2 K% z5 ~6 s ) ]# [ O# _4 i" M# ]
: c! f+ k, I$ D2 Qdefine('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']));# u0 Y0 _1 z8 w* V7 k, Z8 T& [
这里有个过滤,但是不影响
+ ]+ b2 d; U$ m9 c; B
! @- v$ K2 ^" O6 j8 |' b2 Y3 j如果我们在这里进行覆盖这个db变量呢" w3 T6 x' Y+ ^7 ?8 R9 t
0 a2 k$ q$ m! } ~' T6 G因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));
3 ?' j, o; @* @ S# b3 a0 e9 ~$ z
! ^# j) Q/ K3 `. J# S2 u可以将我们传进去的/ - 进行替换
1 _5 m) `: b- t- `% U& d4 z
) ?! Y" p6 p" m. x3 V5 Z1 x3 J7 Y所以我们如果提交如下字符
z! T& Y5 a; u( Q. S, j8 K- l+ L' y' S* D/ E. q ~% M
http://localhost/phpcms/index.php?db-5/gid-xd.html0 \8 h4 L6 z" \5 m+ P M" R S& p
: D$ l; j) e1 p
他由于这个db被覆盖就会出错,所以物理路径就爆出来了$ M: u2 G& w6 H8 o
' [2 j" D( @" R- f$ |- c l+ W+ c! p
0×04 SQL注入!!!) K# ]% d' ]% f3 h0 R. Y
c+ i( M. a. ? 在c.php中5 i( v- X- g( ]' t$ m8 i
1 _* _6 ?# j* L9 _% u 8 y' T, p i9 x/ d3 ]% n% i$ ]
, |( U& Q; h/ v2 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']; }
t5 s! l; _$ _/ v' i; X
) T5 b! i0 ^% }* u0 x. w! M1 V6 D & N0 |' h2 f& {4 Y
6 S7 _+ ]: {5 C注意这里的HTTP_REFERER这个常量
5 {. y) X p' w9 ]4 s, \
$ o* W" u2 j! }( v5 y" Z2 G这里的常量是通过前面的common.inc.php定义好的
# w) Z" w; j: B4 \7 V/ c" ]3 u- Y" T0 b' C/ @( b8 M
define(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);" q; N m. Z! m
7 v' @, W: f, p3 {* s) B没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我
/ }2 ~- W) P; O: E' T# `1 h; M8 ~+ L. V3 `! V* P4 y
然后; o2 Y: b2 h3 Z" _% h. y+ j
: ~$ \. @- B1 D$ y7 C
$db->insert($table, $info);$ {6 C% F8 v0 k( C$ {: N( Z
我们来看一下它这里的操作
- Q5 v9 X( ]# @/ j" S* X' X& I/ n! a; N9 @2 }3 Q+ Q
function insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); }
$ _" a9 n+ a& n" l3 o4 f9 N* ]7 @2 \8 j+ T& H
所以你懂的
1 b% D4 w$ P# x
4 T+ f7 d: s: b. Q j( ~$ x* r/ k) i4 {' N - v6 r& A: R/ s. V: C
1 R+ S, l3 _% P) r! M
附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=4045637737; s1 q l. b, v( S+ \
2 |# _& w; [. T' o7 _/ {6 A 7 e$ ^2 o8 ?* j3 p: v8 d! t
: v% x% ]" u" H3 j" I1 K |