C# Image.FromStream 安全吗?

信息安全 。网 上传文件
2021-08-17 11:08:51

从请求中读取数据作为流后,我需要将其转换为图像,所以我使用了这个方法:

Stream inputStream = HttpContext.Current.Request.InputStream;
Image img = Image.FromStream(inputStream)

因此,虽然我无法知道该 inputStream 中的内容(文件格式已经完成,但仍然......)可能存在病毒或恶意软件,所以在这种情况下 FromStream(Stream) 会抛出 ArgumentException。因为它不是图像。

我的问题是 - 如果上传的文件包含病毒,并且该方法在尝试将流转换为图像时抛出异常:这会对服务器造成任何伤害吗?如果是这样,如何避免呢?在服务器中处理文件上传的场景应该是什么?我只是想知道我是否需要在照片上传的情况下扫描病毒。

2个回答

如果上传的文件是有效的图片格式,.FromStream即使包含病毒也不会抛出异常。也就是说,它没有病毒检查。

另一方面,病毒也无法激活,因为此时文件仅作为原始字节处理。
(如果不可行,它当然有可能包含直接针对 .NETImage类的攻击,例如通过缓冲区溢出。但是,除了极不可能存在这样的漏洞之外,更不可能有人会去定位这样一个利基载体的麻烦)。

所以,在这一点上,你是完全(实际上)安全的,但你也不知道文件是否干净。

真正的问题是,这个文件之后会发生什么?

它是否保存到磁盘并在本地使用?
在这种情况下,您应该使用某种形式的防病毒检查它,如果只是为了您的利益 - 如果您相信它们,您可以让本地 AV 引擎扫描它。

是不是后来返回给其他用户,从而可以使用你的系统进行传播?
在保存文件之前,您绝对应该进行某种形式的 AV 扫描。请注意,这可能不是那么简单,因为您可能将图像存储在数据库中(在将其保存到文件之前,API 可以为内存段激活 AV 扫描仪)......无论如何,我我坚决反对直接在您的实际系统上运行防病毒扫描。你最好有某种形式的网关 AV 扫描仪,甚至在它到达你的系统之前。


但是,考虑到当您允许随机用户上传任意文件时,病毒清除并不是您最担心的问题。

  • 一方面,您可能会被大文件或许多较小的文件淹没,从而对您的服务器进行 DoSing。
  • 如果用户可以指定保存的文件路径 - 他可能会覆盖系统文件或上传可执行代码。
  • 如果文件属性被保存并稍后显示(这包括文件名和用户名,还包括描述、文件类型、位置等) - 这可能导致其他标准 Web 攻击,例如 XSS 或 SQL 注入。
  • 在此处搜索 GIFAR - 这些文件既是有效的图像文件,也是有效的 JAR(Java 存档 - 浏览器的可执行代码)文件。这些当然不是病毒……
  • 根据系统的不同,如果您的用户上传受版权保护的图像或儿童色情等,您可能会面临法律损失的风险。当然,请咨询您的律师,因为我不是其中之一。

TL;博士

简而言之,接受任意上传确实会给您带来一团糟的潜在麻烦,而病毒扫描并不是最糟糕的。

是的,该函数受到所有已知缓冲区溢出的保护,因为 Microsoft 会为 .NET 代码库发送补丁。但这不是一个完整的解决方案。

有关更多信息,请参阅以下链接:

以下是我在接受来自不受信任来源的图像时会采用的保护措施

  • 修补服务器:Image 类是 .NET 框架的一部分,因此只要您使用受支持的框架,MSFT 就会防止缓冲区溢出。

  • 处理此类中的ArgumentException ,因为尝试上传非图像会引发异常。您可以在此例外情况下获得尝试“黑客”的早期警告。

  • 检查图像的扩展名和名称

  • 不允许用户指定目录(如果这样做,请严格控制它)

  • 根据扩展检查内容类型。

  • 对映像运行病毒检查程序(例如VirusTotal

  • 使用标头 X-Content-Type-Options : Nosniff (更多信息来保护免受 GIFR风格的攻击。

  • 不要向最终用户显示图像元数据。Exiv2等工具允许查看和编辑不受信任的数据。

  • 大小限制:包装 Stream 类并允许它切断上传大文件的尝试。如果您使用的是 ASP.NET,那么默认情况下,服务器端组件首先将所有数据保存到 RAM。通过使用直接保存到磁盘的 HTTPHandler 来避免内存耗尽 DoS。

  • 使用单独的 DNS 域来提供图像(更多信息

  • 将所有上传的图像转换为 BMP,然后转换为通用格式(PNG 等)(更多信息

  • 确保公众无法进入上述转换中转区

  • 注入带噪点的图片(更多信息