V0W's Blog

目录穿越导致任意文件读取

字数统计: 835阅读时长: 4 min
2018/08/13 Share

目录穿越导致任意文件读取

可能很多人都觉得这个小漏洞,没什么大不了的,但是有时候这种小漏洞,却会造成大危害,如果不加以重视,很可能会因此造成数据泄露。

介绍

路径穿越是网站被恶意人员利用,来得到其无权限访问的内容

通常是由于代码没有判断 拼接路径的真实路径是否合法,最终导致文件读取

Web程序应该有很好的权限控制,为了避免使用者读取到服务器上未经许可的文件,通常会通过“根目录”这种机制加以限制。一般来讲,用户在网站进行浏览,所能见到的网页都是位于网站根目录下的文件。根目录以外的文件是不允许被未授权访问的。

但是安全方面做得不严谨的web程序可能会出现目录穿越漏洞,恶意人员可以利用这个漏洞来读取根目录以外的文件夹。一旦成功,本不应该暴露的敏感信息就可能会被泄漏给恶意人员。

PHP常见读文件的函数

文件读取代码:
file_get_contest

<?php
$filename=$_GET['m'];
echo file_get_contest($filename);
?>

fopen,fread

<?php
$filename=$_GET['m'];
$fp=fopen($filename,"r") or die ("unable open!");
echo fread($fp,filesize($filename));
fclose($fp);
?>

readfile

<?php
$filename=$_GET['m'];
readfile($filename);
?>

漏洞复现

DirCross目录下的index.php
目录结构如下:

  • /www(网站根目录)
    • test
      • DirCross
        • index.php
        • hello.txt
      • flag.txt
  • secret.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>目录穿越漏洞重现</title>
<body>
<?php
$filename = @$_GET['file'];
$myfile = fopen($filename, "rb") or die("Unable to open file!");
echo fread($myfile,filesize($filename));
fclose($myfile);
?>

</body>
</html>

按理说,逻辑上只允许用户访问DirCross目录下的文件,但是,由于逻辑判断的缺失,导致用户可以跨越不同级目录,任意访问其他文件。

正常情况

1
http://localhost/test/DirCross/index.php?file=hello.txt

mark

但是由于缺少过滤和检测,可以任意读取文件

1
http://localhost/test/DirCross/index.php?file=../flag.txt

mark

1
http://localhost/test/DirCross/index.php?file=../../../secret.txt

mark

解决方案

方案一:

过滤特定字符,如..,./,.\

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>目录穿越漏洞重现</title>
<body>
<?php
$filename = @$_GET['file'];
if(strstr($filename,"..")){
die("发现目录穿越攻击!");
}
$myfile = fopen($filename, "rb") or die("Unable to open file!");
echo fread($myfile,filesize($filename));
fclose($myfile);
?>

</body>
</html>

缺点:黑名单过滤不全的话,很容易被绕过。

方案二:

采用白名单方式,只允许读取特定文件,判断,若不是特定文件,直接die

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

$filename = $_REQUEST['file'];
switch($filename){
case "config":
echo file_get_contents("config.php");
break;

default:
echo '请求错误';

}

?>

方案三:

按照. 分割开来,读文件名参数和文件格式参数,如果文件名参数中有..,die。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
function checkstr($str,$find){
$find_str=$find;
$tmparray=explode($find_str,$str);
if(count($tmparray)>1){
return true;
}else{
return false;}
}

$hostdir=$_REQUEST['path'];
if(!checkstr($hostdir,"..")&&!checkstr($jostdir,"../")){
echo $hostdir;
}else{
echo "请勿提交非法字符";
}
?>

参考链接

路径遍历与文件读取漏洞以及其修复方案

CATALOG
  1. 1. 目录穿越导致任意文件读取
  2. 2. 介绍
  3. 3. PHP常见读文件的函数
  4. 4. 漏洞复现
  5. 5. 解决方案
    1. 5.1. 方案一:
    2. 5.2. 方案二:
    3. 5.3. 方案三:
  6. 6. 参考链接