对象存储中,上传文件都是以对象形式存储在云端,既不会存在可执行文件,又不会因为同站文件存在XSS,所以现在的大趋势下都是将自己所有的静态文件(图片、js、视频等)搬迁至对象存储上,以为就肯定安全了,殊不知搬迁到文件存储上以后,不安全的配置,也会带来很多的安全问题。
基本概念
对象存储作为分布式存储服务,最主要为用户提供了文件上传、文件下载、文件管理(处理)等操作接口,国内常见的几家云厂商的对象存储文档列举如下:
腾讯COS https://cloud.tencent.com/document/product/436/7751阿里OSS https://help.aliyun.com/document_detail/31947.html百度BOS https://cloud.baidu.com/doc/BOS/index.html华为OBS https://support.huaweicloud.com/api-obs/zh-cn_topic_0031051947.html
一般来说,云厂商会提供类似
的类AWS s3 签名URL形式提供下载、上传、管理API,具体参数意义如下:
上传时的安全问题
在对象存储的SDK中,一般都会存在javascript的SDK,也就是支持用户前端上传的
一般来说,在安全的配置下,前端上传会使用子用户、或者临时密钥(STS token)的方式来进行,但是由于某些不怕死的开发,前端js文件、APK文件硬编码AK / SK的情况还是司空见惯,一般来说只需要在burpsuite里面搜索对应云AK的名字,例如
AccessKey
Secret
、
SecretKey
等。
获取用户AK、SK以后,不仅是可以获取此bucket权限,也可以获取此AK所在的权限范围内的所有云API的操作权限。
在上传的时候,有的业务会使用如下逻辑进行上传:
-
首先通过文件时间戳生成一个随机文件名
-
通过此文件名在后端获取文件名PUT签名
-
通过该PUT签名上传
这个时候,由于上传的路径是我们控制,所以我们可以通过修改签名路径的形式,来进行签名,从而去覆盖此存储桶下的任意文件:
如果静态资源都存储在一个bucket的话,可以达到覆盖任意文件,如果没有办法覆盖(后端校验了路径的合法性),在对象存储的也页面我们都可以看到,对象存储是允许配置独立域名。
可能你上传的时候走的aliyuncs.com域名,但是发现,下载文件的时候域名变成了qiye.com,这时也可以尝试XSS攻击。
由于前端使用SDK上传,会减少很多前后端交互API的编写,所以很多开发总是会选择前端上传,所以云厂商开发了STS token的模式:
由于STS token是对针对API接口而不是大范围的云产品的,有的时候在存在AK、SK、STS都返回以后,上传有限制,只允许在特定目录下传文件的时候,不妨试一试带上STS访问ECS、SLB等其他同样支持STS的服务,对于AWS S3标准的STS,我们还可以通过BASE64解码来获取对应的权限
这是腾讯云的PUT ACL的解释
但是上次我们要如何去进行对ACL进行操作呢?如果是前端请求签名,并且前端上传的话,如果后端对路径没有做限制,我们就可以通过:
GET /get_put_sgin?uri=/ HTTP/1.1Host: 127.0.0.1:5000Accept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)Connection: close
获取根目录来进行PUT ACL的写入操作
PUT /?policy&sgin HTTP/1.1Host: ceshicos-1253712656.cos.ap-nanjing.myqcloud.comAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)Connection: closeContent-Type:application/jsonContent-Length: 381
{"Statement": [ { "Principal": { "qcs": [ "qcs::cam::uin/UIN:uin/UIN" ] }, "Effect": "allow", "Action": [ "name/cos:GetBucket", "name/cos:GetObject", "name/cos:PutObject" ], "Resource": [ "qcs::cos:ap-nanjing:uid/1253712656:ceshicos-1253712656/*" ] }],"version": "2.0"}
来对根目录进行ACL的写入,但是要注意的是
PUT bucket写入是一个覆盖操作
,会覆盖原有业务的ACL导致业务无此bucket权限,导致业务中断
。所以如果发现此问题不要贸然测试。
下载时的安全问题
对象存储为什么可以保证存储文件的安全?在私有读的存储桶里,读取任意文件都需要授权签名,签名过期后就无法读取,这样就会导致一张图片必须每次读的时候都去请求权限,在请求权限时,业务最常用的接口就是:
GET /download?uri=this_is_mine HTTP/1.1Host: 127.0.0.1:5000Accept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)Connection: close
服务端会返回签名后的链接给我们访问文件,但是如果我们的uri设置为空会怎么样呢?
很明显,对我们的根目录做了签名,访问的话,我们就可以获取对象存储的管理节点信息:
使用对应key即可获取任意文件(我这里是个空的存储桶)。
其他
除了以上所说的,其他的特性也可能会存在很多安全问题,例如
-
镜像回源 SSRF
-
目录形式bucket回源
-
callback接口泄漏
-
SDK SSRF
-
参数注入
-
日志泄漏
等等,玩法很多,大家可以自行摸索。
结语
对象存储确实让常规的文件上传漏洞利用价值降低,但是又由于开发的错误应用导致新型漏洞也会在对象存储中,对于这些漏洞,建议各位开发严格按照文档部署,对硬编码key一定要听从建议使用子账户,能避免大多数问题。