如何在AWS S3 Bucket中生成仅可读、不可覆盖对象的PresignedUrl
你当前的预签名URL生成代码本身配置没有问题,出现GET类型预签名URL可被用于覆盖对象的问题,可按以下步骤排查修复:
1. 排查S3桶的公共访问配置
如果你的存储桶开启了公共写权限,或者对应对象前缀的匿名访问允许 s3:PutObject操作,那么用户不需要用到你生成的预签名URL,直接对同一个Key发起PUT请求就能覆盖对象,容易被误判为是预签名URL被滥用。
修复方式:
- 进入S3控制台对应桶的「权限」选项卡,确认阻止公共访问的四个配置全部开启
- 检查桶策略,确保没有允许
Principal: "*"对应s3:PutObject类操作的规则
2. 限制生成预签名URL所用IAM身份的权限
预签名URL的权限范围完全继承生成它的IAM用户/角色的权限:如果你的IAM身份本身就拥有对应桶、对应Key前缀的s3:PutObject权限,即使你生成URL时指定了Verb为GET,攻击者仍可篡改请求方法为PUT,只要请求时间在有效期内,S3就会校验通过执行覆盖操作。
修复方式:
- 单独创建一个仅用于生成只读预签名URL的IAM角色/用户,给它绑定最小权限策略,仅放开
s3:GetObject权限,禁止所有写类权限(s3:PutObject/s3:DeleteObject等),示例策略如下:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::你的桶名/*" } ] }
- 生成预签名URL时统一使用这个仅拥有读权限的IAM身份,就算攻击者篡改请求方法,因为签名身份本身没有写权限,S3也会直接拒绝请求。
3. 确认签名参数与SDK版本正确性
- 确认你使用的AWS .NET SDK是官方正式维护的版本,避免旧版本存在的签名未绑定请求方法的漏洞
- 不要在生成预签名URL的逻辑中额外兼容PUT类请求的参数,避免签名时意外包含写操作的授权
4. 额外防护配置(可选)
如果需要更高的安全性,可以额外加以下配置:
- 开启S3桶的版本控制功能,就算对象被意外覆盖,也可以通过历史版本恢复
- 配置S3对象锁,对需要长期保留的图片设置不可覆盖、不可删除的保留周期
- 在桶策略中添加条件,限制非指定IP、非指定UserAgent的PUT请求
内容的提问来源于stack exchange,提问作者Quân Đỗ
相关产品推荐
相关产品推荐

