首页 程序笔记 Web应用安全之八种安全的文件上传方式

Web应用安全之八种安全的文件上传方式

为了让最终用户将文件上传到您的网站,就像是给危及您的服务器的恶意用户打开了另一扇门。即便如此,在今天的现代互联网的Web应用程序,它是一种常见的要求,因为它有助于提高您的业务效率。在Facebook和Twitter等社交网络的Web应用程序,允许文件上传。也让他们在博客,论坛,电子银行网站,YouTube和企业支持门户,给机会给最终用户与企业员工有效地共享文件。允许用户上传图片,视频,头像和许多其他类型的文件。

 

Web应用安全之八种安全的文件上传方式

 

向最终用户提供的功能越多,Web应用受到攻击的风险和机会就越大,这种功能会被恶意用户利用,获得到一个特定网站的权限,或危及服务器的可能性是非常高的。

 

当在测试几个Web应用程序时,我们注意到,相当多的知名Web应用程序,不具备安全的文件上传形式。这些漏洞很容易被利用,我们可以访问这些Web应用程序的服务器托管到文件系统。在这篇文章中,我们为您介绍8种常见的方式,我们遇到过的安全文件上传表单。同时,还将展示一个恶意的用户,可以轻松地绕过这些安全措施。

 

案例1:没有任何验证的简单文件上传表单

 

一个简单的文件上传表单通常包含一个HTML表单和PHP脚本。HTML表单的形式呈现给用户,而需要文件上传功能的PHP脚本中包含的代码。这种形式和PHP脚本下面是一个例子:

 

HTML Form:

 

view source  

<form enctype="multipart/form-data" action="uploader.php" method="POST"> 

<input type="hidden" name="MAX_FILE_SIZE" value="100000" /> 

Choose a file to upload: <input name="uploadedfile" type="file" /><br /> 

<input type="submit" value="Upload File" /> 

</form> 

PHP Code:

 

<?php  

$target_path  =  "uploads/";  

$target_path  =  $target_path  .  basename($_FILES['uploadedfile']['name']);  

if (move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {  

echo "The file " . basename($_FILES['uploadedfile']['name']) . " has been uploaded";  

echo "There was an error uploading the file, please try again!";  

} else {  

}  

?> 

当PHP接收POST请求且编码类型是multipart/form-data,它会创建一个临时文件名随机的临时目录中(例如/ var/tmp/php6yXOVs)。 PHP也将填充全局数组$_FILES上传的文件的信息:

 

$ _FILES ['UploadedFile的'] ['名称']:在客户机上的文件的原始名称  

$ _FILES ['UploadedFile的'] ['类型']:文件的MIME类型  

$ _FILES ['UploadedFile的'] ['大小']:文件的大小(以字节为单位)  

$_FILES ['UploadedFile的']['不对tmp_name']:上传的文件存储在服务器上的临时文件名。 

PHP 函数move_uploaded_file将用户提供的临时文件移动到一个位置。在这种情况下,目的地是服务器根目录以下。因此,文件可以使 用的URL,如:http://www.domain.tld/uploads/uploadedfile.ext访问。在这个简单的例子中,有允许上传 的文件类型没有限制,因此攻击者可以上传一个PHP或NET带有恶意代码的文件,可导致服务器妥协。

 

这可能看起来像很幼稚的例子,但我们在一些Web应用中没有遇到这样的代码。

 

案例2:Mime类型验证

 

另 一个常见的错误Web开发人员确保文件上传表单时,只检查从PHP返回mime类型。当一个文件被上传到服务器,PHP将设置变 量$_FILES['UploadedFile']['type']所提供的Web浏览器客户端使用的MIME类型。然而,文件上传表单验证不能依赖于这 个值。恶意用户可以轻松地使用脚本或其他一些自动化的应用程序,允许发送HTTP POST请求,这让他送一个假的mime类型的文件上传。

 

案例3:限制危险的拓展

 

在另一个例子里,我们遇到了文件上传使用黑名单的做法,作为一项安全措施。从开发者收集制定的危险列表,如果正在上传的文件包含在列表中,访问会被拒绝。

 

使用危险的文件扩展名,其主要缺点之一是,它几乎不可能编制一份完整的清单,包括攻击者可以使用的所有可能的扩展名。例如如果代码运行在托管环境中,通常这样的环境让大量的脚本语言,如Perl,Python和Ruby等,列表可以是无穷无尽的。

 

恶意用户可以很容易地绕过该检查上传一个文件名为“.htaccess”,其中包含类似于下面的一行代码:

 

AddType application/x-httpd-php .jpg

 

上 面的代码行,指示ApacheWeb服务器执行jpg图片,好像他们是PHP脚本。攻击者现在可以上传一个jpg扩展名的文件,其中包含PHP代码。正如 下面的截图,通过web浏览器请求一个jpg文件,其中包含PHP的命令phpinfo()函数,它仍然是从Web服务器执行。

 

案例4: 双扩展名 (第1部分)

 

本案例中使用的安全策略和案例3中所使用的非常相近. 尽管方式换成了简单的检查文件名具有的扩展名, 开发者通过在文件名中查找 ‘.’ 字符并提取点号之后的字符串来得到文件扩展名.

 

绕过该途径的方法有点儿复杂, 但是仍然是现实的. 首先, 让我们看看 Apache 是怎么处理具有多重扩展名的文件的. Apache 手册中有如下一段陈述:

 

“文 件可以有多个扩展名, 这些扩展名的顺序一般情况下是无关紧要的.例如: 如果文件 welcome.html.fr 被映射为内容类型是 text/html ,语言是法语的话, 文件welcome.fr.html 将被映射为完全相同的内容. 如果一个以上的扩展名映射到同种类型的元信息上, 那么将使用最右边的那个, 除了语言和内容编码. 比如: .gif 的MIME类型是 image/gif , .html 的 MIME 类型是 text/html , 那么 welcome.gif.html 的MIME类型将是text/html .”

 

因此一个名为 ‘filename.php.123’ 的文件将会被解释为一个PHP文件并被执行.这仅限于最后的那个扩展名(本例中是 .123)没有在web服务器的 mime-types列表中被指定.web开发者通常不会意识到Apache还存在这么一个 ‘特性’, 出于某些原因来说这可能非常危险.知道了这个以后,一个攻击者可以上传一个名为 shell.php.123 的文件并绕过文件上传保护机制.后台脚本将会计算出最后的扩展名(.123)并作出该扩展名并不在危险的扩展名列表内的结论.话虽如此,想要预防某恶意用 户可能会使用的所有随机扩展名来上传一个文件到你的web服务器上是不可能的.

 

案例5: 双扩展名 (第2部分)

 

一个更好的增强文件上传表单的安全性的途径就是白名单机制. 在本例中, 开发者定义了一个 已知/可接受 的扩展名列表并且不允许使用未在名单中指定的扩展名.

 

然 而, 在某些情况下该途径不会像期待的方式那样工作. 当 Apache 被配置为执行 PHP 代码的时候, 存在两种方式来实现该机制: 使用 AddHandler 指令, 或者使用 AddType 指令. 如果 AddHandler 指令被使用, 所有包含 ‘.php’ 扩展名的文件名(例如: ‘.php’ , ‘.php.jpg’)均被作为 PHP 脚本来执行. 因此, 如果你的 Apache 配置文件包含如下一行的话, 你可能很容易受到攻击:

 

AddHandler php5-script .php

 

一个攻击者可以上传名为 ‘filename.php.jpg’ 的文件并绕过保护机制, 然后执行其中的代码.

 

案例 6: 检查图片头部

 

当 仅允许上传图片的时候, 开发者通常使用 PHP 的 getimagesize 函数来检测图片的头部信息. 该函数在被调用时将会返回图片的尺寸, 如果图片经验证为无效的, 也就是说图片头部信息不正确, 则会返回 false 值. 因此一个开发者一般会检查该函数是否返回 true 或 false, 并且通过该信息来验证上传的文件. 所以, 如果一个恶意用户试着上传一个内嵌有简单 PH

4

站心网

为了让最终用户将文件上传到您的网站,就像是给危及您的服务器的恶意用户打开了另一扇门。即便如此,在今..

为您推荐

JavaScript 六种继承方式

继承是面向对象编程中又一非常重要的概念,JavaScript支持实现继承,不支持接口继承,实现继承主要依靠原型链来实现的。原型链首先得要明白什么是原型链,在一篇文章看懂proto和prototype的关系及区别中讲得非常详细..

HTML5的5大存储方式总结

总体情况h5之前,存储主要是用cookies。cookies缺点有在请求头上带着数据,大小是4k之内。主Domain污染。主要应用:购物车、客户登录对于IE浏览器有UserData,大小是64k,只有IE浏览器支持。目标解决4k的大小问题解决..

传统线程技术中创建线程的两种方式

传统的线程技术中有两种创建线程的方式:一是继承Thread类,并重写run()方法;二是实现Runnable接口,覆盖接口中的run()方法,并把Runnable接口的实现扔给Thread。这两种方式大部分人可能都知道,但是为什么这样玩就..

累死你的不是工作,而是工作方式

《浪潮之巅》的作者吴军,在《得到》专栏里,提及了Google刚进中国时候的一件事。刚开始,Google总部对中国研发团队的评价非常低,因为“出工不出活儿”,北京的三四个工程师都抵不上Google总部的一个工程师。后来吴..

.NET 主程序的.dll.config文件有什么用?

.dll.config 文件通常是在开发过程中自动生成的,它的主要作用是为某个类库(.dll 文件)提供一个独立的配置文件,以便开发者可以为该类库单独定义或测试配置项。以下是生成 .dll.config 文件的原因和机制:1. 配置..

.NET C#连接FTP实现文件上传下载

在 .NET 中可以使用 System.Net.FtpWebRequest 类来连接 FTP 服务器,实现文件上传和下载。以下是实现文件上传和下载的完整代码示例。1. 上传文件到 FTP 服务器using System;using System.IO;using System.Net;class..

.net 通过 HttpClient 下载文件同时报告进度的方法

通过 HttpClient 的 ContentLength 很多时候都可以拿到下载的内容的长度,通过 ReadAsync 可以返回当前读到的长度,将读取到的长度加起来就是已经下载的长度看起来很简单,于是直接给代码private static async Task ..

C#中的线程安全的集合ConcurrentQueue使用示例

在多线程编程中,如何安全地在不同线程之间共享数据是一个非常重要的问题。C# 为我们提供了一些专门设计的线程安全集合,其中之一就是 ConcurrentQueue<T>。它是一种先进先出(FIFO)的数据结构,专门为多线程环境设..

关于SQL优化的几种方式

1、对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。2、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:select id fr..

ASP.NET如何将Views文件夹从项目分离

将 Views 文件夹从 ASP.NET 项目中分离是一个常见需求,比如为了实现模块化或分层架构。以下是实现此功能的完整步骤,从项目中分离 Views 文件夹,将其移到另一个独立的文件夹或项目中,并确保视图渲染仍然正常。1. ..

.NET C# 读取编辑.AVIF图片文件

在 .NET 中读取和编辑 .AVIF 图片文件需要特定的库支持,因为 System.Drawing 等内置功能不直接支持 AVIF 格式。目前可以通过以下方式在 .NET 中实现对 AVIF 文件的读取和编辑:方法一:使用 ImageMagick 的 .NET 封..

.NET C# SkiaSharp读取.AVIF图片文件报错

SkiaSharp 目前对 .AVIF 格式的支持可能依赖于具体的版本和底层库的配置。如果在使用 SkiaSharp 时尝试读取 .AVIF 文件报错,以下是一些可能的原因和解决方案:1. 检查 SkiaSharp 的版本SkiaSharp 的支持功能取决于..

无法加载文件或程序集 'XXXXX' 或其依赖项。访问被拒绝

遇到 “无法加载文件或程序集 'XXXXX' 或其依赖项。访问被拒绝” 错误时,通常是由于权限问题或文件夹、程序集引用配置不当所引起。下面是一些常见的原因及解决方法:1. 文件或程序集权限问题如果服务器或..

如何优化ASP.NET Core应用的性能?

优化ASP.NET Core应用性能需要从代码、数据库、配置、服务器和部署等多个层面进行综合考虑。以下是一些优化ASP.NET Core应用性能的关键方法和技巧:1. 代码级优化使用异步编程:避免阻塞线程,通过async和await处理I..

在Docker、Kubernetes环境下部署.NET应用的最佳实践

在 Docker 和 Kubernetes 环境中部署 .NET 应用是现代云原生开发的重要实践之一。以下是一些经过验证的最佳实践,涵盖 Docker 镜像优化、Kubernetes 部署配置和整体架构建议。1. Docker 镜像构建的最佳实践1.1 使用..

微软 .NET 9 正式发布!专为云原生和生成式 AI 应用设计

微软正式发布了 .NET 9,这是一次重大的版本更新。微软在 .NET 9 中带来了一系列新特性和改进,主要聚焦在性能优化、云原生支持、AI集成以及开发者体验的提升。以下是一些重要的更新亮点:性能改进:在 .NET 9 中,..

用Blazor开发App应用可行吗?

使用 Blazor 开发 App 应用是可行的,并且已成为跨平台应用开发的一种强大选择,特别适合在 Web、移动端(iOS、Android) 和 桌面端 上创建应用。Blazor 是一个支持使用 C# 和 .NET 的框架,开发者可以编写一套代码..

什么是.NET渐进式Web应用(PWA)

.NET 渐进式 Web 应用(PWA,Progressive Web Apps)是一种结合了 Web 应用的跨平台性和本地应用体验的应用程序。通过 PWA 技术,.NET 开发者可以使用 Blazor 和 WebAssembly 创建 Web 应用,支持在各种设备和操作系..

文件上传JavaScript库FilePond使用教程

传统的文件上传控件往往显得笨拙且不够用户友好。FilePond的出现,为Web文件上传带来了革命性的改变。本文将详细介绍FilePond这一JavaScript库,探讨它如何优化文件上传流程,并提供无与伦比的用户体验。什么是FileP..

什么是.NET云原生应用程序?

.NET云原生应用程序是基于.NET技术栈构建的,专为云环境设计、部署和运行的应用程序。.NET云原生应用程序不仅充分利用云计算的优势,如弹性、可伸缩性和高可用性,还能通过现代云原生技术如容器化、微服务架构和自动..

发表回复

返回顶部