0×01 前沿
1 j6 Y# m' `6 D2 e8 S2 W" N5 c$ L* u; _! u$ e u4 U4 A5 G: {
Phpcms2008 是一款基于 PHP+Mysql 架构的网站内容管理系统,也是一个开源的 PHP 开发平台。Phpcms 采用模块化方式开发,功能易用便于扩展,可面向大中型站点提供重量级网站建设解决方案。3年来,凭借 Phpcms 团队长期积累的丰富的Web开发及数据库经验和勇于创新追求完美的设计理念,使得 Phpcms 得到了近10万网站的认可,并且越来越多地被应用到大中型商业网站。
( |7 T" N# c6 O, I1 f' Y' j5 h. n* t# H# b _
0×02 写在前面的话" X6 X8 r; }& f9 K. H6 c
$ g1 ~9 \3 P9 _0 ?, z: e- Q
phpcms 2008 这是我看第二次代码了,之前已经发现了一些问题,只是没放出来,这次稍微仔细看了看,又发现了一些问题9 \) X8 `0 g! D5 g3 R) `
$ H6 K! A- U; |- w, b这次就放2个吧,其中啥啥的getshell暂时就不会放了,比起v9来说,2008的安全性能确实差很多,模块化以及代码严谨程度也没有v9强1 E7 _. E$ c. L% K- \; V
, h# I0 |- d* r这次还没把代码看完,只看完几个页面,就先放2个有问题的地方,如果有更好的方式,到时候一起讨论
X& `6 G% r% T) c0 N5 K" Z
$ b* A k- ~: b0 q3 U6 o0 f5 i4 s0×03 路径? ? ?
0 i+ ]: h! o( _) n* N
8 t1 p2 f/ [$ W9 G: s 在include/common.inc.php中 ,这是phpcms的全局要加载的配置文件
5 Z6 n; z- c4 ~+ X) o, {
! j1 g" Z; z5 L$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])); } 6 }1 H* l! K+ K/ \+ H
. S" I' F% ~7 M4 v8 }8 }1 C
这里的话首先实例化了这个数据库,产生了一个$db资源句柄,他是用来操作数据库的
7 j& N8 K* H1 B, r! _
/ b6 Z8 G) @2 s* `然后就是将我们传进来的参数进行变量化
* w+ o" X, m6 g4 V, o+ \
H' M7 }1 ]$ M/ b这里有一些小过滤,自己可以看,所以这里传进来的参数就作为了变量
- e4 q5 w" W7 f3 K" \3 G8 I* H. c) Y* Q- C" o, u
但是接下来这行呢?
) B+ [; L. {+ ` w/ |2 H5 L8 [$ R* B' N O' y. s4 K6 m
- s- _7 X5 i& n: f7 v; M' I
6 W1 P( \' Y- U" q$ c8 Gif(QUERY_STRING && strpos(QUERY_STRING, '=') === false && preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", QUERY_STRING, $urlvar)) { parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1])); } + w; d: t4 V8 |$ t8 \ V! K3 F
+ s/ w9 V8 n: }9 X9 Q + i3 P6 G% o+ R
9 h$ ]' e+ }4 j' P看看这里?
2 g: \* z! A' {' Y' d# J2 t! e
6 R) W$ L3 N2 M: b1 d这里的QUERY_STRING来自前面' p; ~) r2 F6 {
1 j9 A7 ?* a% c/ J/ c
3 v, s! G4 T/ F: Q# a7 L: r" R& e4 s0 v
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']));$ h4 A# C7 ~' Q z& {+ @7 f# ?
这里有个过滤,但是不影响* q5 o- R4 c$ Q0 [
5 c7 _8 t4 y2 L, p6 M( k
如果我们在这里进行覆盖这个db变量呢5 W5 y4 W9 k' N* ?0 j7 x
% m% t$ B9 n: `/ R
因为这里 parse_str(str_replace(array(‘/’, ’-', ’ ’), array(‘&’, ’=', ”), $urlvar[1]));8 m! k4 P. }$ `( N
3 b, e0 F) U3 |* q0 V3 m' l可以将我们传进去的/ - 进行替换+ L" C# P$ G1 Q; X7 V. V: n: |- n
+ D1 p. C/ y* U* r* }: r
所以我们如果提交如下字符
2 a! p6 Q, h! \" n: x
4 B, Y* I; u3 Y9 r* zhttp://localhost/phpcms/index.php?db-5/gid-xd.html
3 ^) {0 s- V+ J# C4 V1 X' e
0 V) y) A: J y$ e( `他由于这个db被覆盖就会出错,所以物理路径就爆出来了) D9 D2 w( I3 ~& Z/ c) c, @
3 a0 d) l* ^/ i! C
0×04 SQL注入!!! H! v" v7 [3 f M$ y! X
$ |( a* x" e S; ^* o- z7 {$ p 在c.php中& o3 S# H, e$ X" r. A3 N' C, e- o
2 d- c g A/ g3 q' R5 K. P: z
" }4 l/ b* l) H4 N
0 N/ |/ \, c6 b0 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']; }
/ y$ w3 e6 I9 }' N/ q/ w/ D' V' O* M' ~6 I# ]
$ A- _: n8 c; Z2 `+ V7 M) o
4 b& ^2 A5 \) o o8 A0 m6 `注意这里的HTTP_REFERER这个常量+ q; F2 `" Y4 z6 ~& a1 J& r% `
" V3 i+ k* Q6 l& B
这里的常量是通过前面的common.inc.php定义好的3 v" ? [ w/ G ^, R; B; k- M
+ v6 c% K. F- @) M2 r1 @/ y/ `$ G# cdefine(‘HTTP_REFERER’, isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ”);
0 v0 w p. w7 C7 h. {! R
9 v7 R1 j) i1 h: `. T& F) J4 A" V没有经过任何过滤操作,所以你懂的,我估计很多同学已经发现了,只是没去公布了,所以俺就替你们xxoo了,哈哈…别骂我
! T. D" H3 B u6 H) j7 B6 t$ e- H( X$ h7 L
然后
' C3 N9 Y& z( H! t4 |5 Y; g
" F( v' L! I3 K. B$db->insert($table, $info);' `( d: F- z5 H+ z& m5 W
我们来看一下它这里的操作4 ~: A( I% m1 P: y, s; B( I. H
& Y/ [; y9 H- k" `function insert($tablename, $array) { $this->check_fields($tablename, $array); return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')"); } : g5 Q* ~4 _: y! E% F( @3 {
6 [8 g5 \ m' Q: j$ w! V# b所以你懂的+ h+ V) r# V& F6 Z+ t4 F' z
" A* p' S$ ]7 P; ~
7 G `& n! K+ k5 k
" X& t3 p9 E' M$ Y8 x/ @附EXP:http://pan.baidu.com/share/link?shareid=468231&uk=4045637737; q c0 Y1 i: I' C) T* B
`, [6 J7 t1 p$ ~, j6 [# l
5 D- t8 Y+ w+ D+ v2 W& N2 O+ U0 K: s$ K
|