文件上传功能怎么安全实现提示词(类型校验、大小限制、存储与访问控制、防路径穿越,防御向自查)
要实现头像上传、附件上传、批量导入这类功能,或者审查现有上传接口是否安全时用:AI 按防御清单逐项检查和实现:只信任服务端识别的文件类型、限制大小与数量、重命名并存到不可执行的位置、下载时校验权限,给出完整的接口代码。
通用大模型 对话模型通用
你是一名注重安全的后端工程师。请帮我实现(或审查)一个文件上传功能,目标是防御常见的上传风险。本任务只用于加固自己的系统。 - 上传场景:[上传场景](例:用户上传头像、工单附件、Excel 批量导入) - 允许的文件类型与大小:[类型与大小](例:jpg、png,最大 5MB) - 技术栈:[技术栈](例:Node.js + Express) - 存储位置:[存储位置](例:本地磁盘、对象存储) - 谁能访问上传后的文件:[访问范围](例:仅上传者本人和管理员) - 现有代码(审查时填写): [粘贴代码] 逐项实现或检查: 1. 大小与数量:在网关和应用两层限制请求体大小;限制单次上传的文件数;流式处理,避免把整个大文件读进内存。 2. 类型校验: - 用白名单而不是黑名单; - 不信任客户端声明的类型和文件扩展名,根据文件内容的特征识别真实类型; - 图片可以重新解码并重新编码,去除附带的元数据和隐藏内容; - 压缩包、表格、文档类文件的额外风险(如解压炸弹、宏、公式注入),以及对应的处理方式。 3. 文件名与路径:服务端生成随机文件名,不使用用户提供的文件名拼接路径;原始文件名只作为元数据保存,显示时转义;防止路径穿越。 4. 存储:存放在不会被当作脚本执行的位置,最好与应用代码分离(对象存储或独立目录);不要放在网站根目录下可以直接执行的位置。 5. 访问控制:下载时校验当前用户是否有权访问;私有文件使用短期有效的签名链接;响应时设置正确的内容类型和「作为附件下载」的头,防止在浏览器中被当作网页执行。 6. 其他:需要时对文件做病毒扫描(如 ClamAV);记录上传日志;限制上传频率;定期清理未被引用的文件。 输出:风险检查表(项目 | 当前是否满足 | 风险 | 建议)、完整的上传与下载接口代码(中文注释)、测试用例清单(例如伪造扩展名的文件、超大文件、含路径字符的文件名、越权下载)。 另外说明:前端预检查只为体验,服务端校验才算数;对象存储的桶默认设为私有,禁止列出目录。
高亮处换成你自己的内容:[上传场景]、[类型与大小]、[技术栈]、[存储位置]、[访问范围]、[粘贴代码]
ChatGPT Plus 充值
已被复制 0 次
使用说明
怎么填变量:[允许的文件类型与大小] 越严格越安全,只开放业务真正需要的类型。[谁能访问上传后的文件] 决定了是否需要签名链接和下载权限校验,用户私人附件绝不能用可以被猜到的公开地址。
常见坑:
- 只检查文件扩展名或浏览器传来的类型字段,攻击者改个名字就能绕过。要根据文件内容识别类型。
- 直接用用户上传的文件名保存,文件名里带上级目录符号,就可能写到预期目录之外。
- 上传的文件可以通过固定规律的地址直接访问,任何人都能遍历下载别人的附件。
追问技巧:追问「Excel 批量导入时,如何防止单元格中的公式在别人打开导出文件时被执行」,或「改为前端直传对象存储时,服务端还需要做哪些校验」。
示例输出
示例,仅供参考(Node.js,节选)
| 项目 | 当前 | 风险 | 建议 |
|---|---|---|---|
| 类型校验 | 只检查扩展名 | 伪造扩展名上传任意文件 | 读取文件头识别真实类型,只允许 jpg、png |
| 文件名 | 使用原始文件名 | 路径穿越、覆盖其他文件 | 服务端生成随机文件名 |
| 访问控制 | 公开固定地址 | 越权下载 | 下载接口校验归属,或使用短期签名链接 |
js
const ALLOWED = new Map([['image/jpeg', 'jpg'], ['image/png', 'png']])
async function saveUpload(buffer, userId) {
const type = await fileTypeFromBuffer(buffer) // 根据文件内容识别类型
if (!type || !ALLOWED.has(type.mime)) throw new BadRequest('只支持 JPG、PNG 图片')
const name = `${crypto.randomUUID()}.${ALLOWED.get(type.mime)}` // 不使用用户提供的文件名
const clean = await sharp(buffer).rotate().toBuffer() // 重新编码,去除附带的元数据
await storage.put(`avatars/${userId}/${name}`, clean, { contentType: type.mime })
return name
}同款作品
用这条提示词做出来的作品;原作者会因此获得积分
还没有同款,来做第一个。


0 条评论
还没有评论,来抢沙发~