考虑以下经典问题案例:
<?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%安全。有没有我错过的东西?
答案 0 :(得分:1)
我不确定我是否会声称某些东西是100%安全的。也就是说,我不能想到一个明显的例子,这是不安全的,我尝试了大量的排列反对它。也就是说,你要添加一个检查,$ _GET ['f']在那里不是空的。使用上面的代码访问一个没有f值的页面给了我“防止攻击”的消息,这可能不是预期的效果。
<?php
if (!empty($_GET['f']) && dirname($_GET['f']) != '.') die ('Attack prevented');