“公有云是为广大用户、个人或企业提供的云基础设施。公有云就是第三方公有云供应商为用户提供可通过互联网访问的虚拟环境中的服务器空间。然后,用户可以通过购买云服务器、数据存储和其他与云相关的服务等公有云服务来访问这些服务器。虽然用户可通过互联网访问公有云,但数据将通过虚拟化与其他用户的数据隔离,以提高安全性。公有云供应商还主动确保其服务器不受漏洞影响,并使用最新的软件补丁进行更新。但最终还是由使用者负责数据在云中的使用,包括访问、身份验证、加密和应用程序配置。”
随着越来越多的企业将应用、存储上云,各大公有云提供了各种 IaaS、PaaS、SaaS 服务,针对公有云各组件的攻击面也伴随而生。公有云厂商在尽可能保证组件安全的前提下,由于各种基础配置还是由用户决定,因此仍然存在很多安全风险。
对象存储中,上传文件都是以对象形式存储在云端,既不会存在可执行文件,又不会因为同站文件存在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
创建空间时,可设置为公开空间或私有空间。
公开空间:可通过文件对象的 URL 直接访问。
私有空间:文件对象的访问则必须获得拥有者的授权才能访问。
如果设置为公开空间,则任何知道URL链接的人都能访问,此类空间适合存放公共文件,如网站静态资源、用户头像等公开资源。针对敏感文件,尽量还是选择私有空间,私有空间在访问时一般要加上签名信息才能访问。
目前大部分云厂商会提供类似
https://bucket.s3-china-region.cloud.com/?ak=xxxx&sgin=xxxx&time=16xxxx的类似AWS S3 签名URL形式,或者直接兼容S3协议,以提供下载、上传、管理API,具体参数意义如下:
AK用于控制用户权限
Sign用于验证签名,一般的云厂商都会把AK、domain、URI、Query、Header等请求特征、身份特征以及时间戳拼接在一起,然后使用SK做为盐值进行hash,来生成最后的Sgin,用于校验此数据包是否合法
time是时间戳,用户标识此URL过期时间
通过查阅相关文件,我们可以知道使用表单上传文件到 OSS的技术方案里,有三种实现方式:
1、在客户端通过JavaScript代码完成签名,然后通过表单直传数据到OSS。
2、在服务端完成签名,然后通过表单直传数据到OSS。
3、在服务端完成签名,并且服务端设置了上传后回调,然后通过表单直传数据到OSS。OSS回调完成后,再将应用服务器响应结果返回给客户端。
在对象存储的SDK中,一般都会存在JavaScript的SDK,也就是支持用户前端上传的组件。
一般来说,在安全的配置下,前端上传会使用子用户、或者临时密钥(STS token)的方式来进行,但是由于不严谨的开发,前端js文件、APK文件硬编码AK / SK的情况还是司空见惯,一般来说只需要在burpsuite里面搜索对应云AK的名字,例如AccessKey、SecretKey等,除此之外这类数据较多泄露在github、逆向后的客户端源码、js前端代码中,获取到SecretId和SecretKey后相当于拥有了对应用户的身份权限,如果该账户下有权限管理云服务器,则可以通过检索主机接管账户下的云服务器。
推荐使用图形化工具接管云主机:https://yun.cloudbility.com/
在某些业务场景下,可能会存在如下流程:
1、首先结合时间戳生成一个随机文件名
2、通过此文件名信息在后端获取该文件的上传签名
3、最后通过PUT或者POST上传
这个时候,由于上传的路径是我们控制,所以我们可以通过修改签名路径的形式,来进⾏签名,从⽽去覆盖此存储桶下的任意⽂件
我们可以看到已经成功上传了⼀个新⽂件覆盖原来的⽂件。
能达到⽂件覆盖的⽬的后,就可以对储存桶资⾥原有的资源进⾏修改,可能会带来XSS⻛险,严重还可能造成供应链投毒攻击。
如果静态资源都存储在一个bucket的话,可以达到覆盖任意文件,如果没有办法覆盖(后端校验了路径的合法性),在对象存储的也页面我们都可以看到,对象存储是允许配置独立域名。
在文件覆写条件成立后,先假设一个场景,某企业主站里面的静态js文件均放在OSS的云储存配合CDN进行加速,现在已知js文件的路径和名称,那么我们就可以在原有js里插入一段恶意js代码进行文件覆盖,从而达到xss甚至长期信息窃取的风险。
在文件覆写条件成立后,先假设一个场景,某企业为软件提供商,为了节省服务器带宽,将软件/源码上传到OSS进行分发,因为配置不当正好存在任意文件覆盖,导致软件或源码中被插入恶意代码。
由于前端使用SDK上传,会减少很多前后端交互API的编写,所以很多开发总是会选择前端上传,所以云厂商开发了STS token的模式,有关STS的介绍查看https://help.aliyun.com/document_detail/32122.html
由于STS token是对针对API接口而不是大范围的云产品的,有的时候在存在AK、SK、STS都返回以后,上传有限制,只允许在特定目录下传文件的时候,不妨试一试带上STS访问ECS、SLB等其他同样支持STS的服务,对于AWS S3标准的STS,我们还可以通过BASE64解码来获取对应的权限。
PUT Bucket acl 接口用来写入存储桶的访问控制列表(ACL),您可以通过请求头 x-cos-acl 和 x-cos-grant-* 传入 ACL 信息,或者通过请求体以 XML 格式传入 ACL 信息。
详细参考:https://cloud.tencent.com/document/product/436/7737
尝试读取 Bucket 的 ACL 策略,发现可以读取:
尝试使用 PUT 方法修改 Bucket 的 ACL 策略:
尝试遍历 Object,发现可以遍历到了,说明刚才上传的 ACL 策略生效了
即然能覆盖原ACL,那就说明如果配置不当,就可能存在一定的安全问题。
如果是前端请求签名,并且前端上传的话,如果后端对路径没有做限制,我们就可以通过请求SDK获得根目录的写入权限,接着配合PUT ACL进行覆盖。
对根目录进行ACL的写入时要注意的是PUT bucket写入是一个覆盖操作,会覆盖原有业务的ACL导致业务无此bucket权限,导致业务中断。所以如果发现此问题不要贸然测试。
对象存储为什么可以保证存储文件的安全?在私有读的存储桶里,读取任意文件都需要授权签名,签名过期后就无法读取,这样就会导致一张图片必须每次读的时候都去请求权限,在请求权限时,业务最常用的接口就是:
GET /download?uri=file HTTP/1.1
Host: <BucketName-APPID>.cos.<Region>.myqcloud.com
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
发送这个请求就会返回一个加参数的url,但是如果我们的url设置为空,例如这样:
GET /download?uri= HTTP/1.1
Host: <BucketName-APPID>.cos.<Region>.myqcloud.com
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
那么就会访问到对象存储的管理节点信息,从而获取整个桶里的文件信息,再拿得到的key去构造访问链接,从而造成储存桶的文件遍历。
对象存储确实让常规的文件上传漏洞利用价值降低,但是又由于开发的错误应用导致新型漏洞也会在对象存储中,对于这些漏洞,建议各位开发严格按照文档部署,对硬编码key一定要听从建议使用子账户,能避免大多数问题。