2012-04-24 61 views
2

新人在这里问一个问题,应该遇到什么简单的解决方案。验证文件上传服务器端 - 只允许图像与php

我试了一堆代码。看起来我可以获取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

'$ key'的值是什么?无论它包含什么内容,由于很久以前某些PHP作者的某些*高级*愚蠢,您需要引用'$ _FILES ['bf_file'] ['tmp_name'] [$ key]'而不是$ _FILES ['bf_file'] [$ key] ['tmp_name']'。另外请注意,'getimagesize()'是唯一明智的方法,我甚至无法在评论给我的少量空间中解释你的黑名单方法是错误的。 – DaveRandom 2012-04-24 15:39:07

+1

这里有一个:你的preg_match不是多行的,所以很容易受到空白的攻击。使用白名单的原因之一,而不是黑名单。另外,您确实需要从图像画布中复制像素数据,但如果您仅保存文件,则容易受到恶意用户上载包含嵌入式服务器端脚本的图像文件的影响。 – Cheekysoft 2012-04-24 16:10:29

+0

@Cheekysoft,还有'index.php5'(它可能存在)和'index.php.fr'([content negotiation](http://httpd.apache.org/docs/current/content-negotiation.html) ) – xfix 2012-04-24 16:14:43

回答

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

+0

很明显,我只是环顾四周,从网上抓取这些代码,并将它们扔到我的页面中。谈论$ key的位置,这是因为有多张图片可以上传?谢谢 – crazytrain999 2012-04-24 16:33:17

+0

不客气..点击链接有详细的例子之前已经做了...和它的字符串非常f .. ..你不应该有定制它的问题 – Baba 2012-04-24 16:34:37

1

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

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

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

至于没有上传文件,这很容易。只要在isset($_FILES['file_input_name'])附近做条件。

TL;博士 - 了解PHP正确

+0

'那么违反PHP说的,裸语不那么危险如果你有常识 - 公平点,但他们仍然使你的错误日志杂乱无章,容易发生错误。 – DaveRandom 2012-04-24 16:14:07

+0

@DaveRandom:已更新 – xfix 2012-04-24 16:15:49

+0

+1关于哑剧澄清 – Baba 2012-04-24 16:37:00

0

迄今为止最安全的做法是防止你的服务器在用户可以上传文件夹完全执行动态的东西。然后,他们上传的内容无关紧要。

包含php_flag engine off的上传目录中的.htaccess文件将阻止php。无论如何,其他可执行的东西应该被默认禁用,但你一定要检查。