如何在IIS服务器上限制/验证文件上传文件类型

6
我希望能够在我的IIS服务器上设置文件类型的白名单,以授权用户上传文件(我使用的是IIS v7.5)。
我有哪些选择呢?例如,要将特定操作中上传的文件大小限制为5MB,我向webconfig添加了以下部分:
<location path="home/fileupload">
  <system.web>
    <!-- maxRequestLength is in kilobytes (KB) -->
    <httpRuntime maxRequestLength="5120" /> <!-- 5MB -->
  </system.web>
  <system.webServer>
    <security>
      <requestFiltering>
        <!-- maxAllowedContentLength is in bytes -->
        <requestLimits maxAllowedContentLength="5242880"/> <!-- 5MB -->
      </requestFiltering>
    </security>
  </system.webServer>
</location>

在webconfig中是否有设置允许文件类型白名单的选项?或者唯一的选择是在文件完全上传时在代码中验证文件类型?推荐使用哪种技术?如何确保.docx,.pdf,.jpg等文件确实是它们所表示的内容?


在客户端不验证它的原因是什么? - Pablo Claus
1
因为不是所有浏览器都支持此功能,而且任何情况下都应该在服务器端进行验证! - Alexandre Jobin
@AlexandreJobin,您有多确定文件确实是用户所说的那个文件? - Jared
@Jared 因为用户上传的文件将被其他人使用。对于我的需求来说,我要求的有点过头了。但是既然我必须制作一个模块来管理上传,我决定第一次就把它做好,这个模块将适用于我们所有的项目。如果将 .exe 文件重命名为 .docx 或 .zip 文件并尝试打开它,会发生什么?这可能会很危险。我不知道,所以我试图保护一切 :) - Alexandre Jobin
@AlexandreJobin 如果是这种情况,请查看我下面更新的答案。 - Jared
1
http://prideparrot.com/blog/archive/2012/8/uploading_and_returning_files - VJAI
3个回答

3

如果您想要服务器端,可以使用文件的MIME类型。

这篇文章展示了如何根据文件内容(而不是扩展名)确定MIME类型。

如果您只想限制输入为特定的文件扩展名,可以将输入名称与所需接受的名称进行简单检查。 如果通过了此检查,您可以对我链接的库进行交叉引用,以确保用户没有更改文件扩展名。

这样做会提供相当高的确定性,以确保文件是您要接受的文件!

编辑:基于迄今为止的评论.... 根据您的说法,这种方法应该非常适合您。 如果您只想将其限制为在您的某些评论中列出的文件类型,则可以对文件扩展名进行简单检查。 如果有效,则将文件传递给我链接中列出的urlmon.dll。 确保它不会返回无效类型....即可执行文件/ Java / zip等。 如果不是无效类型,则有很高的确定性它是一个安全的文件!

最后,通过阅读该帖子的评论,看起来urlmon.dll可能会隐式支持您想要的所有文件类型,这将消除检查它是否是可执行文件或类似物的需要,但您需要确认doc / docx / xsl / xslx返回有效的mime类型。

1

不,没有web.config设置来限制上传的内容。唯一可能验证上传数据的方法是在代码中实际验证该数据。

即使有设置,它也是无用的,因为它将基于从客户端接收到的Content-Type标头,这可能是非常错误的。

在代码中,您当然可以查看Content-Type标头,但如果您要验证上传的数据是否为特定类型,则必须根据您期望的数据类型手动进行验证。对于图像,这很容易。对于其他文件类型,可能会更加困难。


那么您验证文件的技巧是什么?您知道一个好的库可以验证文件的真实类型吗? - Alexandre Jobin
这取决于文件。没有一种神奇的解决方案可以验证所有类型的文件。你想处理什么类型的文件? - dodexahedron
对于我的实际项目,我需要验证PDF、DOC、DOCX、XLS、XLSX和图像文件。我不会有任何视频或音频,只有可打印的文档。 - Alexandre Jobin
任何文件类型都可以通过尝试将其解析为给定的文件类型,然后处理异常来进行验证。 图像可以通过前几个字节进行验证,在这里已经有答案了。以下是一些示例:https://dev59.com/dnVC5IYBdhLWcg3wsTbv - dodexahedron
这不是唯一的方法...但其中一种方法非常复杂,我刚写了一个并计划很快发布博客...但基本上你需要编写一个C++本地模块并订阅OnAcquireRequestState(本地而不是.Net)。然后检查HttpMethod是否为post。然后使用HttpRequest :: ReadEntityBody将post数据逐块加载到完整的块缓冲区中。块计数在HttpRawRequest中...然后使用Mime Type解析器解析文件名的post数据。如果有错误文件,则返回请求完成并设置错误响应...还有更多内容。 - Ryan Mann
幸运的是,如果您的应用程序池支持CLR,并且您所针对的所有内容都支持CLR,则可以使用具有混合模式CLR支持的C++本机DLL...因此,您可以使用System.Net.Formatting进行Mime解析,并使事情变得更加容易。您的应用程序池都需要运行CLR 4。然后使用preCondition = bitness32或bitness64和runtimeVersionv4.0。 - Ryan Mann

0

数据注释是您正在寻找的内容,这里有一个可能会帮助您的搜索,谷歌数据注释

更新

我认为它是通过文件扩展名进行验证的。如果您不想依赖于文件扩展名,那么我认为最好的选择是根据MIME类型进行验证。这更加复杂,并且因浏览器而异,可以被伪造(虽然这比伪造扩展名更复杂。)

一个简单但不免费的选择是使用Telerik RadAsyncUpload

您可以自己编写此代码(尽管我从未尝试过),this可能会帮助您入门。(本文涉及到没有IIS无法可靠检测MIME类型的事实,但它应该能让您开始。)

希望这能帮到你。正如你所知,你可以通过文件大小限制、验证文件扩展名来限制文件,如果你添加了 MIME 类型的验证,我认为你已经尽力了。我认为这是你可以做的所有安全措施,以避免排除有效文件;虽然我听说过对文件进行哈希处理和其他选项,但这些肯定会排除合法文件。

另外,正如我提到的,MIME 类型可能是伪造的并发送到你的服务器,为了更加安全,你应该在客户端和服务器端都进行验证。


数据注释会检查文件的有效性还是只检查文件扩展名? - Jared
RadAsyncUpload将基于文件扩展名进行过滤,因此这是我可以在服务器端和客户端轻松完成的操作。我正在使用他们控件的MVC版本 :) - Alexandre Jobin
@AlexandreJobin 我相信也有根据 MIME 类型进行过滤的能力。不过我认为这是在更高的价格点上。 - Garrett Fogerlie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接