考虑以下经典问题案例:
<?php
$filename = "/tmp/".$_GET['f'];
readfile($filename);
此代码容易受到 directory traversal attack 的攻击,例如,如果
$_GET['f']
的值为 ../etc/shadow
,则该文件的内容将被披露给攻击者。有一些众所周知的方法可以防止这种类型的攻击;我不是在问如何做到这一点。问题是: 是下面使用
dirname
的一种防弹方式来防止攻击吗? <?php
if (dirname($_GET['f']) != '.') die ('Attack prevented');
听起来应该是因为
dirname
:.
(在线文档的保证不那么严格,但 the source 是明确的) 因此,据我所知,唯一可能的攻击途径是以一种编码方式将数据传递给
$_GET['f']
,这样字符 /
或 \
(别忘了 Windows)将编码为不包含相应的字符,同时这种编码必须由底层 C 运行时库的 fopen
函数透明支持。无 ASCII 值限制排除了所有单字节编码、UTF-8 和 UTF-16 的两种风格;此外,由于 C 运行时的规范与平台无关,因此攻击只能适用于某些使用“易受攻击”编码来表示名称的文件系统。据我所知,这样的文件系统不存在;任何人都很难创造它;最后,即使 PHP 存在,它也不会托管在这样一个假设的奇异系统上。
总之,在我看来,这项检查是 100% 安全的。有什么我错过了吗?
最佳答案
我不确定我是否会声称某些东西是 100% 安全的。也就是说,我想不出一个明显的例子,这会是不安全的,我尝试了大量的排列来反对它。也就是说,您需要添加一个检查,以确保 $_GET['f'] 不为空。使用上述代码访问没有 f 值的页面给了我“攻击被阻止”的消息,这可能不是预期的效果。
<?php
if (!empty($_GET['f']) && dirname($_GET['f']) != '.') die ('Attack prevented');
关于php - dirname 是否足以防止目录遍历攻击?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19447199/