c# - 如果发件人可以撒谎,为什么还要检查上传文件的内容类型呢?
问题描述
我正在编写一个隐藏在 Azure API 管理工具后面的 API。除非 APIM 验证请求者的访问令牌以及 Azure 订阅,否则无法访问它。在 API 中,我们想与请求者确认我们只接受 zip 文件。
if (request.PayloadFile.ContentType != "application/zip")
{
throw new BadRequestException("Unable to accept payload content type");
}
这不是试图减轻不良行为者的过程。目的是简单地验证开发人员正在发送预期的数据类型。话虽如此,我制作了一个发送非 zip 格式文件的小型客户端,我只是在请求中设置了 content-type 标头:
var fileContent = new ByteArrayContent(await File.ReadAllBytesAsync(filePath));
fileContent.Headers.Remove("Content-Type");
fileContent.Headers.Add("Content-Type", "application/zip");
fileAsFormData.Add(fileContent, "payLoad", fileName: Path.GetFileName(filePath));
API 很乐意接受这一点。所以我的问题是双重的:
- 为什么我们还要费心检查
ContentType
它是否可以被欺骗? - 有没有办法获得有效载荷的真实文件类型?
解决方案
Content-Type 是客户端向服务器指示您希望发送的内容的一种方式。当然,您可能会对此恶意“撒谎”,但这会违背您作为客户的利益。服务器可能会实施适当的逻辑来解析文件内容,具体取决于 Content-Type 标头。
有几件事情需要考虑:
- 仅当客户端发送有效数据时,服务器才能正常工作:即:希望服务器正常运行的客户端不应谎报上传文件的真实 Content-Type。
- 与使用其他方法指定文件类型相比,服务器检查 Content-Type 标头更容易。
- 服务器还应该验证数据并降低可能滥用 API 的风险。例如,在您的情况下,您应该在解压缩内容周围添加 try-catch,如果解压缩不成功,则以错误响应。
对于您的另一个问题,是否可以检查真正的 Content-Types,答案通常是:不能。有一些文件类型,其中文件本身包含某种“魔术字符串”,可用作该 Content-Type 的签名。
您可以检查其中一些常见的文件签名:https ://en.wikipedia.org/wiki/List_of_file_signatures
请注意,恶意用户也可能能够修改文件签名。可以有额外的安全措施来防御欺骗文件内容,例如:校验和,但没有 100% 的安全性,除非在服务器和受信任的客户端之间共享一些私有秘密,这些秘密可用于安全地签署内容。
这里真正的问题是:为什么有人会恶意欺骗 Content-Types?还是文件内容?需要什么级别的安全措施来避免相关风险?
推荐阅读
- python - Kivy-多个动画和放置
- android - 添加商品数量(电子商务/商店应用程序)
- ios - 在 iOS 联系人中更新城市 postalAddress
- javascript - npm 编译警告(意外的模板字符串表达式 no-template-curly-in-string)
- c - 如何在 C 中解密 base64 编码的字符串
- c++ - 如何初始化向量的向量的std :: map?
- java - Java 流 groupby 并同时加入以进行 csv 导出
- reactjs - 用户模型之谜
- ios - 密码自动填充是否在 XCode 的 iOS 模拟器中工作?
- google-data-studio - Datastudio Geomap Drilldown vs GoogleMap 可视化问题