上传的安全威胁

2022-01-09 00:00:00 upload php

我允许用户将文件上传到我的服务器.我面临哪些可能的安全威胁?如何消除它们?

I am allowing users to upload files to my server. What possible security threats do I face and how can I eliminate them?

假设我允许用户从他们的系统或网络上传图像到我的服务器.现在要检查这些图像的大小,我必须将它们存储在我的 /tmp 文件夹中.不是很危险吗?如何将风险降到最低?

Let's say I am allowing users to upload images to my server either from their system or from net. Now to check even the size of these images I have to store them in my /tmp folder. Isn't it risky? How can I minimize the risk?

另外,假设我正在使用 wget 从用户在我的表单中上传的链接下载图像.我首先必须将这些文件保存在我的服务器中以检查它们是否真的是图像.另外,如果恶作剧者给了我一个 URL,我最终下载了一个充满恶意软件的整个网站怎么办?

Also let's say I am using wget to download the images from the link that the users upload in my form. I first have to save those files in my server to check if they actually are images. Also what if a prankster gives me a URL and I end up downloading an entire website full of malware?

推荐答案

首先,要意识到上传文件意味着用户给了你大量各种格式的数据,而且用户可以完全控制该数据.这甚至是普通表单文本字段的一个问题,文件上传是相同的,而且更多.第一条规则是:不要相信任何一个.

First of all, realize that uploading a file means that the user is giving you a lot of data in various formats, and that the user has full control over that data. That's even a concern for a normal form text field, file uploads are the same and a lot more. The first rule is: Don't trust any of it.

您通过文件上传从用户那里得到什么:

What you get from the user with a file upload:

  • 文件数据
  • 文件名
  • 一种 MIME 类型

这是文件上传的三个主要组成部分,没有一个是可信的.

These are the three main components of the file upload, and none of it is trustable.

  1. 不要信任 $_FILES['file']['type'] 中的 MIME 类型.这是一个完全任意的、用户提供的值.

  1. Do not trust the MIME type in $_FILES['file']['type']. It's an entirely arbitrary, user supplied value.

不要将文件名用于任何重要的事情.这是一个完全任意的、用户提供的值.通常,您不能信任文件扩展名或名称.不要使用类似 'dir/' 的方式将文件保存到服务器的硬盘上.$_FILES['file']['name'].如果名称是 '../../../passwd',您将覆盖其他目录中的文件.始终自己生成一个随机名称以将文件另存为.如果您愿意,您可以将原始文件名作为元数据存储在数据库中.

Don't use the file name for anything important. It's an entirely arbitrary, user supplied value. You cannot trust the file extension or the name in general. Do not save the file to the server's hard disk using something like 'dir/' . $_FILES['file']['name']. If the name is '../../../passwd', you're overwriting files in other directories. Always generate a random name yourself to save the file as. If you want you can store the original file name in a database as meta data.

永远不要让任何人或任何东西任意访问文件.例如,如果攻击者将 malicious.php 文件上传到您的服务器,并且您将其存储在您网站的 webroot 目录中,那么用户只需访问 example.com/uploads/malicious.php 执行该文件并在您的服务器上运行任意 PHP 代码.

Never let anybody or anything access the file arbitrarily. For example, if an attacker uploads a malicious.php file to your server and you're storing it in the webroot directory of your site, a user can simply go to example.com/uploads/malicious.php to execute that file and run arbitrary PHP code on your server.

  • 切勿将任意上传的文件公开存储在任何地方,始终将它们存储在只有您的应用程序可以访问它们的地方.

  • Never store arbitrary uploaded files anywhere publicly, always store them somewhere where only your application has access to them.

只允许特定进程访问文件.如果它应该是图像文件,则只允许读取图像并调整它们大小的脚本直接访问该文件.如果此脚本在读取文件时出现问题,则可能不是图像文件,标记它和/或丢弃它.其他文件类型也是如此.如果该文件应该可供其他用户下载,请创建一个脚本来提供该文件以供下载,并且不对其进行任何其他操作.

Only allow specific processes access to the files. If it's supposed to be an image file, only allow a script that reads images and resizes them to access the file directly. If this script has problems reading the file, it's probably not an image file, flag it and/or discard it. The same goes for other file types. If the file is supposed to be downloadable by other users, create a script that serves the file up for download and does nothing else with it.

如果您不知道要处理的文件类型,请自行检测文件的 MIME 类型和/或尝试让特定进程打开文件(例如,让图像调整大小进程尝试调整假定图像的大小).这里也要小心,如果该过程中存在漏洞,恶意制作的文件可能会利用它,从而导致安全漏洞(此类攻击的最常见示例是 Adob​​e 的 PDF 阅读器).

If you don't know what file type you're dealing with, detect the MIME type of the file yourself and/or try to let a specific process open the file (e.g. let an image resize process try to resize the supposed image). Be careful here as well, if there's a vulnerability in that process, a maliciously crafted file may exploit it which may lead to security breaches (the most common example of such attacks is Adobe's PDF Reader).

<小时>

解决您的具体问题:


To address your specific questions:

[T] 要检查这些图像的大小,我必须将它们存储在我的/tmp 文件夹中.是不是很危险?

[T]o check even the size of these images I have to store them in my /tmp folder. Isn't it risky?

没有.如果您不对这些数据进行任何操作,那么仅将数据存储在临时文件夹中的文件中是没有风险的.数据只是数据,无论其内容如何.仅当您尝试执行数据或程序正在解析数据时才会有风险,如果程序包含解析缺陷,恶意数据可能会诱使该数据执行意外的操作.

No. Just storing data in a file in a temp folder is not risky if you're not doing anything with that data. Data is just data, regardless of its contents. It's only risky if you're trying to execute the data or if a program is parsing the data which can be tricked into doing unexpected things by malicious data if the program contains parsing flaws.

当然,在磁盘上存放任何类型的恶意数据比在任何地方没有恶意数据风险更大.你永远不知道谁会来和它一起做点什么.所以你应该验证所有上传的数据,如果它没有通过验证,请尽快丢弃它.

Of course, having any sort of malicious data sitting around on the disk is more risky than having no malicious data anywhere. You never know who'll come along and do something with it. So you should validate any uploaded data and discard it as soon as possible if it doesn't pass validation.

如果恶作剧者给了我一个网址,我最终下载了一个充满恶意软件的整个网站怎么办?

What if a prankster gives me a url and I end up downloading an entire website full of malware?

具体下载什么取决于您.一个 URL 最多会产生一个数据块.如果您正在解析该数据并基于该初始 blob 下载更多 URL 的内容,那是您的问题.不要这样做.但即使你这样做了,那么你也会有一个临时目录,里面装满了东西.同样,如果您不使用这些东西做任何危险的事情,这并不危险.

It's up to you what exactly you download. One URL will result at most in one blob of data. If you are parsing that data and are downloading the content of more URLs based on that initial blob that's your problem. Don't do it. But even if you did, well, then you'd have a temp directory full of stuff. Again, this is not dangerous if you're not doing anything dangerous with that stuff.

相关文章