Compromised Cloud Container Credentials: Azure Edition

Introduction

As more and more enterprises move their workloads to Azure, it has become more common to see Azure Container Registry (ACR) used as well. Whenever a new resource is introduced, the attack surface grows. ACR is no exception, and it shows in the security assessments and penetration tests that we do.

The problem

When doing Azure Resource Security Assessments, and Azure Assume Breach services for clients we will also take the stance of an adversary, meaning that we will look outside of simple misconfigurations and investigate exploitation as well.

Looking for clear text credentials to escalate privileges and exploit is nothing new. This often sends us to the Azure Container Registry service.

Having the low-privileged Role Based Access Control (RBAC) permissions of “Reader” on an ACR will allow you to download (pull) the images from the registry, to enumerate locally.

These images often contain clear-text credentials, or other sensitive information that helps us escalate privileges.

Proof-of-concept

To show the process of getting the information needed to pull the images, and to eventually pull the images, we will use Az CLI, and Docker Desktop installed on a Windows 10 machine.

1.       Log in to the tenant and set the context to any subscription with a Container Registry


2.      The current user I am using:

3.   These are my currently assigned roles. Here we see the built-in Reader RBAC role, and nothing else.

4.    List all the Azure Container Registries under current context


5.       Authenticate to the ACR


Huh? Oh well, that probably makes sense you know. Azure AD (Entra ID?) authentication, no big deal.

6.       List the repositories under the ACR

7.    List the tags of the image in the repository

Yeah, alright. Now this should be it, right? What could possibly come after listing all the details of a resource as a Reader?

The great reveal!

Once we’re logged in with the Az CLI, we have collected the necessary information, and we have Docker Desktop running, there are only a few things left.

8.       Pull the image to your local machine using Docker Desktop (This uses the Az CLI context to generate a token for the Container Registry backend)

9.     Start a container using the image and enter command-line in current window.

This is it! We now have root access to the underlying file system!

Why does this matter? It’s not connected to the intended network anymore?

We see an alarming amount of hard-coded clear-text credentials on these images, ranging from on-premises Active Directory users, to Azure AD (Entra ID?) Applications and Service Principals.


The solution

In the perfect world, no sensitive information is kept in the container images that are hosted in the ACR, but from experience, this is not an easy task. Instead we can look at a few other restrictions.

Option 1: Simple network restrictions

Requirements: Premium SKU Container Registry 

Once the ACR has been set to Premium, we will get the option to set “Public network access” to “Selected networks” under the “Networking” pane:

Note: In some scenarios, this might not solve the issue. For example, if you choose to allow your entire public IP range, an adversary would still be able to reach the ACR, in an assumed breach scenario.


Option 2: Private Endpoint (A personal favorite)

Requirements: Premium SKU Container Registry

This is a solution that will allow you to completely customize which Virtual Networks in your tenant can reach the ACR.

This could be a Container Instance running an image, and perhaps a Virtual Machine for managing both of those, or it could be connected to your on-premises administrative network. The options with a Private Endpoint are vast and can be very restrictive!

Deployment might look like this:


Just need to ensure that we disable public network access:

Takeaways

The security of resources deployed in Azure will always only be as secure as we configure them to be.

Any security journey starts with least-privilege implementation, but there are additional initiatives we can take, such as auditing the technical configuration of the resources in the tenant, and regular testing of both the internal and external attack surface.

Specifically for Azure Container Registry, following any of the options, that are feasible for your environment, will aid in avoiding unintended attack-paths, and data leakage.

Lastly, anyone working with the images in a repository should take care not to include information that is not strictly necessary for operation.

[1] Azure built-in roles - Azure RBAC | Microsoft Learn