File Upload Cheat Sheet / 文件上传技巧清单¶
Introduction / 介绍¶
File upload is becoming a more and more essential part of any application, where the user is able to upload their photo, their CV, or a video showcasing a project they are working on. The application should be able to fend off bogus and malicious files in a way to keep the application and the users safe.
文件上传正变得越来越重要,它是任何应用程序中用户上传照片、简历或展示他们正在工作的项目的必要部分。应用程序应该能够抵御虚假和恶意文件,以保护应用程序和用户的安全。
In short, the following principles should be followed to reach a secure file upload implementation:
简而言之,以下原则应遵循以实现安全的文件上传实现:
- List allowed extensions. Only allow safe and critical extensions for business functionality
中文:列出允许的扩展名。仅允许对业务功能安全和关键的扩展名**- Ensure that input validation is applied before validating the extensions.
中文:在验证扩展名之前,确保应用了输入验证**
- Ensure that input validation is applied before validating the extensions.
- Validate the file type, don't trust the Content-Type header as it can be spoofed
中文:验证文件类型,不要信任Content-Type头,因为它可以被欺骗** - Change the filename to something generated by the application
中文:将文件名更改为由应用程序生成的名称** - Set a filename length limit. Restrict the allowed characters if possible
中文:设置文件名长度限制。如果可能,限制允许的字符** - Set a file size limit
中文:设置文件大小限制** - Only allow authorized users to upload files
中文:仅允许授权用户上传文件 - Store the files on a different server. If that's not possible, store them outside of the webroot
中文:将文件存储在不同的服务器上。如果不可能,请将它们存储在webroot之外- In the case of public access to the files, use a handler that gets mapped to filenames inside the application (someid -> file.ext)
中文:如果文件公开访问,请使用将映射到应用程序内部文件名的处理程序(someid -> file.ext)
- In the case of public access to the files, use a handler that gets mapped to filenames inside the application (someid -> file.ext)
- Run the file through an antivirus or a sandbox if available to validate that it doesn't contain malicious data
中文:如果可用,运行文件通过杀毒软件或沙箱以验证其不包含恶意数据 - Run the file through CDR (Content Disarm & Reconstruct) if applicable type (PDF, DOCX, etc...)
中文:如果适用,运行文件通过CDR(内容解除武装与重建) - Ensure that any libraries used are securely configured and kept up to date
中文:确保使用的任何库都安全配置并保持更新 - Protect the file upload from CSRF attacks
中文:保护文件上传免受CSRF攻击
File Upload Threats / 文件上传威胁¶
In order to assess and know exactly what controls to implement, knowing what you're facing is essential to protect your assets. The following sections will hopefully showcase the risks accompanying the file upload functionality.
为了评估和确切了解需要实施哪些控制措施,了解你所面临的情况对于保护你的资产至关重要。以下章节将有望展示与文件上传功能伴随的风险。
Malicious Files / 恶意文件¶
The attacker delivers a file for malicious intent, such as:
攻击者为了恶意目的提供文件,例如:
- Exploit vulnerabilities in the file parser or processing module (e.g. ImageTrick Exploit, XXE)
中文:利用文件解析器或处理模块中的漏洞(例如 ImageTrick 漏洞,XXE) - Use the file for phishing (e.g. careers form)
中文:使用文件进行钓鱼(例如:求职表格) - Send ZIP bombs, XML bombs (otherwise known as billion laughs attack), or simply huge files in a way to fill the server storage which hinders and damages the server's availability
中文:发送ZIP炸弹、XML炸弹(也称为亿笑攻击)或简单地发送大文件以填充服务器存储,从而阻碍和损害服务器的可用性 - Overwrite an existing file on the system
中文:覆盖系统中的现有文件 - Client-side active content (XSS, CSRF, etc.) that could endanger other users if the files are publicly retrievable.
中文:客户端活动内容(XSS、CSRF等),如果文件可以公开检索,可能会危及其他用户。
Public File Retrieval / 公开文件检索¶
If the file uploaded is publicly retrievable, additional threats can be addressed:
如果上传的文件是公开可检索的,可以解决以下额外威胁:
- Public disclosure of other files
中文:其他文件的公开披露 - Initiate a DoS attack by requesting lots of files. Requests are small, yet responses are much larger
中文:通过请求大量文件来发起DoS攻击。请求很小,但响应却很大 - File content that could be deemed as illegal, offensive, or dangerous (e.g. personal data, copyrighted data, etc.) which will make you a host for such malicious files.
中文:可能被视为非法、冒犯性或危险的内容的文件(例如:个人数据、版权数据等),这将使您成为此类恶意文件的宿主。
File Upload Protection / 文件上传保护¶
There is no silver bullet in validating user content. Implementing a defense in depth approach is key to make the upload process harder and more locked down to the needs and requirements for the service. Implementing multiple techniques is key and recommended, as no one technique is enough to secure the service.
在验证用户内容方面没有一劳永逸的方法。实施深度防御策略是使上传过程更困难、更符合服务需求和要求的关键。实施多种技术是关键且推荐的,因为没有任何一种技术足以保证服务的安全。
Extension Validation / 扩展名验证¶
Ensure that the validation occurs after decoding the filename, and that a proper filter is set in place in order to avoid certain known bypasses, such as the following:
确保在解码文件名之后进行验证,并设置适当的过滤器,以避免以下已知绕过方法:
- Double extensions, e.g.
.jpg.php, where it circumvents easily the regex\.jpg
中文:双重扩展,例如.jpg.php,它容易绕过正则表达式\.jpg - Null bytes, e.g.
.php%00.jpg, where.jpggets truncated and.phpbecomes the new extension
中文:空字节,例如.php%00.jpg,其中.jpg被截断,.php成为新的扩展 - Case manipulation, e.g.
.pHp,.phP, to bypass case-sensitive blocklist filters
中文:大小写操作,例如.pHp,.phP,以绕过大小写敏感的阻止列表过滤器 - Alternative extensions that may be mapped to the same server-side interpreter depending on configuration, e.g.
.phtml,.php5,.phtfor PHP, or.jsp/.jspx,.asp/.aspxfor Java/.NET (PortSwigger)
中文:根据配置,可能映射到相同服务器端解释器的替代扩展名,例如 PHP 的.phtml、.php5、.pht,或 Java/.NET 的.jsp/.jspx、.asp/.aspx(PortSwigger) - Windows NTFS Alternate Data Streams, e.g.
shell.asp:.jpgorshell.php::$DATA, where the colon is interpreted as a stream separator and the actual file created on disk carries the extension before the colon - reject any filename containing a colon (:) (OWASP - Unrestricted File Upload)
中文:Windows NTFS 替代数据流,例如shell.asp:.jpg或shell.php::$DATA,其中冒号被解释为流分隔符,实际创建在磁盘上的文件在冒号之前带有扩展名 - 拒绝任何包含冒号(:)的文件名(OWASP - 无限制文件上传) - Generic bad regex that isn't properly tested and well reviewed. Refrain from building your own logic unless you have enough knowledge on this topic.
中文:通用的不良正则表达式,未经适当测试和良好审查。除非你对这个主题有足够的了解,否则请勿构建自己的逻辑。
Refer to the Input Validation CS to properly parse and process the extension.
参考 输入验证 CS 以正确解析和处理扩展。
List Allowed Extensions / 列出允许的扩展¶
Ensure the usage of business-critical extensions only, without allowing any type of non-required extensions. For example if the system requires:
确保仅使用 业务关键 扩展,不允许任何类型的 非必需 扩展。例如,如果系统需要:
- image upload, allow one type that is agreed upon to fit the business requirement;
中文:图片上传,允许一种符合业务要求的类型; - cv upload, allow
docxandpdfextensions.
中文:CV上传,允许docx和pdf扩展名。
Based on the needs of the application, ensure the least harmful and the lowest risk file types to be used.
根据应用程序的需求,确保使用危害最小和风险最低的文件类型。
Block Extensions / 阻止扩展名¶
Identify potentially harmful file types and block extensions that you regard harmful to your service.
识别可能有害的文件类型并阻止您认为对服务有害的扩展名。
Please be aware that blocking specific extensions is a weak protection method on its own. The Unrestricted File Upload vulnerability article describes how attackers may attempt to bypass such a check.
请注意,仅阻止特定扩展名是一种薄弱的保护方法。未限制文件上传漏洞文章描述了攻击者可能如何尝试绕过此类检查。
Content-Type Validation / 内容类型验证¶
The Content-Type for uploaded files is provided by the user, and as such cannot be trusted, as it is trivial to spoof. Although it should not be relied upon for security, it provides a quick check to prevent users from unintentionally uploading files with the incorrect type.
上传文件的内容类型由用户提供,因此不能信任,因为它很容易被伪造。尽管不应依赖它进行安全检查,但它提供了一种快速检查,以防止用户无意中上传类型不正确的文件。
Other than defining the extension of the uploaded file, its MIME-type can be checked for a quick protection against simple file upload attacks.
除了定义上传文件的扩展名外,还可以检查其MIME类型,以快速防止简单的文件上传攻击。
This can be done preferably in an allowlist approach; otherwise, this can be done in a denylist approach.
最好采用白名单方法来实现;否则,可以使用黑名单方法。
File Signature Validation / 文件签名验证¶
In conjunction with content-type validation, validating the file's signature can be checked and verified against the expected file that should be received.
与内容类型验证结合,可以验证文件的签名是否与预期接收的文件匹配。
This should not be used on its own, as bypassing it is pretty common and easy.
中文:这不应单独使用,因为绕过它是相当常见且容易的。
Filename Safety / 文件名安全性¶
Filenames can endanger the system in multiple ways, either by using non acceptable characters, or by using special and restricted filenames. For Windows, refer to the following MSDN guide. For a wider overview on different filesystems and how they treat files, refer to Wikipedia's Filename page.
文件名可以通过多种方式危害系统,例如使用不可接受的字符或使用特殊和受限的文件名。对于Windows,请参考以下MSDN指南。关于不同文件系统及其处理文件的方式的更广泛概述,请参考Wikipedia的文件名页面。
In order to avoid the above mentioned threat, creating a random string as a filename, such as generating a UUID/GUID, is essential. If the filename is required by the business needs, proper input validation should be done for client-side (e.g. active content that results in XSS and CSRF attacks) and back-end side (e.g. special files overwrite or creation) attack vectors. Filename length limits should be taken into consideration based on the system storing the files, as each system has its own filename length limit. If user filenames are required, consider implementing the following:
为了避免上述提到的威胁,创建一个随机字符串作为文件名,例如生成UUID/GUID,是至关重要的。如果文件名由业务需求要求,应在客户端(例如,导致XSS和CSRF攻击的主动内容)和后端(例如,特殊文件的覆盖或创建)攻击向量上进行适当的输入验证。应根据存储文件的系统考虑文件名长度限制,因为每个系统都有自己的文件名长度限制。如果需要用户文件名,请考虑实施以下措施:
- Implement a maximum length
中文:实现最大长度 - Restrict characters to an allowed subset specifically, such as alphanumeric characters, hyphen, spaces, and periods
中文:特别限制字符为允许的子集,例如字母数字字符、连字符、空格和句点- Consider telling the user what an acceptable filename is.
中文:考虑告诉用户可接受的文件名是什么 - Restrict use of leading periods (hidden files) and sequential periods (directory traversal).
中文:限制使用开头的点(隐藏文件)和连续的点(目录遍历) - Restrict the use of a leading hyphen or spaces to make it safer to use shell scripts to process files.
中文:限制使用开头的连字符或空格,以便更安全地使用shell脚本处理文件 - If this is not possible, block-list dangerous characters that could endanger the framework and system that is storing and using the files.
中文:如果这不可能,则阻止可能危害存储和使用文件的框架和系统的危险字符
- Consider telling the user what an acceptable filename is.
On Windows/NTFS, a long filename may have an 8.3 short name alias, depending on file system settings. Do not assume that an alias exists or has a particular spelling. If an overwrite or collision check validates only the long filename supplied by the user, an attacker who can predict the short alias of an existing sensitive file may reference it directly to overwrite that file, bypassing an exact-name or extension check. Generating the stored filename server-side, as recommended above, removes this risk, since the attacker no longer controls which file is targeted. Disabling short-name creation prevents new aliases; it does not remove existing aliases. Assess existing short names separately before relying on this setting: Microsoft documents removal and compatibility checks, including backup precautions before removal.
在Windows/NTFS上,长文件名可能有一个8.3短名别名,具体取决于文件系统设置。不要假设存在别名或具有特定的拼写。如果覆盖或冲突检查仅验证用户提供的长文件名,那么能够预测现有敏感文件短别名的攻击者可以直接引用它来覆盖该文件,绕过精确名称或扩展名检查。如上所述在服务器端生成存储的文件名可以消除这种风险,因为攻击者不再控制目标文件。禁用短名创建可以防止新别名;它不会删除现有别名。在依赖此设置之前,单独评估现有的短名:Microsoft文档中记录了删除和兼容性检查,包括删除前的备份预防措施
File Content Validation / 文件内容验证¶
As mentioned in the Public File Retrieval section, file content can contain malicious, inappropriate, or illegal data.
如公共文件检索部分所述,文件内容可能包含恶意、不适当或非法数据
Based on the expected type, special file content validation can be applied:
- For images, decode and re-encode to an allowed image format, explicitly removing unnecessary metadata. Rewriting does not guarantee that all malicious content is removed, and the image processor itself handles untrusted input. Use an up-to-date library with restricted formats, resource limits, and sandboxing.
中文:对于 图像,将其解码并重新编码为允许的图像格式,明确移除不必要的元数据。重写不能保证移除所有恶意内容,图像处理器本身处理不受信任的输入。使用带有限制格式、资源限制和沙箱的最新库。 - For Microsoft documents, the usage of Apache POI helps validating the uploaded documents.
中文:对于 Microsoft 文档,使用 Apache POI 有助于验证上传的文档。 - ZIP files are not recommended since they can contain all types of files, and the attack vectors pertaining to them are numerous.
The File Upload service should allow users to report illegal content, and copyright owners to report abuse.
If there are enough resources, manual file review should be conducted in a sandboxed environment before releasing the files to the public.
Adding some automation to the review could be helpful, which is a harsh process and should be well studied before its usage. Some services (e.g. Virus Total) provide APIs to scan files against well known malicious file hashes. Some frameworks can check and validate the raw content type and validating it against predefined file types, such as in ASP.NET Drawing Library. Beware of data leakage threats and information gathering by public services.
File Storage Location¶
The location where the files should be stored must be chosen based on security and business requirements. The following points are set by security priority, and are inclusive:
- Store the files on a different host, which allows for complete segregation of duties between the application serving the user, and the host handling file uploads and their storage.
- Store the files outside the webroot, where only administrative access is allowed.
中文:将文件存储在网站根目录之外,仅允许管理员访问。 - Store the files inside the webroot, and set them in write permissions only.
中文:将文件存储在网站根目录之内,并仅设置写权限。 - If read access is required, setting proper controls is a must (e.g. internal IP, authorized user, etc.)
中文:如果需要读取访问,必须设置适当的控制措施(例如内部IP、授权用户等)
Storing files in a studied manner in databases is one additional technique. This is sometimes used for automatic backup processes, non file-system attacks, and permissions issues. In return, this opens up the door to performance issues (in some cases), storage considerations for the database and its backups, and this opens up the door to SQLi attack. This is advised only when a DBA is on the team and that this process shows to be an improvement on storing them on the file-system.
以研究的方式在数据库中存储文件是另一种技术。这有时用于自动备份过程、非文件系统攻击和权限问题。作为回报,这可能会引发性能问题(在某些情况下)、数据库及其备份的存储考虑,并可能打开SQL注入攻击的大门。只有在DBA团队中且此过程显示出在文件系统上存储的改进时,才建议这样做。
Be aware that an attacker may attempt to upload a web server configuration file (e.g. .htaccess, web.config) into the upload directory. If the web server allows per-directory configuration overrides, such a file could be used to change how that directory handles file types, for example mapping an otherwise harmless extension to be executed by the server. As a second layer of defense, disable per directory configuration overrides on upload directories at the web server level (e.g. Apache AllowOverride None, locked IIS handler mappings), in addition to storing files outside the webroot as recommended above.
请注意,攻击者可能会尝试将Web服务器配置文件(例如.htaccess、web.config)上传到上传目录。如果Web服务器允许按目录配置覆盖,则此类文件可以用来更改该目录处理文件类型的方式,例如将本应无害的扩展名映射为由服务器执行。作为第二层防御,除了如上所述将文件存储在网站根目录之外,还应在Web服务器级别禁用上传目录的按目录配置覆盖(例如Apache AllowOverride None、锁定IIS处理程序映射)
Some files are emailed or processed once they are uploaded, and are not stored on the server. It is essential to conduct the security measures discussed in this sheet before doing any actions on them.
中文:一些文件在上传后会被发送电子邮件或处理,而不会存储在服务器上。在对此类文件采取任何行动之前,执行本页中讨论的安全措施是至关重要的。
User Permissions / 用户权限¶
Before any file upload service is accessed, proper validation should occur on two levels for the user uploading a file:
在访问任何文件上传服务之前,应对上传文件的用户的两个级别进行适当的验证:
- Authentication level
中文:认证级别- The user should be a registered user, or an identifiable user, in order to set restrictions and limitations for their upload capabilities
中文:用户必须是注册用户或可识别用户,以便为其上传能力设置限制和限制
- The user should be a registered user, or an identifiable user, in order to set restrictions and limitations for their upload capabilities
- Authorization level
中文:授权级别- The user should have appropriate permissions to access or modify the files
中文:用户应具有适当的权限来访问或修改文件
- The user should have appropriate permissions to access or modify the files
Filesystem Permissions / 文件系统权限¶
Set the files permissions on the principle of least privilege.
中文:根据最小权限原则设置文件权限。
Files should be stored in a way that ensures:
文件应存储的方式应确保:
- Allowed system users are the only ones capable of reading the files
中文:允许的系统用户是唯一能够读取文件的用户 - Required modes only are set for the file
中文:仅设置必需的模式对文件- If execution is required, scanning the file before running it is required as a security best practice, to ensure that no macros or hidden scripts are available.
中文:如果需要执行,则作为安全最佳实践,在运行之前扫描文件是必需的,以确保没有宏或隐藏的脚本可用。
- If execution is required, scanning the file before running it is required as a security best practice, to ensure that no macros or hidden scripts are available.
Upload and Download Limits / 上传和下载限制¶
The application should set proper size limits for the upload service in order to protect the file storage capacity. If the system is going to extract the files or process them, the file size limit should be considered after file decompression is conducted and by using secure methods to calculate zip files size. For more on this, see how to Safely extract files from ZipInputStream, Java's input stream to handle ZIP files.
为了保护文件存储容量,应用程序应为上传服务设置适当的大小限制。如果系统将要提取文件或处理它们,则应在文件解压缩后考虑文件大小限制,并使用安全方法计算zip文件的大小。有关更多信息,请参阅如何安全地从ZipInputStream提取文件,Java的输入流用于处理ZIP文件。
The application should set proper request limits as well for the download service if available to protect the server from DoS attacks.
如果可用,应用程序还应为下载服务设置适当的请求限制,以保护服务器免受DoS攻击。
Java Code Snippets / Java代码片段¶
Document Upload Protection) (文档上传保护) repository written by Dominique for certain document types in Java.
References / 参考¶
- Microsoft: Upload Files in ASP.NET Core) (Microsoft:在ASP.NET Core中上传文件)
- CWE-434: Unrestricted Upload of File with Dangerous Type) (CWE-434:不受限制的危险类型文件上传)