在处理它之前我需要过滤 $_FILES['file'] 吗?
简短的回答:不。这是一堆字符串值,仅此而已。
长答案:
我曾经通过检查文件类型和扩展名来保护网络应用程序,以了解这些文件是否在白名单中。
如果应用和执行正确,这是一个很好的方法。
$_FILES 数组只是一个载体。它本身不能被滥用,但你必须相信它携带的东西——即相信正在传递给/由服务器传递的文件。
当我写这个答案时;以下; 似乎 OP 对他们实际保护的内容以及原因感到困惑:
OP 声明为“最佳实践”(绝对不是):
如果你想使用 $_FILES['file']['tmp_name'] 来存储到你的数据库或显示在你的 UI 中,你应该使用 addlashes 或 PDO 准备语句来保护免受 SQL 注入攻击。
这是对$_FILES
数组如何填充的误解。该$_FILES['file']['tmp_name']
值由服务器设置,而不是由用户或客户端设置。
用户给定的值为:
$_FILES['file']['name']
$_FILES['file']['type']
$_FILES['file']['size']
这些是需要审查的字符串值。只要您不信任这些字符串值,您就无需担心。
在数据库中存储文件通常不是一个好主意,并且有其自身的缺陷,dhnwebpro 对这个问题有自己的答案,关于数据库安全。
$_FILES['file']['tmp_name']
是文件在临时存储空间中的服务器位置。
PHP手册明确指出:
默认情况下,文件将存储在服务器的默认临时目录中,除非在 php.ini 中使用 upload_tmp_dir 指令指定了另一个位置。可以通过在 PHP 运行的环境中设置环境变量 TMPDIR 来更改服务器的默认目录。
如果该文件未被移走或重命名,则该文件将在请求结束时从临时目录中删除。
如果您认为您的$_FILES['file']['tmp_name']
价值被滥用,那么这是服务器受损的迹象,您的盘子上会遇到一大堆麻烦,远远超出恶意文件上传。
那么,如何审核正在携带的文件呢?
有许多类型的文件攻击,这个主题远远超出了您所询问的范围。例如; 真正的 JPEG 图像可以在 JPEG 元数据中包含 XSS 脚本,但是在加载和查看 JPEG 时会触发此 XSS,但出于所有意图和目的,JPEG 文件不是“坏文件”或不是 XSS 文件,以不专门检查此漏洞的外部观察者。
那么,你是阻止这个file.jpg
还是阻止所有的Jpeg 文件?这是一个艰难的决定,但在 PHP 中有一些非常好的解决方法(我相信这也超出了这个问题的范围)。简而言之; 您的问题可以通过一些编辑和清晰来说明您究竟要保护什么以及您愿意走多远才能达到该保护级别。
我可以为您提供一个粗略的全面指南,以防止某些MIME 文件类型被您的服务器接受。这看起来和感觉就像您想要的那样,可以阻止偷偷摸摸的 MP4 视频作为文档文件上传(反之亦然)。
1:
忽略文件名 ( $_FILES['file']['name']
)。永远不要相信用户数据。
编辑:正如meagar所指出的,您可能需要保留原始文件名,在这种情况下,您应该使用 REGEX 或类似方法检查它以删除不需要的字符...
2:
忽略声明的文件类型 ( $_FILES['file']['type']
)。任何给定 MIME 类型的文件名(例如.pdf
)都应该被忽略。永远不要相信用户数据。
3:
使用 PHPFinfo
函数集作为初步指标。它并不完美,但会捕捉到大多数东西。
$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
$mimeType = finfo_file($finfo, $_FILES['file']['tmp_name']);
$whitelist = ['text/html','image/gif','application/vnd.ms-excel'];
finfo_close($finfo);
if(in_array($mimeType,$whitelist)){
// File type is acceptable.
}
4:图片:
如果您正在检查上传的图像,最好的方法是finfo
按照3检查文件类型,然后让 PHP 将图像加载到空白画布中并重新保存图像,从而去除所有多余的元数据和其他可能不需要的不是图像的数据-数据。
喜欢这种方法:使用 php 从 jpg 中删除 exif 数据。
5:
还建议始终为您上传的文件随机命名,不要使用该$_FILES['file']['name']
值。
6:
根据您尝试避免和/或消除的威胁类型,您可以打开上传的文件并读取文件的前几个字节,并将其与该类型白名单文件中确认的字节进行比较。这是非常细微的,再次超出了这个答案的范围,这个答案已经足够长了。