Az - Container Registry
Reading time: 6 minutes
{{#include ../../../../banners/hacktricks-training.md}}
Basic Information
Azure Container Registry (ACR) is a secure, private registry that lets you store, manage, and access container images in the Azure cloud. It integrates seamlessly with several Azure services, providing automated build and deployment workflows at scale. With features like geo-replication and vulnerability scanning, ACR helps ensure enterprise-grade security and compliance for containerized applications.
Permissions
These are the different permissions according to the docs that can be given over a Container Registry:
- Access Resource Manager
- Create/delete registry
- Push image
- Pull image
- Delete image data
- Change policies
- Sign images
There are also some built-in roles that can be assigned, and it's also possible to create custom roles.
Authentication
warning
It's very imporatant that even if the registry name contains some uppercase letters, you should always use lowercase letters to login, push and pull images.
There are 4 ways to authenticate to an ACR:
- With Entra ID: This is the default way to authenticate to an ACR. It uses the
az acr login
command to authenticate to the ACR. This command will store the credentials in the~/.docker/config.json
file. Moreover, if you are running this command from an environment without access to a docker socket like in a cloud shell, it's possible to use the--expose-token
flag to get the token to authenticate to the ACR. Then to authenticate you need to use as user name00000000-0000-0000-0000-000000000000
like:docker login myregistry.azurecr.io --username 00000000-0000-0000-0000-000000000000 --password-stdin <<< $TOKEN
- With an admin account: The admin user is disabled by default but it can be enabled and then it'll be possible to access the registry with the username and password of the admin account with full permissions to the registry. This is still supported because some Azure services use it. Note that 2 passwords are created for this user and both are valid. You can enable it with
az acr update -n <acrName> --admin-enabled true
. Note that the username is usually yhe registry name (and notadmin
). - With a token: It's possible to create a token with a specific
scope map
(permissions) to access the registry. Then, it's possible to use this token name as username and some of the generated password to authenticate to the registry withdocker login -u <registry-name> -p <password> aregistry-url>
- With a Service Principal: It's possible to create a service principal and assign a role like
AcrPull
to pull images. Then, it'll be possible to login to the registry using the SP appId as username and a generated secret as password.
Example script from the docs to generate a SP with access over a registry:
#!/bin/bash
ACR_NAME=$containerRegistry
SERVICE_PRINCIPAL_NAME=$servicePrincipal
# Obtain the full registry ID
ACR_REGISTRY_ID=$(az acr show --name $ACR_NAME --query "id" --output tsv)
PASSWORD=$(az ad sp create-for-rbac --name $SERVICE_PRINCIPAL_NAME --scopes $ACR_REGISTRY_ID --role acrpull --query "password" --output tsv)
USER_NAME=$(az ad sp list --display-name $SERVICE_PRINCIPAL_NAME --query "[].appId" --output tsv)
echo "Service principal ID: $USER_NAME"
echo "Service principal password: $PASSWORD"
Encryption
Only the Premium SKU supports encryption at rest for the images and other artifacts.
Networking
Only the Premium SKU supports private endpoints. The other ones only support public access. A public endpoint has the format <registry-name>.azurecr.io
and a private endpoint has the format <registry-name>.privatelink.azurecr.io
. For this reason, the name of the registry must be unique across all Azure.
Microsoft Defender for Cloud
This allows you to scan the images in the registry for vulnerabilities.
Soft-delete
The soft-delete feature allows you to recover a deleted registry within the indicated number of days. This feature is disabled by default.
Webhooks
It's possible to create webhooks inside registries. In this webhook it's needed to specify the URL where a request will be sent whenever a push or delete action is performed. Moreover, Webhooks can indicate a scope to indicate the repositories (images) that will be affected. For example, 'foo:*' means events under repository 'foo'.
From an attackers perspective it's interesting to check this before performing any action in the registry, and remove it terporarely if needed, to avoid being detected.
Connected registries
This basically allows to mirror the images from one registry to another one, usually located on-premises.
It has 2 modes: ReadOnly and ReadWrite. In the first one, the images are only pulled from the source registry, and in the second one, images can also be pushed to the source registry.
In order for clients to access the registry from Azure, a token is generated when the conected registry is used.
Runs & Tasks
Runs & Tasks allows to execute in Azure container related actions that you typically needed to do locally or in a CI/CD pipeline. For example, you can build, push, and run images in the registry.
The easiest way to build and run a container is using a regular Run:
# Build
echo "FROM mcr.microsoft.com/hello-world" > Dockerfile
az acr build --image sample/hello-world:v1 --registry mycontainerregistry008 --file Dockerfile .
# Run
az acr run --registry mycontainerregistry008 --cmd '$Registry/sample/hello-world:v1' /dev/null
However, that will trigger runs that aren't super interesting from an attackers perspective cause they don't have any managed identity attached to them.
However, tasks can have a system and user managed identity attached to them. There tasks are the ones useful to escalate privileges in the container. In privileges escalation section it's possible to see how to use tasks to escalate privileges.
Cache
The cache feature allows to download images from an external repository and store the new versions in the registry. It requires to have some credentials configured by selecting the credentials from an Azure Vault.
This is very interesting from a attacker's perspective because it allows to pivot to an external platform if the attacker has enough permissions to access the credentials, download images from an external repository and configuring a cache could also be used as persistence mechanism.
Enumeration
warning
It's very important that even if the registry name contains some uppercase letters, you should only use lowercase letters in the url to access it.
# List of all the registries
# Check the network, managed identities, adminUserEnabled, softDeletePolicy, url...
az acr list
# Get the details of a registry
az acr show --name <registry-name>
# List tokens of a registry
az acr token list --registry <registry-name> --resource-group <res-group>
# List repositories in a registry
az acr repository list --name <registry-name> --resource-group <res-group>
# List the tags of a repository
az acr repository show-tags --repository <repository-name> --name <registry-name> --resource-group <res-group>
# List deleted repository tags
## At the time of this writing there isn't yet any command to restore it
az acr repository list-deleted --name <registry-name>
# List tasks
## Check the git URL or the command
az acr task list --registry <registry-name>
# List tasks runs
az acr task list-runs --registry <registry-name>
# List connected registries
az acr connected-registry list --registry <registry-name>
# List cache
az acr cache list --registry <registry-name>
# Get cache details
az acr cache show --name <cache-name> --registry <registry-name>
Privilege Escalation & Post Exploitation
Az - Automation Accounts Privesc
References
- https://learn.microsoft.com/en-us/azure/container-registry/container-registry-authentication?tabs=azure-cli
- https://learn.microsoft.com/en-us/azure/container-registry/container-registry-roles?tabs=azure-cli#access-resource-manager
{{#include ../../../../banners/hacktricks-training.md}}