简体   繁体   English

如何保护PHP图像上载脚本免受攻击?

[英]How can I protect a PHP image upload script from exploits?

I've created (using a script and some help from Stack and some help from friends; I know very little about PHP) a simple page for a local non-profit publication where people can upload photos. 我创建了(使用Stack 提供的脚本和一些帮助以及朋友的一些帮助;我对PHP知之甚少)一个简单的页面,用于本地非营利性出版物,人们可以上传照片。

I'm not great with security (from a basis of ignorance, not deliberate negligence) but I've taken the following steps to protect this page: 我对安全性不是很好(基于无知,而不是故意疏忽)但我采取了以下步骤来保护这个页面:

• the PHP script is set to only accept .jpg, .png and .tif files for upload; •PHP脚本设置为仅接受.jpg,.png和.tif文件进行上传;
• the subfolder that it saves the form content to has permissions set at 700, and the subfolder it saves uploaded photos to has permissions set at 700; •保存表单内容的子文件夹具有设置为700的权限,并且保存上传照片的子文件夹具有设置为700的权限;
• according to documentation, my host has the following configuration to ensure that only .php files run as .php: •根据文档,我的主机具有以下配置,以确保只有.php文件以.php运行:

<FilesMatch \.php$>
    SetHandler php52-fcgi
</FilesMatch>

• I've put an .htaccess file in the relevant (main and saved content) folders: •我在相关(主要和保存的内容)文件夹中放置了.htaccess文件:

RemoveHandler .php
RemoveHandler .inc
RemoveHandler .pl
RemoveHandler .cgi
RemoveHandler .py
RemoveHandler .fcgi

Overnight, however, somebody found this test page and submitted what seems to be a perfectly benign test message and small .jpg. 然而,一夜之间,有人找到了这个测试页面,并提交了一个看起来非常良性的测试信息和小.jpg。 This is a private test page with a non-intuitive URL that only I and about three other people know about; 这是一个私人测试页面,其中包含一个非直观的网址,只有我和其他三个人都知道; none of the others sent this test. 其他人都没有发过这个测试。

This obviously has me worried that there's something hinky going on, and I'm worried that I don't know enough about security to make sure this page is safe. 这显然让我担心会发生一些奇怪的事情,我担心我对安全性的了解不足以确保这个页面是安全的。

Is there something obvious that I'm missing? 有什么明显的东西让我失踪吗?

When dealing with uploaded you should keep in mind that all the data you can find in the $_FILES array can be faked. 在处理上传时,您应该记住,您可以在$ _FILES数组中找到的所有数据都是伪造的。 It's traveling through HTTP so it's pretty easy to give the image/jpg mime to an executable file for exemple. 它正在通过HTTP进行传输,因此将image / jpg mime提供给可执行文件非常容易。

1- Check the true mime 1-检查真正的哑剧

PHP come with some function to check the real mime of a file. PHP附带了一些功能来检查文件的真实mime。 For that you should use fileinfo 为此你应该使用fileinfo

$finfo = new finfo(FILEINFO_MIME, "/usr/share/misc/magic");
$filename = "/var/tmp/afile.jpg";
echo $finfo->file($filename);

2- Check the image's properties 2-检查图像的属性

You apparently want to upload only image , so the received file must have a width and a height : 您显然只想上传图片,因此收到的文件必须有宽度和高度:

Use getImageSize() to get all the required information about the image. 使用getImageSize()获取有关图像的所有必需信息。 If it return false , the file is probably not an image and you can delete it. 如果返回false,则该文件可能不是图像,您可以将其删除。 getImageSize can also give you a mime type , but i don't know if it can be trusted. getImageSize也可以给你一个mime类型,但我不知道它是否可以信任。

2.5- Reprocess image 2.5-重新处理图像

As suggested by user628405 , reprocessing the image with GD is probably the more secure thing to do. 正如user628405所建议的那样,用GD重新处理图像可能是更安全的事情。

$img = imagecreatefrompng('vulnerable.png'); 
imagepng($img, 'safe.png');

Obviously it has to be adapted according to the image type. 显然它必须根据图像类型进行调整。 See all the imagecreatefrom* in php documentation. 在php文档中查看所有imagecreatefrom *。

3- Upload folder In addition of what you have already done : 3-上传文件夹除了你已经做过的事情:

Make sure your upload folder is not available from the web. 确保您的上传文件夹不在网上。 Validate the uploaded file then move it to an other folder if needed and rename the file. 验证上载的文件,然后根据需要将其移动到其他文件夹并重命名该文件。 It will prevent hacker from executing a malicious file (can't execute it if it can't be reached by an url). 它将阻止黑客执行恶意文件(如果网址无法访问,则无法执行)。

Further reading : https://www.owasp.org/index.php/Unrestricted_File_Upload 进一步阅读: https//www.owasp.org/index.php/Unrestricted_File_Upload

Don't rely on any data from the client, including content type! 不要依赖客户端的任何数据,包括内容类型!

Don't save uploaded files in the web root. 不要将上载的文件保存在Web根目录中。 Uploaded files should be only accessible via your scripts, for better control. 只能通过脚本访问上传的文件,以便更好地控制。

Don't save uploaded files with their original file names and extensions! 不要使用原始文件名和扩展名保存上传的文件! Store this data in a database for retrieval later. 将此数据存储在数据库中以便以后检索。

You can check the MIME type of the file, but don't worry as long as your php handler can only execute .php files and you're taking care of not saving uploaded .php files in your script, you're not exposing any security leak. 你可以检查文件的MIME类型,但是不要担心,只要你的php处理程序只能执行.php文件而你正在处理不保存脚本中上传的.php文件,你不会暴露任何文件安全漏洞。

This is valid for .php files as well as any other server-side scripting language installed on your server of course. 这对于.php文件以及服务器上安装的任何其他服务器端脚本语言当然有效。

A better idea is to keep a white of the extensions you're accepting to save on your filesystem. 更好的想法是保留您要接受的扩展名以保存在文件系统上。

I would ignore the MIME type and the file extension of the incoming file. 我会忽略MIME类型和传入文件的文件扩展名。 These can be faked. 这些可以伪造。

Store those files in a directory if you are going down that avenue. 如果您要沿着那条大道走下去,请将这些文件存储在目录中。

Ensure that that directory is just for images (music) and then get a script to place the correct extension on them by looking at the files format. 确保该目录仅用于图像(音乐),然后通过查看文件格式获取脚本以在其上放置正确的扩展名。

Also ensure that that directory cannot execute PHP (or anything else). 还要确保该目录不能执行PHP(或其他任何东西)。

This will keep you safe. 这将保证您的安全。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM