我正在构建一个允许用户上传文件的门户。我需要确保这些文件不包含病毒。我理想的解决方案是让主机 OS AV 监视临时文件夹并扫描任何传入的文件。
在 ASP.Net 2 中上传文件时,它是写入临时文件夹中的磁盘,还是保留在内存中?如果写入磁盘,IIS 会锁定它以使 AV 无法删除它吗?如果它被写入磁盘,在哪里?
我正在构建一个允许用户上传文件的门户。我需要确保这些文件不包含病毒。我理想的解决方案是让主机 OS AV 监视临时文件夹并扫描任何传入的文件。
在 ASP.Net 2 中上传文件时,它是写入临时文件夹中的磁盘,还是保留在内存中?如果写入磁盘,IIS 会锁定它以使 AV 无法删除它吗?如果它被写入磁盘,在哪里?
这是 ASP.NET 如何处理文件的实际问题。它取决于版本,但 2.0 和所有后续版本都会在您有机会处理它们之前将上传内容写入磁盘。上面的答案实际上是错误的——2.0 以上的 ASP.NET会将文件写入磁盘。如果您考虑一下,将上传文件加载到内存中会给您带来 DDOS 漏洞,因为大文件会占用越来越多的服务器内存。按版本,这是 ASP.NET 的行为方式:
ASP.NET 1.0 和 1.1 将整个请求加载到内存中,然后您才能访问它。这意味着大文件可能会填满所有内存,导致异常并以其他方式关闭服务器。
ASP.NET 2.0 引入了一种用于上传的磁盘缓存方案,在客户端代码可以处理之前再次捕获并处理它。可以按如下方式访问临时文件夹:
string uploadFolder = Path.Combine(HttpRuntime.CodegenDirInternal, "uploads");
从 ASP.NET 4.0 开始,上面引用的属性名称是 HttpRuntime.CodegenDir:
string uploadFolder = Path.Combine(HttpRuntime.CodegenDir, "uploads");
至少现在它已缓存到磁盘,因此您不会遇到 1.0 和 1.1 的内存问题,但在完全检索之前您仍然无法访问它。
我认为理想的方法是拥有一个“传入”文件夹,该文件夹已被授予 ASP.NET 保存文件的必要权限。我从未遇到过即使在调用SaveAs
FileUpload 控件后文件仍处于锁定状态的情况。
请注意,FileUpload 控件在您调用之前不会上传文件SaveAs
,这是文件被持久保存到服务器上的磁盘的时间。它似乎将所有文件内容保存在一个中,在调用该方法HttpInputStream
时将其写入磁盘。SaveAs
然后,您的 AV 应用程序应该可以自由扫描文件。如果出现错误,您可以向用户提供相关反馈。
您使用的是 ASP FileUpload 服务器控件吗?
如果是这样,它将被加载到服务器内存中,直到您对其进行处理。
这是来自 MSDN;
保存上传文件的位置没有固有限制。但是,要保存文件,ASP.NET 进程必须有权在您指定的位置创建文件。此外,您的应用程序可能配置为需要绝对路径(而不是相对路径)来保存文件,这是一种安全措施。
如果您对安全性很认真,另一个相关提示是确保您保存文件的文件夹位于 webroot 之上,这样用户就不能以任何方式直接访问它。您仍然可以让他们通过一些数据库工作删除他们上传的文件,即保存位置并确保每个文件都是唯一命名的(如果用户正在验证,我只需将文件名保存为 USERNAME.XYZ 其中 XYZ 是文件的扩展名.
对于您的场景...我通常对任何上传/临时位置都有一个应用程序设置,默认设置在 ~/App_Data/Uploads/ 下,直到字节被持久保存到磁盘之前它对 AV 不可见。如果您真的想要主动扫描,那么您可能希望有一个多阶段队列......(另外,您将希望在 ASP.Net 中执行异步请求),如果您等待任何扫描完成。
我会考虑使用您的本机扫描程序将您的上传路径列入白名单,并查看是否有公开的 API 可根据请求运行手动扫描。另一种方法是使用 ClamAV/ClamWin 设置作为服务扫描程序,您可以每小时在其上运行更新(我已经为邮件系统完成了此操作),并且文件签名往往相当不错,即使在存档文件中也是如此(如果配置正确)。
此外,您可能希望使用 7z.exe(7-zip 命令行)来提取任何档案。7-zip 几乎可以提取我见过的所有档案类型,尽管它只支持新档案的几个压缩目标。
希望这会有所帮助,因为我打算将此作为评论附加到另一篇文章中,但它变得冗长。
就像 Cerebrus 一样,我会告诉您 UploadFile 控件不会向磁盘驱动器写入任何内容,除非您告诉它这样做。