dirname是否足以防止目录遍历攻击?

时间:2013-10-18 10:18:10

标签: php security encoding url-parameters directory-traversal

考虑以下经典问题案例:

<?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)编码为包含相应字符的ASCII值的内容,同时此编码必须由底层C运行时库{{I}透明地支持{1}}功能。

无ASCII值限制排除了所有单字节编码,UTF-8和两种风格的UTF-16;此外,由于C运行时的规范与平台无关,因此攻击只适用于使用“易受攻击”的编码来表示名称的某些文件系统。据我所知,这样的文件系统不存在;任何人创造它都没有意义;最后PHP即使存在,也不会托管在这样一个假设的异域系统上。

总之,在我看来,此检查 100%安全。有没有我错过的东西?

1 个答案:

答案 0 :(得分:1)

我不确定我是否会声称某些东西是100%安全的。也就是说,我不能想到一个明显的例子,这是不安全的,我尝试了大量的排列反对它。也就是说,你要添加一个检查,$ _GET ['f']在那里不是空的。使用上面的代码访问一个没有f值的页面给了我“防止攻击”的消息,这可能不是预期的效果。

<?php
if (!empty($_GET['f']) && dirname($_GET['f']) != '.') die ('Attack prevented');