0×01 前沿/ V' {: c" b: [
" _# \' V6 {3 @6 `' t5 V' {4 x% Q Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。) w6 H1 G3 B) U
5 Q5 Y y( x/ J" Y. d4 r
0×02 写在前面的话5 y% N D, d! r1 K$ x4 ?
, T8 _5 [6 Q# T( U
phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题
& K5 v. p& k: [& V$ y2 N+ ?! P2 U
; Q* b7 e3 H1 w, b% J4 r9 p! j$ s1 B" `这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强
( \& {, g9 z- J4 u- {
K1 V3 P& {1 A) A. i这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论2 A7 Q# s4 A/ W* b
: _1 }- f9 L5 E& R ?2 ~$ j6 j
0×03 路径? ? ?, D$ ^6 \0 t) [& G( F
, ^6 {! T9 L4 P7 \
在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件
# C- ^8 F) c& c' ?8 L4 T
& }2 `% R9 x d5 |% A$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" D, S' n/ l0 q+ }) \
1 n0 X0 G4 k3 {" t3 J这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的
( l% E. X8 O( l E$ q, Y3 c& L% r, u" z* D& r& V i/ x
然后就是将我们传进来的参数进行变量化
& S6 X. c" `5 M& X0 o7 t8 g
4 D! g1 Q! h9 U \3 B' L+ R这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量. J& T9 ?; F5 l( F- n$ d% F
" i3 ? N0 A7 U% c( G" M. S6 c5 w
但是接下来这行呢?2 Z( G5 v$ J4 i7 g! _ j
1 [% t' R I. n6 ^" G4 X% { ; C- c' A& K( v' K
9 \/ }! k6 s+ `" M# fif(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); } " b* D H# o: x: [* Z+ t7 J
: v4 L# }# ]* Q9 {0 W
8 i, y0 |# L4 ?3 k, q9 z( X
& W# k- Z1 @. j# I$ F看看这里?- Z) W% N# X% i" s6 L& W* `( `
* c8 P* w8 D) P* K' s% U
这里的QUERY_STRING来自前面0 O) r' k9 P2 O w
# O2 _1 {2 I' F* |0 C
9 u! \9 F1 s: [) `, Q2 B: `/ `: W6 U n
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']));+ ?. z9 y5 J0 ], q. U; N
这里有个过滤,但是不影响
3 b9 \: |, @+ E, T6 J7 f- z! m
- E2 C; O A) ?$ q+ G# Z V如果我们在这里进行覆盖这个db变量呢2 i9 `8 U3 J, W
: |1 x0 }# G4 o( r" w
因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));- r+ O2 [3 ~2 S4 P/ `) F6 e8 g
7 V5 B& @# G+ p可以将我们传进去的/ - 进行替换
! X% ?7 P6 K. g* O- l5 d) A
3 ~4 v# l8 L# S3 {3 ?; N6 d所以我们如果提交如下字符) Q* F# M) b3 j' }* k* F
2 @" I& k! A1 [' F% ~+ `
http://localhost/phpcms/index.php?db-5/gid-xd.html
# O: I8 `1 M# K# o$ ?" x
$ I: S! f% B5 C, P1 A他由于这个db被覆盖就会出错,所以物理路径就爆出来了
8 J: i! ]) J3 y8 T3 w# N. a6 ^9 s0 S5 s
0×04 SQL注入!!!$ R! [) ^* Y3 T3 T
& t7 U5 a7 s& y( r! r6 m/ \8 U 在c.php中! @4 d6 X* \2 C8 O% [! y2 v2 e
* j9 y# x- u4 y; W9 m ) @4 V- V5 H8 p. j! ^0 F1 a% ^3 l% k
+ e. ?& S# }& @
<?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']; }
6 A" f, N: a# K$ C
4 j7 H' K1 s. } . M/ }7 B4 x x1 q
$ U: [! ]4 D2 @8 |( l
注意这里的HTTP_REFERER这个常量
1 F, j: ]4 g) w0 P5 T; p7 J# W- R5 @& u0 ^" \$ i
这里的常量是通过前面的common.inc.php定义好的9 Z& X' e8 {# L! J7 V* n0 ]- h
8 d1 Y' b5 l6 F
define(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);, ^" K) Y4 M1 o+ e! ~0 A* N7 g
! u+ ?' m/ F* ~/ a
没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我
) s3 h$ l' S/ ]- b* n, R$ ?( X( L9 J8 W
然后9 Y, Z, n* I3 [7 H" w9 t% [# d+ ^4 h2 |
5 J t0 g; F( W: A* W$db->insert($table, $info);
2 d% M# o$ d4 F5 m$ n* h我们来看一下它这里的操作
) c: a) I: W0 c' T+ V# J: z) P: Z( V- P
function insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); }
2 I# q9 Y$ M: h; O$ ^ b& A% X1 t. C+ F0 N$ i- d
所以你懂的% T6 e+ c- P5 W k5 d8 C: Q4 Z
- P" Z- E: o) U % A7 u! P. V8 O9 [( L& w
3 i* C$ k! |8 d3 e# K
附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=40456377374 I1 ?8 |! a* n9 I; ]
; J) q. U/ ~5 B- Z
- L% B! Z5 A( V* `7 Q T6 Y, j( U0 `2 r! r& h" Y+ |
|