Over the past decade, Azure’s presence in businesses has grown significantly as new features and support were added to Azure. The purpose of this article is to cover three main points:
- Explain the components of Azure and how they fit into a modern IT environment.
- Explain how certain things within Azure can be leveraged from an offensive perspective.
- Introduce the PowerZure project and explain how it helps offensive operations against Azure.
Azure was released in 2010 as “Windows Azure” and was renamed “Microsoft Azure” in 2014 to imply that Azure covers more than just Windows products, as well as the major addition of Azure Resource Manager (Azure RM) and Azure Active Directory (Azure AD). It started as Platforms as a Service (PaaS) to spin up Virtual Machines (VMs), Storage, WebApps, and SQL Databases but has now evolved into Infrastructure as a Service (IaaS), as well as Software as a Service (SaaS), offering over 600 services.
Current implementations of Azure often involve using several components shown above, which will be highlighted.
Azure’s architecture is complicated as there are several components. There are a few components that are essential to understand as they are commonly used within businesses.
This represents the Azure global account. It’s the unique identity that the business owns and allows access to subscriptions, tenants, and services.
Tenants are instances of Azure for the Enterprise. An Enterprise can have multiple tenants. This is often seen in companies that are geographically separated or subsidiaries. Access to one tenant in an enterprise does not give access to another tenant. An analogy is that tenants are similar to Forests in Active Directory, where trusts can be established (within Azure AD), but that is not default and must be configured.
Subscriptions are how you gain access to Azure services (Azure itself, Azure AD, Storage, etc). Subscriptions are often broken out into uses for the businesses, e.g. a subscription for production web apps, another subscription for development web apps, etc.
Resources are the specific application, such as SQL servers, SQL DBs, virtual networks, run-books, accounts, etc.
Resource groups are the containers that house the resources. Business will often have multiple resource groups depending on their usage of the resource.
Runbooks are part of the Azure Automation service and support scripting languages PowerShell and Python (2.7). These allow for automation of operations within Azure, e.g. start-up of multiple virtual machines at once. There are possible attack vectors within Runbooks that are covered later.
Azure Active Directory
Azure Active Directory (Azure AD) is directory services in the cloud. There are many differences between it and on-premise AD, which is also covered later.
Azure AD Connect
Azure AD connect is the tools that actually connects on-premise with Azure AD. It has features such as hash synchronization and federation (between Tenants) to link to on-premise AD.
An Azure service principal is a security identity used by user-created apps, services, and automation tools to access specific Azure resources. Think of it as a ‘user identity’ (login and password or certificate) with a specific role, and tightly controlled permissions to access your resources. It only needs to be able to do specific things, unlike a general user identity. It improves security if you only grant it the minimum permissions level needed to perform its management tasks. For example, an organization can assign its deployment scripts to run authenticated as a service principal.
A visualization of Azure’s architecture is shown below
Azure AD is not a replacement for on-premise AD, nor is it the same as Azure (i.e. AzureAD vs. Azure). AzureAD is a management platform for AD from the cloud (reset passwords, create users, add users to groups, etc.) and used as the authentication piece into Azure as a whole (as well as O365). This still introduces several interesting attack paths that may also effect on-premise AD.
There are three primary ways of integrating on-premise Active Directory to Azure AD, Password Hash Synchronization (PHS), Pass Through Authentication (PTA), and Federated Services (ADFS). PHS and PTA both have potential attack vectors associated with them.
Password Hash Synchronization
With Password Hash Synchronization (PHS), the passwords from on-premise AD are actually sent to the cloud, similar to how domain controllers synchronize passwords between each other via replication. This is done from a service account that is created with the installation of AD Connect.
This introduces a unique attack path where if the synchronization account is compromised, it has enough privileges that it potentially could lead to the compromise of the on-premise AD forest, as that account is granted replication rights which are needed for DCSync. Realistically, the sync account password should not be known and thus will not be logged in anywhere, however Dirk-jan, during his Troopers 2019 presentation, discovered how to reverse the account’s password from the SQL DB and made a script that would do the hard work.
Pass Through Authentication
Pass through authentication keeps the passwords on-premise but also allows the users to have a single password for Azure and on-premise. For example, when a user logins to Outlook on the web, they enter their credentials into the web portal (Azure AD), which Azure then uses PKI to encrypt the credentials and sends them to an agent on-premise. The agent decrypts the credentials and validates it against the DC, which returns a status back to the agent, which is then relayed back to Azure AD.
It’s possible to perform DLL injection into the PTA agent and intercept authentication requests, which include credentials in clear-text. @_xpn_ has written an excellent blog post on doing this.
Active Directory Federated Services (ADFS)
Azure AD can connect back to on-premise via ADFS. With ADFS, Azure AD is set as a trusted agent for federation and allows login with on-premise credentials.
Policies in Azure do not do the actual controlling of access, they are meant to enforce different rules and effects for resources. For example, with policy, you can restrict certain sizes of a VM in your subscription, or make sure the Administrators group in a VM doesn’t have too many members. Policies are broken into two parts — the policies themselves, and policy definitions. An example is shown below.
Policies contain multiple definitions, where definitions are what does the auditing/action. Thus, you can create a definition and apply it to multiple policies.
Role Based Access Control (RBAC) and Roles
Azure offers a more granular control to security with RBAC, in the form of Roles. It differs from Policies by focusing on user actions at different scopes. You might be added to the Contributor role for a resource group, allowing you to make changes to that resource group. RBAC in Azure allows for custom roles, however many businesses rely on the built-in roles. The list of roles and their access can be found here. To confuse you more, there’s a difference between Azure roles (referred to as Azure RBAC) and AzureAD roles. The primary difference, is that AzureAD roles only affect AzureAD and do not have any influence over resources within Azure. With this being said, the exclusion to that is the Global Administrator role, which has the option (literally a toggle switch in the Azure Portal) to also give themselves (Global Administrator) ownership of all resources within Azure itself.
For the purpose of this this article, only the following roles within Azure RBAC will be discussed:
The reason being is there are far too many roles to go in depth on all of them, with also the additional option of custom roles. Within the Azure portal, you can read a resource’s security settings, such as which roles can access or make changes to that resource. This can be viewed in the Identity Access & Management (IAM) tab in the Azure portal if you prefer not to use the CLI.
Resources can have their own specific access control list (ACL), so you can add a user to only be able to view that specific resource. It’s important to note that roles/permissions are inheritance-based, meaning if a user is in the Contributor role for the resource group, they will effectively have Contributor access to every resource within the resource group. Even if they are only assigned to the reader role for a resource within that resource group, since they have Contributor access to the whole group they will be a Contributor to that resource.
Attacking Azure and Introducing PowerZure
With several components in Azure, there are several different avenues for attacks within the platform. These attack vectors leverage misconfigurations or design flaws, some of which are listed here. The major question that needs to be addressed, is what is the goal of testing an Azure instance? This will depend on the engagement and scope of work, so there’s multiple answers to that, however in this article the purpose is to demonstrate the implications of certain roles and resources within Azure and how those can be abused both from a privilege escalation standpoint and an overall data extraction standpoint to possibly achieve that goal.
After interacting with Azure via CLI and the az module, I realize there is a great opportunity to script out many of the tasks an attacker would do within Azure. As a result, I’ve created PowerZure, a PowerShell project that’s purpose is to make interacting with Azure a bit easier, as well as adding offensive capability.
PowerZure leverages three PowerShell modules for Azure:
- Azure CLI
- Azure PowerShell
- AzureAD PowerShell
Each module does things the other cannot, hence the need for all three. However, PowerZure mostly relies on the Azure CLI module.
PowerZure has several functions available and they are broken out in reference to their purpose:
- Operational — Functions that will cause an operation within Azure
- Information Gathering — Functions that gather information on resources in Azure
- Data Exfiltration — Functions that will exfiltrate data
For the sake of length and time, not all functions will be covered, but it is necessary to explain the purpose of some and the details around what is happening under the hood.
Since PowerZure requires the az module, After importing PowerZure
ipmo .\PowerZure, it will download the modules if not already present.
For a full coverage of PowerZure, check out the documents on readthedocs.io
It then requires sign in before usage of the functions. There’s three types of logins for Azure:
- Interactive. Simply type az login and you will be directed to a login page. If using MFA, you must login via Interactive mode.
- Cached token. Tokens for Azure are cached in
So after you login once, the token is cached. This allow shows the possibility that an access token can be stolen and re-used.
3. Pass in credentials. You can login (if MFA is not enabled and you’re using a non-personal account) via
az login -u User -p Password
Once logged in, PowerZure will display your username, the subscriptions you have access to, your roles, and your Azure AD group memberships. Knowledge of what Role the user has is key to figuring out what you can do operationally and what functions you can use within PowerZure. PowerZure’s help menu specifically lists out which roles are needed to run the function. This is purely in reference to the built-in roles, as custom roles are unpredictable. To view the help menu, the command is
In addition, each function can be used with Get-Help to get information or syntax.
Before further operation of PowerZure, a default subscription must be set if there are multiple subscriptions so the script will know which to operate against. A subscription can be set via
Set-Subscription -Id [idgoeshere]
The subscription IDs are printed once you login to Azure with PowerZure. If only one subscription is present, this can be ignored.
Each of the Global roles (Administrator, Owner, Contributor, Reader) will be broken down into what can be accomplished, why it’s necessary to accomplish, and how PowerZure helps.
The Global Reader role has read-only access for components in Azure (Subscriptions, Policies, Resources, etc.) This by itself can grant an attacker useful information. For example, if the attacker compromises an account with Reader privileges, they can read Runbooks. Runbooks fall under the “Automation Accounts” resource. An example is shown below
This can be useful to see if there’s any hard-coded credentials within those Runbooks.
As a Reader, you can also read several other resource’s details to search for hard-coded credentials or other potentially interesting information, including:
- Logic apps
- Deployment Templates
- Virtual Networks (Potentially useful to view new targets/address spaces)
- Export Templates on Virtual Machines
- Connection Strings in Azure SQL
- Configurations on several other resources/applications
PowerZure can be leveraged to do a lot of enumeration as a Reader. For example, gathering all users, groups, roles, etc. Runbooks can also be read. In PowerZure, Runbooks can be listed via Get-Runbooks
From here, the Runbooks can be obtained with Get-RunbookContent
Readers have access to all of the functions listed under ‘Information Gathering’, which can be found here.
Contributor role allows you to actually edit resources and services within Azure, instead of just reading properties. Several attack vectors are present from the Contributor role that can be exploited with PowerZure.
Execute-Commandwill execute a supplied command on a targeted VM. As Contributor, these commands are executed as SYSTEM.
Execute-MSBuildis a function that will take in a MSBuild payload and execute it. By default, Windows VMs deployed with Azure’s templates will have .NET 4.0 installed.
Execute-Programwill upload and execute any file that is supplied. It works by identifying a storage container, uploads the supplied file through
Get-AzVMCustomScriptExtension, then executes that program via
az vm run invoke. This entire process does take time (~2 mins) unfortunately, due to the dynamic location of where the file is uploaded to on the VM.
Get-AllKeyVaultContentswill automatically go through a Key Vault, check for access, and print the results of any secrets, keys, or certificates. By default, Key Vaults only allow access to their owners, however if a user has Global Contributor, they can edit the access policies on the Key Vault and give themselves access. PowerZure does this automatically.
Get-AllAppSecretswill return all passwords or certificate credentials for any Application that has them stored.
Get-AllSecretsis a catch-all; it will run return all Key Vault secrets/keys/credentials, App Secrets, and Automation Account Run-as credentials.
Contributors also can download disks from virtual machines.
Get-AvailableVMDiskswill list the available disks that are downloadable. This can then give the information needed for
Get-VMDiskwhich will generate a URL to download that disk. A fair warning, though, disks can be massive in size.
Owners can do everything a Contributor can do, but they have one additional feature: They can also give permission to a resource they own. This is particularly useful as an attacker because it provides many opportunities to create a backdoor into a resource. For example, if an Owner controls a Virtual Machine resource, they can explicitly grant any user Owner status over that Virtual Machine. In PowerZure, this is accomplished via the
Set-Role function. In addition, existing roles can be checked via
Set-Role -Role Contributor -User email@example.com -Resource Win10VMTest
Administrators over a subscription have the ability to do everything an Owner can, plus create additional users and groups within Azure AD. They also have the ability to assign roles for the subscription. PowerZure has the ability to utilize an Administrator account to create a backdoor with a Runbook.
Create-Backdoor, when executed, will create a Runbook. Inside the Runbook is instructions to create a new user and assign them to the Owner role, then generate a Webhook which will output a URI. This URI can then be passed into Execute-Backdoor.
Execute-Backdoorwill execute the Runbook. An attacker will create a backdoor in case the current account that is in use has it’s password changed. With Administrator role needed to create a user, a new co-administrator should be made as well to achieve this in the Runbook, in case credentials to the user in the Administrator role are changed.
So what is the point of PowerZure if you can accomplish all of this via the Azure Portal online? While true, PowerZure was written to help automate and script many of the tedious tasks that are endured when enumerating Azure through the Portal, e.g. listing all users of every group. The use case of the tool is situational. One example, is if a penetration tester or red-teamer compromises a computer and realizes the user has logged into Azure CLI before (not unusual for System Admins) and they have an accessToken in their .Azure file. The tester could then take that token and impersonate the user in Azure, where they now have Contributor access to several different VMs. In addition, operations within the portal do not always return the full details of the job. With
az returning the raw JSON, PowerZure abstracts the JSON to give relevant details, or in some cases, displays the raw output.
Azure usage has increased dramatically in the past few years and AzureAD is becoming more popular to use. My opinion is that it is not a replacement for on-premise AD at this time, however I do foresee Microsoft adding more functionality to AzureAD to allow businesses to interact more with on-premise. This blog post was meant to establish a base layer of knowledge on the platform and establish some common misconfigurations that can be exploited with PowerZure.
The one thing this article did allude to was the detections around said tactics. The detection capabilities within Azure are heavily gate-kept behind Azure’s services and the default detection capabilities leave much to be desired, often requiring work-arounds. As a result, this requires more detail that I believe would be best detailed in a follow up article. Said article will follow this one in regards to detections within Azure.
- PowerZure Project https://github.com/hausec/PowerZure
- NetSPI and Karl Fosaaen
2. FoxIT and Dirk-Jan
3. Trimarc and Metcalf
4. XPN’s blog