如何防止我的服务器上的每个恶意文件上传? (检查文件类型)?

时间:2009-03-27 14:58:36

标签: php python security file types

我的问题是避免用户在我的网络服务器上上传一些恶意文件。 我正在使用linux环境(debian)。

实际上上传是通过以下代码通过php处理的:

function checkFile($nomeFile, $myExt = false){
if($myExt != false){ $goodExt = "_$myExt"."_"; }else{ $goodExt = "_.jpg_.bmp_.zip_.pdf_.gif_.doc_.xls_.csv_.docx_.rar_"; }
$punto = strrpos($nomeFile, '.');
$ext = "_".substr($nomeFile, $punto, 8)."_";
if(stristr($goodExt, $ext)){ return 1; }else{ return 0; }
}

这里我可以指定允许上传的扩展名,如果文件不符合,我会在上传完成后立即删除。 但这样一来,用户可以通过简单的重命名来自由更改文件扩展名......这对我不利;即使file.exe(例如)如果在file.jpg中重命名也不会被执行(我是对吗?),我不希望在我的服务器上有潜在的危险文件。

有一种方法,在php,python或whatelse中,unix系统可以轻松运行,以检查文件的真实类型吗?

我已经尝试过python mimetypes模块,但它检索文件的ipotetical mime类型..基于扩展名-.-

6 个答案:

答案 0 :(得分:10)

我不敢说你选择的答案是正确的。 file 命令的作用是读取linux系统中的文件 / usr / share / file / magic ,它有文件签名。例如,GIF图像以文本 GIF8 开头,或JPEG文件以字节 0xffd8 开头。您只需要在上传的文件中使用这些签名来欺骗 file 命令。这两个文件将被接受为图像,即使它们将作为PHP代码运行:

eval_gif.php:

GIF8<?php eval($_GET["command"]);?>

eval_jpg.php(hexdump都):

ff d8 3c 3f 70 68 70 20  65 76 61 6c 28 24 5f 47  |..<?php eval($_G|    
45 54 5b 22 63 6f 6d 6d  61 6e 64 22 5d 29 3b 3f  |ET["command"]);?|    
3e 0a 0a                                          |>..|

这些是过滤时最常见的错误:

  • 根本不过滤。
  • 根据不正确的正则表达式过滤容易绕过。
  • 不使用is_uploaded_file和move_uploaded_file函数可能会导致LFI漏洞。
  • 不使用$ _FILES数组(改为使用全局变量)可以使用RFI版本。
  • 根据$ _FILES数组中的类型进行过滤,因为它来自浏览器。
  • 基于服务器端检查的mime-type进行过滤,通过模拟魔术文件包含的内容来欺骗(即具有此内容的文件GIF8被识别为图像/ gif文件,但完美地作为php脚本执行)
  • 使用危险文件或扩展名列入黑名单,而不是明确允许列入白名单。
  • 不正确的apache设置,允许上传重新定义php可执行扩展名(即txt)的.htaccess文件..

答案 1 :(得分:7)

用户不应该能够执行他们上传的文件。删除他们的执行权限。

答案 2 :(得分:7)

您需要验证上传的文件实际上是扩展程序指示的类型。你可以通过各种方法做到这一点,最简单的方法是通过file命令。我不知道它是否有API。你可以在shell中自己试试。对于你在上传之前重命名为file.jpg的file.exe的例子,运行file file.jpg它会打印出一些告诉你它是可执行文件的东西。然而,它可能会被愚弄。

如果您认为.exe意味着它将被执行,我猜您对Linux文件权限知之甚少。在linux上,只有文件权限中的执行位才能确定 - 如果打开该位,您可以执行任何文件,无论扩展名如何。不要在任何上传的文件上设置它,你应该安全地执行它们。您可能仍然会将它们提供给您网站的访问者,因此它仍然可能是XSS攻击的载体,因此请注意这一点。

答案 3 :(得分:2)

  

有一种方法,在php,python或whatelse中,unix系统可以轻松运行,以检查文件的真实类型吗?

没有

您可以创建一个名为“something.pdf”的文件,该文件是完全有效的PDF文档,但仍包含“&lt; html&gt;”等签名字符串。当Internet Explorer遇到(在某种程度上其他浏览器,但IE最差)时,即使您使用正确的MIME媒体类型提供此文档,也可以将此文档视为HTML而不是PDF。然后,因为HTML可以包含控制用户与您的站点交互的JavaScript,所以您的应用程序会遇到跨站点脚本安全漏洞。

内容嗅探是一种安全灾难。有关常规解决方法,请参阅此帖子:Stop people uploading malicious PHP files via forms

答案 4 :(得分:1)

通常,您使用'file'命令查找文件包含的内容。但是,我不确定它是否会检测.exe文件:

http://unixhelp.ed.ac.uk/CGI/man-cgi?file

答案 5 :(得分:0)

你们,我曾经说'执行',例如 - 意思。 真的,两年前我有一个问题:一个公平的白帽确实上传了一个php文件到我的服务器,运行它,并且该文件自行创建了某种CMS来控制我的服务器php用户权限..然后只是给我发了一封电子邮件,说的更少或更多:'你的申请不安全。为了示范,我不这样做......'

事实上,我检查我服务器上的每个文件的每个权限,但我仍然不喜欢有一些appleius文件的想法..

我将尝试文件unix函数,我已经看到我可以通过这样的代码检索输出:

<?
php passthru('file myfile.pdf', $return);
echo $return;
?>

通过一些调整,我希望能够安然无恙。

@Paolo Bergantino:我的应用程序是一个基于Web的服务,人们上传图像,pdf文档,csv文件,ecc ...,但下载并不是唯一可以执行的操作;例如,图像必须显示在用户的公共页面中。 我认为我将采取的方式是:

  1. 上传文件;
  2. 使用文件passthru检查文件类型;
  3. 如果不清楚则删除;
  4. 否则,将其移至用户目录(以randoms字符串命名)
  5. 感谢大家。