验证文件上传服务器端 - 仅允许使用php的图像

时间:2012-04-24 15:34:28

标签: php security validation image-uploading

这里的新人问一个简单的解决方案应该遇到什么的问题。

我尝试过一堆代码。看来我可以获取getimagesize的文件流并让其他东西工作而不会崩溃。

我正在清理一个需要限制上传文件的旧项目,这样它们只是图像文件而且没有任何恶意。

此代码总是给我一个错误消息,无论

$imageinfo = getimagesize($_FILES['bf_file'][$key]['tmp_name']);  
if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg') {  
alert ("Sorry, we only accept GIF and JPEG images");  
exit;  
}  

这是黑名单努力

$blacklist = array(".php", ".phtml", ".php3", ".php4", ".js", ".shtml", ".pl" ,".py"   
,".txt", ".doc");

foreach ($blacklist as $file)
{
if(preg_match("/$file\$/i", $_FILES['bf_file'][$key]['tmp_name']))
{
alert "ERROR: Uploading executable files Not Allowed\n";
exit();
}
} 

这是另一个getimagesize

$size = getimagesize($_FILES[bf_file][$key][tmp_name]);
$fp = fopen($_FILES[bf_file][$key][tmp_name], "rb");
if ($size && $fp) {
header("Content-type: {$size['mime']}");
fpassthru($fp);
continue;
} else
// error
alert("Inappropriate file type"); 

无论是否上传文件,我都会收到错误消息。

我只需要将这些控件放在我的文件中的某个位置,这样如果上传的文件通过了检查,那么一切都只是作为上传器传递,其他一切都像它应该的那样工作但没有这些限制器和检查的好处。

此外,不应要求用户上传文件。主题,正文和文件上传有3个字段。只有主体和身体需要有数据并且现在可以正常工作。

任何帮助将不胜感激。

谢谢,

詹姆斯

3 个答案:

答案 0 :(得分:1)

您的脚本遍布各处示例

$imageinfo = getimagesize($_FILES['bf_file'][$key]['tmp_name']);

获取临时名称应该是$_FILES['bf_file']['tmp_name'][$key],并且文件大小已经通过$_FILES['bf_file']['size'][$key]

返回

为什么不看看类似问题的详细示例

multi image upload wrong quantity on file-upload

Uploading images with the help of arrays and fetch errors

答案 1 :(得分:1)

在第一个片段中。好吧,getimagesize()实际上返回MIME类型(与Baba所说的相反),但你不应该依赖它。完全有可能使文件在开始时看起来像 PNG GIF(阻止PNG的任何原因?),但是在标题有<?php dangerous_code(); ?>之后。另外,我不知道你在[$key]尝试了什么。我不知道它做了什么,数组看起来像$_FILES[$form_name][$file_field](例如$_FILES['file_input']['tmp_size']。没有第三个字段。除非你上传多个文件,然后看看巴巴所说的(这是非常hacky接下来,PHP没有alert() - 你可能意味着echo

在第二个片段中,我看到你做错了。 Dot是正则表达式中的元字符,但在这种情况下它并不重要。无论如何,黑名单方法都存在缺陷,因为您不知道您的服务器是否不支持.php5扩展名。即使它没有,有人可以通过创建文件hack.php.fr来滥用Apache中的content negotiation(Apache认为.fr是语言)。您的方法存在缺陷 - 只要提供PNG文件.png扩展名,无论原始扩展程序是什么等等。

在第三个例子中,你激活错误的变量 - 但也使用裸字(你不应该,虽然我知道你应该有大写的常量(所以与PHP说的相反,如果你有的话,裸字不是那么危险)常识),它们非常慢,比普通字符串慢,如果你有E_NOTICE(提示:你应该),会产生很多错误。接下来,continue不适用于if条件 - 它适用于循环条件(它也适用于switch(作为break),但我想这只是为了保持一致性。)< / p>

至于不必上传文件,这很容易。只需对isset($_FILES['file_input_name'])进行条件限制。

tl; dr - 正确学习PHP

答案 2 :(得分:0)

到目前为止,最安全的方法是阻止您的网络服务器在用户可以完全上传的文件夹中执行动态内容。那么他们上传的内容并不重要。

包含php_flag engine off的上传目录中的.htaccess文件将阻止php。默认情况下,默认情况下应禁用其他可执行文件,但您一定要检查。