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

Posted

技术标签:

【中文标题】dirname 是不是足以防止目录遍历攻击?【英文标题】:Is dirname adequate to prevent directory traversal attacks?dirname 是否足以防止目录遍历攻击? 【发布时间】:2013-10-27 03:38:43 【问题描述】:

考虑以下经典问题案例:

<?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运行时库的fopen函数必须透明地支持这种编码。 p>

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

总之,在我看来,这个检查 100% 安全的。有什么我错过的吗?

【问题讨论】:

我已经使用了answer 中的代码,您也可以查看该问题的MainMa 答案 @tttony:谢谢,但正如我上面所说,我知道如何防止攻击。问题是,以这种方式可以自信地阻止它吗? 根据我的测试,你的方法有效,看起来简单但有效 【参考方案1】:

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

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

【讨论】:

当然,这些示例包含用于说明的最少代码。你尝试了什么样的排列方式? 我创建了一个文件 1 级并以我能想到的所有可能的方式输入该文件以引用该文件(即 ?f=../test.txt ?f​​=..\test.txt ? f=..%2Ftest.txt ?f​​=/test.txt ?f​​=%2Ftest.txt ?f​​=asdf) 这个列表还在继续。只有脚本真正本地的文件路径不会引发错误。再说一次,我讨厌使用“100% 安全”,但我找不到明显的东西来解决这个问题。

以上是关于dirname 是不是足以防止目录遍历攻击?的主要内容,如果未能解决你的问题,请参考以下文章

检查双点是不是足以防止路径越狱?

python文件夹遍历,文件操作,获取文件修改创建时间

参数真的足以防止 Sql 注入吗?

路径遍历漏洞查找利用预防

目录遍历攻击详解

PHP防止木马攻击的措施