python 如何防止每个恶意文件上传到我的服务器上?(检查文件类型)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/690108/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to prevent every malicious file upload on my server? (check file type)?
提问by Strae
my proble is to avoid that users upload some malicious file on my web-server. Im working on linux environment (debian).
我的问题是避免用户在我的网络服务器上上传一些恶意文件。我在 linux 环境(debian)上工作。
Actually the uploads are handled via php by this code:
实际上,上传是通过以下代码通过 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; }
}
here i can specify the extensions allowed to be uploaded, and if the file dont meet them i delete as soon as the upload is completed. But this way let the user free to change the file extension with a simple rename.. and thats bad for me; even if a file.exe (for example) wont never be executed if is renamed in file.jpg (am i right?), i dont want to have potential danger files on my server.
在这里我可以指定允许上传的扩展名,如果文件不符合它们,我会在上传完成后立即删除。但是这种方式让用户可以通过简单的重命名自由更改文件扩展名……这对我来说很糟糕;即使 file.exe(例如)在 file.jpg 中重命名后永远不会被执行(我是对的吗?),我也不希望我的服务器上有潜在的危险文件。
There is a way, in php, python, or whatelse can a unix system run easly, to check the truly type of a file?
有一种方法,在 php、python 或其他什么 Unix 系统中可以轻松运行,以检查文件的真实类型?
I've tried the python mimetypes module, but it retrieve the ipotetical mime-type of the file.. based on the extension -.-
我试过 python mimetypes 模块,但它检索文件的 ipotetical mime-type.. 基于扩展名 -.-
回答by palako
I'm afraid to say that the answer you selected as correct is not correct. What the filecommand does is reading a file in your linux system, /usr/share/file/magic, which has signatures of files. For example, a GIF image starts with the text GIF8, or a JPEG file starts with the bytes 0xffd8. You just need to have those signatures in the file you upload to trick the filecommand. These two files would be accepted as images, even though they would run as php code:
恐怕要说您选择的正确答案是不正确的。什么是文件命令的作用是读取文件在你的Linux系统,在/ usr /共享/文件/魔术,其中有文件的签名。例如,GIF 图像以文本GIF8 开头,或者 JPEG 文件以字节0xffd8 开头。您只需要在上传的文件中包含这些签名即可欺骗file命令。这两个文件将被接受为图像,即使它们将作为 php 代码运行:
eval_gif.php:
eval_gif.php:
GIF8<?php eval($_GET["command"]);?>
eval_jpg.php(hexdump):
eval_jpg.php(十六进制转储):
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 |>..|
These are the most common mistakes when filtering:
这些是过滤时最常见的错误:
- Not filter at all.
- Filter based on incorrect regular expressions easily bypassable.
- Not using is_uploaded_file and move_uploaded_file functions can get to LFI vulnerabilities.
- Not using the $_FILES array (using global variables instead) can get to RFI vulns.
- Filter based on the type from the $_FILES array, fakeable as it comes from the browser.
- Filter based on server side checked mime-type, fooled by simulating what the magic files contain (i.e. a file with this content GIF8 is identified as an image/gif file but perfectly executed as a php script)
- Use blacklisting of dangerous files or extensions as opposed to whitelisting of those that are explicitely allowed.
- Incorrect apache settings that allow to upload an .htaccess files that redefines php executable extensions (i.e. txt)..
- 根本不过滤。
- 基于不正确的正则表达式的过滤器很容易绕过。
- 不使用 is_uploaded_file 和 move_uploaded_file 函数可能会导致 LFI 漏洞。
- 不使用 $_FILES 数组(改为使用全局变量)可能会导致 RFI 漏洞。
- 根据 $_FILES 数组中的类型进行过滤,可伪造,因为它来自浏览器。
- 基于服务器端检查的 mime 类型的过滤器,通过模拟魔法文件包含的内容来愚弄(即具有此内容的文件 GIF8 被识别为图像/gif 文件,但完美地作为 php 脚本执行)
- 使用危险文件或扩展名的黑名单,而不是将那些明确允许的文件或扩展名列入白名单。
- 不正确的 apache 设置允许上传重新定义 php 可执行文件扩展名(即 txt)的 .htaccess 文件。
回答by RossFabricant
Users shouldn't be able to execute the files they upload. Remove their permission to execute.
用户不应该能够执行他们上传的文件。删除他们的执行权限。
回答by rmeador
You're going to need to validate that the uploaded file is actually the type that the extension indicates it is. You can do that through various methods, probably the easiest is via the file
command. I don't know if it has an API. You can try it out yourself in the shell. For your example of file.exe that was renamed to file.jpg before being uploaded, run file file.jpg
and it will print out something telling you it's an executable. It can be fooled, however.
您将需要验证上传的文件实际上是扩展名指示的类型。您可以通过各种方法来做到这一点,最简单的方法可能是通过file
命令。不知道有没有API。您可以自己在 shell 中尝试一下。对于在上传之前重命名为 file.jpg 的 file.exe 示例,运行file file.jpg
它会打印出一些内容,告诉您它是一个可执行文件。然而,它可以被愚弄。
I'm guessing you don't know much about Linux file permissions if you think .exe means it will be executed. On linux, only the execute bit in the file permissions determine that -- you can execute any file, regardless of extension, if that bit is turned on. Don't set it on any uploaded files and you should be safe from executing them. You may still be serving them back up to your site's visitors, so it could still be a vector for XSS attacks, so watch out for that.
如果您认为 .exe 意味着它将被执行,我猜您对 Linux 文件权限了解不多。在 linux 上,只有文件权限中的执行位决定——您可以执行任何文件,无论扩展名如何,只要该位打开。不要在任何上传的文件上设置它,你应该可以安全地执行它们。您可能仍在为您网站的访问者提供服务,因此它仍然可能成为 XSS 攻击的载体,因此请注意这一点。
回答by bobince
There is a way, in php, python, or whatelse can a unix system run easly, to check the truly type of a file?
有一种方法,在 php、python 或其他什么 Unix 系统中可以轻松运行,以检查文件的真实类型?
No.
不。
You can create a file called, say, “something.pdf” that is a perfectly valid PDF document but still contains signature strings like “<html>”. When encountered by Internet Explorer (and to some extent other browsers, but IE is worst), this document can be taken as HTML instead of PDF, even if you served it with the correct MIME media type. Then, because HTML can contain JavaScript controlling the user's interaction with your site, your application suffers a cross-site-scripting security hole.
您可以创建一个名为“something.pdf”的文件,它是一个完全有效的 PDF 文档,但仍包含诸如“<html>”之类的签名字符串。当 Internet Explorer(以及在某种程度上其他浏览器,但 IE 最糟糕)遇到此文档时,即使您使用正确的 MIME 媒体类型提供它,该文档也可以被视为 HTML 而不是 PDF。然后,由于 HTML 可以包含控制用户与站点交互的 JavaScript,因此您的应用程序会遇到跨站点脚本安全漏洞。
Content-sniffing is a security disaster. See this post for some general workarounds: Stop people uploading malicious PHP files via forms
内容嗅探是一场安全灾难。有关一些常规解决方法,请参阅此帖子:阻止人们通过表单上传恶意 PHP 文件
回答by theller
Typically you use the 'file' command to find out what a file contains. I'm not sure, however, if it will detect .exe files:
通常,您使用“文件”命令来找出文件包含的内容。但是,我不确定它是否会检测到 .exe 文件:
回答by Strae
ye, i used to say 'executed' for example-meaning. Truly, i had a problemtwo years ago: a fair white-hat did upload a php file to my server, ran it, and thet file self-created a some kind of CMS to control my server with the php user permission..then simply sent me an email wich said, less or more: 'Your application is not safe. For demostration, i have dont this and that...'
是的,我曾经说“已执行”作为示例含义。确实,两年前我遇到了一个问题:一个公平的白帽子确实将一个 php 文件上传到我的服务器,运行它,然后该文件自行创建了某种 CMS 以使用 php 用户权限控制我的服务器..then只是给我发了一封电子邮件,或多或少说:“您的应用程序不安全。为了演示,我没有这个和那个......'
Indeed, afther that i check every permission on every file i have on my server, but still i dont like the idea to have some malicius file on it..
确实,之后我检查了服务器上每个文件的所有权限,但我仍然不喜欢在其上放置一些恶意文件的想法..
I'll give a try to the file unix function, i've already see that i can retrieve the output by a code like that:
我将尝试使用文件 unix 函数,我已经看到我可以通过这样的代码检索输出:
<?
php passthru('file myfile.pdf', $return);
echo $return;
?>
With some tuning i hope will be safe enaught.
通过一些调整,我希望能足够安全。
@Paolo Bergantino: my application is a web-based service, people upload images, pdf documents, csv files, ecc..., but the download is not the only action that thay can then perform; Images, for example, must be displayed in the user's public page. The way i think i'll take is that:
@Paolo Bergantino:我的应用程序是一个基于网络的服务,人们上传图像、pdf 文档、csv 文件、ecc...,但下载并不是他们可以执行的唯一操作;例如,图像必须显示在用户的公共页面中。我认为我会采取的方式是:
- Upload the File;
- Check the file type with the file passthru;
- Delete if is not clear;
- Else, move it to the user's directory (named with randoms strings)
- 上传文件;
- 使用文件通路检查文件类型;
- 不清楚的就删掉;
- 否则,将其移动到用户目录(以随机字符串命名)
Thanks to everyone.
谢谢大家。