几年前,我在PHP中发布了一个关于某种方式的问题的答案,让用户在URI中传递要下载的文件的相对路径,同时防止目录遍历.
我得到了一些评论,说明代码是不安全的,还有一些downvotes(最近的是今天).这是代码:
$path = $_GET['path'];
if (strpos($path, '../') !== false ||
strpos($path, "..\\") !== false ||
strpos($path, '/..') !== false ||
strpos($path, '\..') !== false)
{
// Strange things happening.
}
else
{
// The request is probably safe.
if (file_exists(dirname(__FILE__) . DIRECTORY_SEPARATOR . $path))
{
// Send the file.
}
else
{
// Handle the case where the file doesn't exist.
}
}
Run Code Online (Sandbox Code Playgroud)
我一遍又一遍地检查了代码,对其进行了测试,但仍无法理解它引入的安全问题.
我在评论中得到的唯一提示是../可以替换为%2e%2e%2f.这不是问题,因为PHP会自动将其转换为../.
这段代码有什么问题?什么可能是允许目录遍历或以某种方式破坏某些内容的输入值?
还有很多其他可能性可以通过,例如:
.htaccess
some-secret-file-with-a-password-in-it.php
Run Code Online (Sandbox Code Playgroud)
换句话说,目录或子目录中的任何内容都是可访问的,包括.htaccess文件和源代码.如果该目录或其子目录中的任何内容不应该可下载,那么这就是一个安全漏洞.
我刚刚通过Burp intruder运行了你的代码,在这种情况下找不到任何解决方法。
它可能因针对其他/旧技术堆栈的利用而被否决,这些技术堆栈采用类似的方法将某些字符组合列入黑名单。
%252e正如您所提到的,当前版本的 PHP 自动对输入进行 URL 解码,但是双 URL 编码 (dot = )、16 位 Unicode 编码 (dot = %u002e)、超长 UTF-8 Unicode 编码 (dot = %c0%2e)等技术存在缺陷或者插入空字节 ( %00) 可能会欺骗过滤器,并允许服务器端代码在过滤器给出赞许后将路径解释为未编码的版本。
这就是为什么它敲响了警钟。尽管您的方法在这里似乎可行,但通常情况可能并非如此。技术总是在变化,最好总是谨慎行事,并尽可能使用不受字符集解释影响的技术,例如使用可能总是好的已知好字符的白名单,或使用文件系统功能(链接答案中提到了realpath)以验证实际路径是否是您期望的路径。
| 归档时间: |
|
| 查看次数: |
207 次 |
| 最近记录: |