考虑以下经典问题案例:
<?php
$filename = "/tmp/".$_GET['f'];
readfile($filename);
此代码容易受到目录遍历攻击,例如,如果 的值为$_GET['f']
该../etc/shadow
文件的内容,则该文件的内容将被泄露给攻击者。
有一些众所周知的方法可以防止这种类型的攻击;我不是在问如何做到这一点。问题是:下面使用dirname
防弹的方式来防止攻击吗?
<?php
if (dirname($_GET['f']) != '.') die ('Attack prevented');
听起来应该是因为dirname
:
.
当且仅当输入路径中没有斜杠时才返回(在线文档的保证不那么严格,但来源是明确的)- 是二进制安全的(因此不能被嵌入的空值欺骗)
据我所知,唯一可能的攻击途径$_GET['f']
是以编码方式传递数据,这样字符/
或\
(让我们不要忘记 Windows)编码为不包含相应字符的 ASCII 值的东西,并且同时,底层 C 运行时库的fopen
函数必须透明地支持这种编码。
无 ASCII 值限制排除了所有单字节编码、UTF-8 以及 UTF-16 的两种风格;此外,由于 C 运行时的规范与平台无关,因此攻击只能适用于某些使用“易受攻击”编码来表示名称的文件系统。据我所知,这样的文件系统并不存在。任何人都很难创造它;最后,即使 PHP 存在,也不会托管在这样一个假设的奇异系统上。
总之,在我看来,这个检查是100% 安全的。有什么我错过的吗?