0×01 前沿
! U9 L0 i. B' h4 J. }, L
9 n* [1 O6 J# F/ E# W+ ~ Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。
5 c' V7 A2 m& L# P# k, i/ F
@; }4 w( O- \' E1 N L! l* n6 ~0×02 写在前面的话
2 Y5 o* |; Y( c4 C8 G5 w
/ G+ N3 B! g1 N" g& a phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题
) |/ ~8 k2 H4 R# j: S3 {
- p3 x1 l$ t* t) Y+ g- Q g- ?这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强9 r5 d. }0 [$ r& |
* N1 N' @; j8 ]! { [这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论' f. k* _2 W! D" g
; a; K7 m- R! h5 Q+ {
0×03 路径? ? ?) A7 P: J/ k; X) C
/ s7 K/ l0 Y' t: |. W- h( y 在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件
$ H4 l0 r( v1 l z& q% h9 T: t$ Y- g3 J
$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])); }
+ M0 ~$ c+ ^) ]' S, D- Y* ]" S6 `6 C3 M9 O9 Y$ R$ a1 i
这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的; g" t! C8 R( K- E5 h0 e: a" f) W
: s+ f# A0 i0 B' g- A% P然后就是将我们传进来的参数进行变量化
j# i5 M1 q8 j" }/ z U9 E+ z2 z J
这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量. ~8 s, s X; O' \: L6 N
/ e' s% O2 F7 d* h
但是接下来这行呢?! A; Y7 n2 A2 {6 o0 D- W
) Y& S" O; _$ q- Y9 ^" A # C/ ~3 R" L; F O+ G# u1 n: X
) S1 p/ |3 B% C. e7 B0 N' J- s1 F
if(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); }
! f5 Q) K1 o$ f
2 r% R r0 d7 {9 C2 x : W8 ]8 Z- b6 t5 t2 v. g1 n
4 J: [% N5 `: d) f9 L* ^/ K: \看看这里?
# n8 [6 {* o3 T$ {) A+ ?+ H; S! s9 `3 I9 R- K0 ~
这里的QUERY_STRING来自前面
. J3 M) w# K# B O, j2 Q; {, `/ }
, W2 h2 ]% g& w! p& U* [" S5 c
& t4 C+ [) q% q: w9 ]) U0 Sdefine('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']));
1 ^) b: B, ?, d, c) c9 R8 `这里有个过滤,但是不影响
6 G8 \+ g' y( L% z, U H, V& Z; o% B6 x' I) ^3 y
如果我们在这里进行覆盖这个db变量呢
- C# |6 |$ P, `, J3 r0 p- N
- h* T$ l4 w5 C, j0 {因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));
; X* G( \0 M# S/ V9 X0 D P
$ |: p9 q* W* t0 v可以将我们传进去的/ - 进行替换
8 g1 ?1 b' |4 j) U- C n5 [" R# m4 [$ L! R$ r, K) x
所以我们如果提交如下字符* |0 Z$ V( P1 a+ k( W4 N; Y
/ ~, k' L: S! D- Ehttp://localhost/phpcms/index.php?db-5/gid-xd.html- E2 T- N5 { e( M4 x4 ^
3 g% t) C5 d; J# X6 F- T
他由于这个db被覆盖就会出错,所以物理路径就爆出来了
- Y& {& G! p7 O. t$ X( q, a* |( k4 \4 R) g- y! `0 d6 t
0×04 SQL注入!!!2 ]9 \, \$ `* ]6 d9 r( Z
% Z8 `9 D7 y5 S
在c.php中+ a( y& K7 V. w0 ` e1 g+ l
& c. {6 l4 \3 h9 Z5 x5 ]$ w- \3 X , |2 c' `. K3 k% g4 R$ b# ?( {
2 d w0 o# F2 w& \3 k t
<?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']; }
, v! s1 m( b0 ?& U/ K3 n/ l% \6 J" Z1 k) \+ t7 ]) l: n4 [/ b, R
# I7 u. }- Y; ?, x; ^' J2 S
* p! B# O7 [' X% g. @; T: m; l
注意这里的HTTP_REFERER这个常量0 K5 z3 f' W ]; ]2 U
" k$ t" W; o9 a! T: Z8 Z$ X( o这里的常量是通过前面的common.inc.php定义好的
! i; g; \' Q1 r5 ^2 c
" |# N4 T) |9 ?define(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);0 H! t6 v' n3 Q j/ Y) F
c' e9 X$ r5 M# i5 ^9 W6 p4 {+ y7 M没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我4 L- G, w/ j/ c w$ q- V8 Y
, S9 S) q1 ^ Y# O, s! L然后, W3 H: E/ \3 e( e/ x, E
; ~) P' P) }8 r; L8 T
$db->insert($table, $info);: H6 p6 q* l1 f- T% Z/ Z7 @% \" P/ V
我们来看一下它这里的操作
8 B( R% `2 E1 [7 Y1 `4 C6 T& [, \% p5 G# ?3 J
function insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); } / C/ x; @) b7 E5 x
* k6 Q% m6 ?5 V! ?所以你懂的
3 f5 b4 q3 p& r4 {
5 M9 v- A. ?$ h0 L7 V! n+ \ 4 I0 C7 n3 j% }; \+ m1 y* b
' _+ @) E9 F+ o0 @附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=4045637737* K" ~ u, z" a, B- ?/ P( T8 e
6 T! ~7 G4 J0 R+ f% k, ?
* ?6 B& S8 C, P' \8 f
$ F/ P6 |( [0 j; b/ ~
|