所以我有一个客户想要一个摄影网站,用户可以上传他们的照片以回应摄影比赛。虽然从技术上讲这不是问题,但我想知道允许任何用户将任何图像上传到我的服务器上的相关风险。我感觉风险很高......
我在考虑使用像http://www.w3schools.com/php/php_file_upload.asp
这样的东西如果我让匿名用户上传文件,我该如何保护目录图像(以及可能有害的文件)上传到?
答案 0 :(得分:1)
如果您想确保图片是真实图片,可以使用gd加载http://www.php.net/gd
如果正确创建了gd资源,那么图像就是真实图像
首先使用以下方法检测哑剧:
getimagesize($filename);
然后,例如,如果它是一个jpeg加载到gd:
$gdresource = imagecreatefromjpeg($filename);
如果$gdresource
在没有警告的情况下有效/创建,则图像有效且未损坏... getimagesize()
(可能)不足以检测损坏的图像
另外,另一个重要的注意事项......不要依赖$_FILES['blabla']['name']
,因为它可能包含无效的utf-8序列(假设您使用的是utf-8),它可能是潜在的攻击机制,就像任何用户输入一样
因此您还需要对其进行验证/消毒
$originalFileName = $_FILES['blabla']['name'];
$safeOriginalFileName = iconv('UTF-8', 'UTF-8//IGNORE', $originalFileName);
// more additional checks here. for example filename is empty ""
move_uploaded_file(...., $safeOriginalFileName);
另外,请记住$_FILES['blabla']['name']
包含文件扩展名,这可能不正确。因此,您需要将其删除并使用实际正确的扩展名(您之前使用getimagesize() + imagecreatefrom*()
解决的扩展名)
$safeOriginalFileName = basename( $safeOriginalFileName ); // removes the extension
$safeOriginalFileName = $safeOriginalFileName . ".jpg"; // correct extension
希望这有助于:)
正如DaveRandom指出的那样,不要依赖$_FILES['blabla']['type']
,而是按照我的建议使用getimagesize() + imagecreatefrom*()
答案 1 :(得分:0)
上传的文件存储在临时位置,此位置可在$_FILES
变量中找到。
当您的脚本接受上传的文件时,您可以使用move_uploaded_file()
将其移至您选择的位置。
因此,即使用户是匿名的,您也可以控制如何处理上传以及是否接受上传(例如,基于内容,大小等)。
此外,(匿名)用户提供文件和附带的详细信息。所以,如果你盲目地使用这些细节,那么你就很容易受到攻击(意图不好的用户可能会提供错误的细节,使其合法化)。因此,如果您需要这些详细信息,请自行收集(而不是使用$_FILES
)!
有关详细信息,请参阅PHP documentation
答案 2 :(得分:0)
你需要研究一下,但主要是这些是主要的提示:
您可以拥有的基本安全性是实际检查图像的MIME类型和扩展名。虽然这很容易伪造。
使用readfile()
,fopen()
和file_get_contents()
之类的二进制安全函数,我不记得究竟是哪些函数,但有一些PHP函数处理文件存在安全问题,研究哪些是避免它们。
有些函数使用preg_match()
和类似函数来检查是否有与您正在阅读的文件中的脚本类似的内容。使用它们来确保没有隐藏的脚本。这会使这个过程变慢,因为preg_match()
读取大文件的资源非常昂贵,但它不应该非常明显
您还可以触发防病毒软件在电子邮件服务上传的文件上运行。
据我所知,潜在的破坏性图像通常会包含脚本语言,如php代码或javascript来尝试XSS攻击,那里有很多危险,所以我猜你不能保证100%的安全性文件,但要定期查看所有新的危险和避免它们的方法。