Exploiting and defending anonymous access in Azure

Many cloud-related security breaches start with a compromised user identity. Once an attacker gets a foot in the door using the compromised credential, they can gather intelligence to move further in the attack chain or look for opportunities to escalate privileges. However, in not so rare cases, reserchers or attackers have been able to exploit service misconfigurations to gain initial access without having to compromise an identity to begin with.

The Azure platform has over 190 services the last time I counted (this depends really on what you count as a service E.g. do you count blob as a separate service or just the storage account?). Most of these services require some form of authentication for access — a method for the caller to prove their identity with a verifiable token. This can either be identity-based using Azure AD or Active Directory as in the case of Azue Files or key-based using a long lived access key or short-lived access token.

However, there are a few exceptions that allows the configuration of unauthenticated and unauthorized access. The most common ones that I’ve seen are the Azure Blob Container and the Azure Container registry!

Azure Blob Storage Container

Blob storage container access levels

This is to make it easier to support use cases like static web hosting or content hosting for public sites. The downside is that sensitive information is sometimes placed in those storage containers! You can see examples here, here and here.

Using service discovery, guessing and DNS bruteforce techniques, containers and objects can be located publicly and exploited for intel gathering or credential hunting as part of an attack chain.

If the anonymous access level is configured at the container level, there are two main unknowns that can be discovered, guessed or brute-forced — the account name and the container name. If the anonymous access level is configured at the object level, there are three main unknowns that can be discovered, guessed or brute-forced — the account name, the container name and the object name.

http://[ACCOUNT_NAME].blob.core.windows.net/[CONTAINER_NAME]/[OBJECT_NAME]

The Invoke-EnumerateAzureSubDomains and Invoke-EnumerateAzureBlobs functions of MicroBurst can be used for this. There is a hands-on exercise that coveres this exact scenario in this new book if you’ll like to see this in action — https://amzn.to/2Vt0Jjx (co-authored with Karl Fosaeen).

Azure Container Registry

Anonymous pull access enabled

With ACR — the name of the registry and the name of the image is what is needed to attempt an anonymous pull. These two unknowns could be guessed or bruteforced. The image tag is not required as if none is specified, the image with the tag called “latest” will be pulled by default.

docker pull [ACCOUNT_NAME].azurecr.io/[IMAGE_NAME]

It is not uncommon to find further credentials in container images that can be used to further an attack chain.

Credential hunting in container images

In my experience, the container registry anonymous pull scenario usually happens when cloud engineers enable this option either to troubleshoot an issue with image pull OR to workaround a limitation but then they forgot to set it back to false.

Protecting Anonymous Access in Azure

1. Understand the supported access options of an Azure service before adoption! These are the two that I’ve encountered in my own work but there could be other Azure services that can also be configured for anonymous access!

2. Audit your environment for resources with anonymous access enabled. To identify anonymous blob containers and objects, you can use BlobHunter — a free tool created by CyberArk to perform authenticated audits for this use case. Many cloud security posture management platforms like Prisma Cloud, Security Center would also do this on a more wider and continuous basis.

BlobHunter authenticated audit of anonymous blob containers and objects

2. Disable the option to configure “anonymous access” where possible. Thankfully, both services mentioned in this blog allows for this. This can either be done on the resource level or centrally using Azure policy.

Here is a screenshot to disable public or anonymous access for blob storage containers and objects (Azure PortalStorage AccountConfiguration Blob public access)

Disable blob public access on a resource level

And here is a screenshot of the Azure CLI command to disable anonymous pull for a container registry

In many cases, we can also disable centrally using Azure Policy. There is a built-in policy for blob storage that is currently in preview (see screenshot below). I don’t like the use of the term “public access” here as public access is still allowed even if you disable it — only that all requests needs to be authenticated.

Disable blob public access using Azure policy

There is no built-in policy to assess anonymous container registries but one can be constructed to assess the value of the anonymousPullEnabled property. Here’s a sample assessment using Prisma Cloud’s RQL.

config from cloud.resource where cloud.type = ‘azure’ AND api.name = ‘azure-container-registry’ AND json.rule = anonymousPullEnabled equals true

4. Audit resource logs for anonymous access usage. As the saying goes — trust but verify. SecOps teams can also monitor for anonymous access usage in event logs to uncover blind spots that may have been missed when organization standards were implemented.

5. Use private endpoints for PaaS services that supports them. This reduces at least some risk by adding an extra layer of defense with network isolation. Blob containers and ACR supports this.

Cloud security architect at the prisma cloud speedboat at Palo Alto Networks. Author of two books on Azure cloud security — https://amzn.to/2Vt0Jjx