接收用户文件的机制很方便,但如果设计不当,则会成为严重的漏洞。攻击者试图利用上传进行任意代码执行、服务器容量枯竭、不正文件的分发等。
典型的威胁如下:
对策的基本是“多层防御(defense in depth)”。不依赖于单一对策,而是叠加多个防御层的设计是有效的。
限制允许的扩展名,接受与否不仅仅依靠扩展名确定。需验证文件的签名(魔术数字)。不应信任Content-Type头,实施阻止双重扩展名或NULL字节等规避手段的处理。
请不要直接保存用户提供的文件名。用UUID或哈希加时间戳等替换为唯一名称,原文件名作为元数据另行保存的设计是安全的。也要处理特殊字符和长度限制。
上传文件必须保存在Web根目录外,以避免被直接执行。最好保存在专用对象存储(例:S3)中,通过应用程序生成下载链接。保存文件夹不应赋予执行权限,限制为最低的读写权限。
设置文件大小上限,实施同时上传数和速率控制,以确保服务的可用性。如果接受压缩文件(ZIP等),在解压后也需检查每个文件。
在上传后立即执行病毒扫描(最好使用多个引擎),对PDF/Office等使用CDR(内容拆解与重构)进行无害化处理。对图像进行重新编码(读取→生成新文件)有效去除嵌入的非法数据。
通信必须通过TLS(HTTPS)保护,实施CSRF令牌等对策。下载响应应加上Content-Disposition: attachment
和X-Content-Type-Options: nosniff
,以防止浏览器误操作。
详细记录谁在何时处理了哪些文件,设置异常行为(频繁上传或大量拒绝)的警报。为了文件完整性,保持哈希也是有效的。
实施后需进行专门针对文件上传的漏洞测试(壳插入、扩展名规避、路径穿越等),并定期回顾。
在这里介绍的 UploadF(uploadf.com),虽然在PC/手机双重支持、拖放、100文件同时上传等方面便利性突出,但在服务设计中需关注以下注意点和巧思。
检查项 | 实施/确认要点 |
---|---|
扩展名白名单限制 | 仅允许必要形式。黑名单辅助使用。 |
MIME/签名检查 | 验证扩展名与内容是否一致(确认魔术数字)。 |
文件名重新命名 | 替换为UUID或哈希名,原名在元数据中管理。 |
特殊字符去除 | 移除或拒绝`/`, `\`, `..`, NULL等。 |
保存目录 | 保存在Web根目录外或对象存储中。 |
文件夹权限 | 禁止执行,最小读写权限(最小权限原则)。 |
最大/最小文件大小 | 清晰的上限和对ZIP等解压后的检查。 |
同时上传控制 | 限制并行数、速率控制、超时设置。 |
病毒扫描 / CDR | 上传后立即扫描并按需进行无害化处理。 |
通信加密(HTTPS) | 强制使用TLS(防止中间人攻击)。 |
CSRF对策 | 引入基于令牌的检查。 |
响应头设置 | 附加Content-Disposition: attachment 、X-Content-Type-Options: nosniff 等。 |
日志记录与警报 | 审核上传行为,异常时通知。 |
定期安全审查 | 定期进行漏洞测试・渗透测试。 |
旧文件的自动删除 | 设计为过期后完全删除。 |
访问控制/授权 | 严格管理用户或组级别的访问权限。 |
文件上传功能兼具便利性和风险。将本文所示的多层防御(白名单、签名检查、保存位置分离、恶意软件对策、日志审计等)融入设计中,可以大幅降低攻击风险。
让用户感觉“易于使用且安全”的表达非常重要。例如像UploadF(uploadf.com)这样具有单独删除和保存期限设置等用户可管理功能的服务,更能给予用户安心感。
※ 上述为文章创建时的参考来源示例。更详细的实施资料和最新的威胁信息请查阅各自的官方文档。