在处理文件上传时,根据PHP 官方文档,文件名应该针对目录遍历和可能的其他类型的攻击进行清理:
// basename() may prevent filesystem traversal attacks;
// further validation/sanitation of the filename may be appropriate
$name = basename($_FILES["pictures"]["name"][$key]);
尽管如此,我发现默认情况下,文件名在到达 PHP 脚本时已经过清理。
我有证据表明 Apache 收到了恶意文件名:filename="../file.png",而 PHP 脚本改为在 $_FILES 变量中读取经过清理的名称。
Apache 输入的低级转储:
mod_dumpio: dumpio_in (data-HEAP):
--------------------------eb8b65b665870e02
Content-Disposition: form-data;
name="attachment";
filename="../file.png" ← [Malicious file name]
Content-Type: image/png
PHP 脚本
echo $_FILES['attachment']['name']; ← [File name already sanitised: 'file.png']
我在 Apache 模块和 php-fpm 中都发现了这种行为,运行 PHP 从 5.5 到 7.2,我必须推断 PHP 解释器在将变量传递给脚本之前执行了这种清理。
所以,感谢 PHP 在我不知情和同意的情况下为我做卫生。但是(这是我的问题),因为据我所知,这个功能是无证的,我想知道清理标准/正则表达式/算法,以确保它满足我的需求。