T1525

Implant Internal Image

Persistence Last updated:

Adversaries may implant cloud or container images with malicious code to establish persistence after gaining access to an environment. AWS AMIs, GCP Images, Azure Images, and container registries such as ECR, ACR, and Docker Hub private registries can be backdoored. Unlike uploading malware to external infrastructure, this technique focuses on modifying or creating images within a victim's own cloud environment. If the infrastructure provisioning pipeline is configured to always pull the latest image, a backdoored image ensures persistent access to any newly spun-up instance.

What is T1525 Implant Internal Image?

Implant Internal Image (T1525) maps to the Persistence tactic — the adversary is trying to maintain their foothold in MITRE ATT&CK.

This page provides production-ready detection logic for Implant Internal Image, covering the data sources and telemetry it touches: Cloud: Cloud Service Modification, AWS CloudTrail, Azure Activity Log, Cloud: Cloud Storage Object Modification. The queries below are rated high severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.

MITRE ATT&CK

Tactic
Persistence
Technique
T1525 Implant Internal Image
Canonical reference
https://attack.mitre.org/techniques/T1525/
Microsoft Sentinel / Defender
kusto
let AwsImageOps = dynamic([
  "CreateImage", "RegisterImage", "CopyImage", "ImportImage",
  "ModifyImageAttribute", "ImportSnapshot", "CreateSnapshot",
  "PutImage", "BatchDeleteImage", "InitiateLayerUpload", "CompleteLayerUpload"
]);
let AzureImageOps = dynamic([
  "microsoft.compute/images/write",
  "microsoft.compute/galleries/images/versions/write",
  "microsoft.containerregistry/registries/push/action",
  "microsoft.containerregistry/registries/importimage/action",
  "microsoft.compute/virtualmachines/capture/action"
]);
// AWS EC2 / ECR image operations ingested via AWS CloudTrail connector
AWSCloudTrail
| where TimeGenerated > ago(24h)
| where EventSource in ("ec2.amazonaws.com", "ecr.amazonaws.com")
| where EventName in (AwsImageOps)
| extend ActorIdentity = UserIdentityArn
| extend ActorType = UserIdentityType
| extend SourceIP = SourceIpAddress
| extend IsRootActor = (UserIdentityType =~ "Root")
| extend IsExternalIP = (SourceIpAddress !startswith "10." and SourceIpAddress !startswith "192.168." and SourceIpAddress !startswith "172." and SourceIpAddress !startswith "fd" and SourceIpAddress != "AWS Internal")
| extend RequestedResource = tostring(parse_json(RequestParameters).name)
| project TimeGenerated, Platform="AWS", EventName, ActorIdentity, ActorType, SourceIP,
         IsRootActor, IsExternalIP, RequestedResource, RequestParameters, UserAgent
| union (
  // Azure Compute and Container Registry image operations
  AzureActivity
  | where TimeGenerated > ago(24h)
  | where tolower(OperationNameValue) in (AzureImageOps)
  | where ActivityStatusValue =~ "Succeeded"
  | extend ActorIdentity = Caller
  | extend SourceIP = CallerIpAddress
  | extend IsExternalIP = (CallerIpAddress !startswith "10." and CallerIpAddress !startswith "192.168." and CallerIpAddress !startswith "172.")
  | extend RequestedResource = tostring(parse_json(tostring(Properties)).resource)
  | project TimeGenerated, Platform="Azure", EventName=OperationNameValue, ActorIdentity,
           ActorType="AzureIdentity", SourceIP, IsRootActor=false, IsExternalIP,
           RequestedResource, RequestParameters=tostring(Properties), UserAgent=""
)
| sort by TimeGenerated desc

Detects cloud and container image creation, modification, and push operations across AWS (EC2 AMIs, ECR) and Azure (Compute Images, Container Registry) using native cloud audit log connectors in Microsoft Sentinel. Monitors for CreateImage, RegisterImage, CopyImage, ImportImage, ModifyImageAttribute on EC2; PutImage, CompleteLayerUpload on ECR; and equivalent Azure Compute/ACR write operations. Flags activity from root/privileged accounts and external IP addresses as higher-risk. Requires the AWS CloudTrail connector and Azure Activity Log connector to be configured in Sentinel.

high severity medium confidence

Data Sources

Cloud: Cloud Service Modification AWS CloudTrail Azure Activity Log Cloud: Cloud Storage Object Modification

Required Tables

AWSCloudTrail AzureActivity

False Positives

  • CI/CD pipeline automation creating golden AMIs or base container images as part of a legitimate image build and push workflow (e.g., Packer, GitHub Actions, Jenkins pipelines)
  • Cloud operations engineers capturing VM images for disaster recovery, golden image refresh, or compliance-mandated snapshots
  • Infrastructure-as-code tools (Terraform, Pulumi, CDK) creating or modifying images during automated provisioning runs
  • Container registry mirroring jobs that replicate approved public images into an internal private registry for air-gapped or compliance use
  • Security teams creating forensic images from compromised instances as part of an incident response workflow

Sigma rule & cross-platform mapping

The detection logic for Implant Internal Image (T1525) above is provided in a vendor-neutral form so you can deploy it on any SIEM. The same logic is shipped here as native KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the following logsource:

logsource:
  product: azure

Browse the community-maintained Sigma rules for this technique:


Testing Methodology

Validate this detection against 4 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1AWS AMI Creation from Existing Instance

    Expected signal: AWS CloudTrail event: EventName=CreateImage, EventSource=ec2.amazonaws.com. The event will include requestParameters with instanceId, name, and noReboot fields. A follow-up DescribeImages event will appear as the AMI status is checked. The actor's IAM ARN, source IP, and user agent (aws-cli) will be captured in UserIdentityArn, SourceIpAddress, and UserAgent fields.

  2. Test 2Docker Image Modification and Push to Local Registry

    Expected signal: Docker daemon logs will record the build and push operations. If Docker events are forwarded to Splunk via a log shipper (Filebeat, Splunk UF), events will show image build and push with the image name and tag. In Kubernetes environments, admission controller logs (OPA, Kyverno) will record any attempt to run this image. Container runtime security tools (Falco, Sysdig) will generate events for the image push.

  3. Test 3AWS ECR Image Push with Modified Tag

    Expected signal: AWS CloudTrail events: GetAuthorizationToken (ECR login), InitiateLayerUpload (begin push), UploadLayerPart (each image layer), CompleteLayerUpload (layer commit), and PutImage (finalize image with tag) — all with EventSource=ecr.amazonaws.com. All events include the actor IAM ARN, source IP, repository ARN, and user agent. The PutImage event includes imageManifest in requestParameters.

  4. Test 4Azure Container Registry Image Import

    Expected signal: Azure Activity Log event: OperationName=microsoft.containerregistry/registries/importimage/action, ResourceType=Microsoft.ContainerRegistry/registries, ActivityStatus=Succeeded. Includes Caller (UPN or service principal), CallerIpAddress, and ResourceId. The Azure Monitor diagnostic logs for ACR will also record the image push with repository, tag, and digest details.


Response Playbook

Triage

  1. Identify the actor who performed the image operation — retrieve the full IAM ARN (AWS) or UPN/service principal (Azure). Determine whether the identity is a human user, service account, assumed role, or CI/CD service identity. Check if this identity has historically performed image operations.
  2. Check the source IP address of the operation. An external or unexpected IP for an image creation event is a significant escalation indicator. Use threat intelligence feeds or your SIEM's IP enrichment to identify the IP reputation and geolocation.
  3. Examine what image was created or modified. For AWS AMIs, use `aws ec2 describe-images --image-ids <ami-id>` to get the name, description, creation date, and associated snapshot. For container images, retrieve the image manifest and scan the layers for unexpected additions.
  4. Determine whether any infrastructure provisioning systems (Terraform, CloudFormation, Kubernetes) are configured to automatically deploy the latest version of the affected image. If so, any instances spun up after the implant could already be compromised.
  5. Review the timeline immediately before the image operation — look for reconnaissance events (DescribeImages, ListImages, GetAuthorizationToken) that suggest an adversary was enumerating available images before selecting a target for implanting.
  6. Check for related CloudTrail or Activity Log events from the same actor in the same session: privilege escalation, credential exfiltration (GetSecretValue, DescribeSecret), lateral movement (AssumeRole, CreateKey, AddUserToGroup), or data access events.

Containment

  1. If the image is confirmed malicious: immediately deregister the AMI (`aws ec2 deregister-image --image-id <ami-id>`) or delete the container image tag from the registry. Prevent further deployments by modifying the registry policy or image pull permissions.
  2. Identify all running instances launched from the implanted image. Use `aws ec2 describe-instances --filters Name=image-id,Values=<ami-id>` to enumerate affected instances. Isolate them by moving to a quarantine security group with no ingress/egress, or using the EDR isolation feature.
  3. Revoke the credentials used to perform the image operation. For AWS IAM roles, delete the session tokens and rotate the access keys. For Azure, revoke the service principal's credentials and audit its role assignments.
  4. Block the source IP in AWS Security Groups, Azure NSGs, or your perimeter firewall if the operation originated from an external or unexpected IP.
  5. Review and harden the image pipeline: enforce mandatory code review and scanning (Trivy, Grype, Snyk) before any image can be pushed to production registries. Consider implementing signed image policies (Docker Content Trust, AWS Signer, Azure Container Registry content trust).
  6. If the implanted image was already deployed and instances are running from it: treat each affected instance as fully compromised — assume persistent access, credential theft, and potential lateral movement have already occurred.

Evidence Collection

  1. AWS CloudTrail — retrieve the full event record for the image operation including requestParameters and responseElements. Use `aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=CreateImage` filtered by the time window.
  2. AWS EC2 — `aws ec2 describe-images --image-ids <ami-id> --include-deprecated` — capture all metadata including name, description, state, platform, root device, block device mappings, and associated snapshot IDs.
  3. AWS ECR — `aws ecr describe-images --repository-name <repo> --image-ids imageTag=<tag>` to get image digest, push date, and size. Also retrieve the image manifest: `aws ecr batch-get-image --repository-name <repo> --image-ids imageTag=<tag>`.
  4. Container image layer analysis — pull the image and run `docker history --no-trunc <image>` to see all layers and commands. Use `docker inspect <image>` for full metadata. Scan with a vulnerability scanner: `trivy image <image>` or `grype <image>`.
  5. Azure Activity Log — retrieve the full operation record including caller, callerIpAddress, operationName, resourceId, and properties. Export to Log Analytics or storage account for preservation.
  6. Azure Container Registry — `az acr repository show-tags --name <registry> --repository <repo>` and `az acr manifest show --name <registry>/<repo>:<tag>` to capture image metadata and layer digests.
  7. IAM/RBAC audit — capture the full permission set of the actor identity at the time of the event to understand what else they could access. For AWS: `aws iam get-user`, `aws iam list-attached-user-policies`, `aws iam simulate-principal-policy`.
  8. Instance metadata — for any running instances launched from the suspect image, collect OS-level forensic artifacts: process list, network connections, scheduled tasks/cron jobs, startup scripts, and filesystem changes.

Escalation Criteria

  • ! Image operation performed by a root account or a high-privilege service account that does not normally interact with image registries
  • ! Image creation or push performed from an external IP address, especially one with poor reputation or associated with known threat actors
  • ! Reconnaissance events (DescribeImages, ListImages, GetAuthorizationToken) immediately preceding the image write operation — indicates intentional targeting rather than accidental or misconfigured automation
  • ! The implanted image is configured as the default or latest tag in a registry that production workloads automatically pull from — risk of widespread deployment across the environment
  • ! Evidence of a backdoor payload in the image layers: reverse shell, web shell, crypto miner, SSH key injection, or modified system binaries
  • ! Running instances launched from the suspect image are already active — requires immediate incident response to contain potentially compromised workloads
  • ! The actor identity was compromised or used in other suspicious activity in the same session (credential stuffing, lateral movement, privilege escalation)

Investigation Guide

Forensic Artifacts

  • > AWS CloudTrail: CreateImage, RegisterImage, ModifyImageAttribute, PutImage, CompleteLayerUpload events in us-east-1 and all other regions where CloudTrail is enabled
  • > AWS EC2 AMI metadata: image name, description, creation date, owner account ID, snapshot IDs, block device mappings — accessible via `aws ec2 describe-images --owners self`
  • > AWS ECR image manifest: layer digests, image config, creation timestamps — retrieved via `aws ecr batch-get-image`
  • > Container filesystem layers: each Docker/OCI layer is a tarball; malicious additions will appear as new files or modifications in specific layers — examine with `docker save <image> | tar xv`
  • > Cloud instance user data / startup scripts: check if the image includes modified userdata, rc.local, or systemd units that execute at first boot
  • > Azure Activity Log: write operations on microsoft.compute/images and microsoft.containerregistry/registries with caller identity and IP
  • > Azure Container Registry webhooks and audit logs: image push events with actor, digest, and timestamp
  • > GCP Cloud Audit Logs (if applicable): compute.images.insert, storage.objects.create events in Cloud Storage buckets used for image staging
  • > Kubernetes admission controller logs: any pod creation events referencing the suspect image digest — check OPA/Gatekeeper or Kyverno audit logs

Tuning Guidance

Start by building a baseline of legitimate image actors in your environment. The most common false positive source is CI/CD service accounts (GitHub Actions, GitLab CI, Jenkins) that regularly build and push images as part of software delivery pipelines. Create an allowlist of known-good IAM role ARNs or Azure service principals that are authorized to perform image operations. For AWS, you can scope this by filtering on the `userIdentity.sessionContext.sessionIssuer.arn` field to identify assumed-role sessions from known CI/CD platforms. For container registry operations, ECR repositories with lifecycle policies and immutable tags generate far fewer false positives than mutable repositories. Consider enabling ECR image scanning on push (Amazon Inspector) and Azure Defender for Container Registries to add a secondary signal layer. Focus high-confidence alerting on: (1) image operations from root accounts — these are almost never legitimate, (2) operations from external IPs with no corresponding VPN/bastion session, and (3) images pushed outside of business hours from non-service accounts. If your environment uses AWS Organizations, enable CloudTrail across all member accounts and alert on cross-account image sharing events (ModifyImageAttribute with launchPermission changes) which are a strong indicator of adversary exfiltration staging.


Hunting Queries

Hunt for cloud image operations performed by identities that have no historical record of touching image resources in the past 90 days. A first-time image actor is a strong indicator of a compromised account being used for implanting, especially when combined with an external source IP.

Hunting — KQL
kql
// Hunt for image operations by accounts that have never previously touched image resources
let KnownImageActors = AWSCloudTrail
| where TimeGenerated between (ago(90d) .. ago(1d))
| where EventSource in ("ec2.amazonaws.com", "ecr.amazonaws.com")
| where EventName in ("CreateImage", "RegisterImage", "PutImage", "CompleteLayerUpload", "CopyImage", "ImportImage")
| summarize HistoricalImageOps=count() by UserIdentityArn;
AWSCloudTrail
| where TimeGenerated > ago(7d)
| where EventSource in ("ec2.amazonaws.com", "ecr.amazonaws.com")
| where EventName in ("CreateImage", "RegisterImage", "PutImage", "CompleteLayerUpload", "CopyImage", "ImportImage")
| join kind=leftanti KnownImageActors on $left.UserIdentityArn == $right.UserIdentityArn
| project TimeGenerated, EventName, UserIdentityArn, UserIdentityType, SourceIpAddress, RequestParameters
| sort by TimeGenerated desc
Hunting — SPL
spl
index=main sourcetype="aws:cloudtrail" (eventName="CreateImage" OR eventName="RegisterImage" OR eventName="PutImage" OR eventName="CompleteLayerUpload" OR eventName="CopyImage" OR eventName="ImportImage")
| eval ActorArn='userIdentity.arn'
[search index=main sourcetype="aws:cloudtrail" earliest=-90d latest=-1d
    (eventName="CreateImage" OR eventName="RegisterImage" OR eventName="PutImage" OR eventName="CompleteLayerUpload")
| stats count by 'userIdentity.arn'
| rename 'userIdentity.arn' as ActorArn
| where count > 0
| fields ActorArn
| format "NOT (" "ActorArn=\"" "\"" " OR " "ActorArn=\"" "\")"]
| table _time, eventName, ActorArn, sourceIPAddress, requestParameters
| sort - _time

Hunt for cloud images that were created and then deployed to running instances within 60 minutes. Legitimate golden image pipelines typically involve testing, scanning, and approval gates before deployment. A very short creation-to-deployment window — especially with different actor ARNs for creation vs. launch — is a strong indicator of an adversary rapidly deploying a backdoored image.

Hunting — KQL
kql
// Hunt for image creation immediately followed by deployment — fast image-to-launch patterns suggest automated backdoor delivery
let ImageCreations = AWSCloudTrail
| where TimeGenerated > ago(7d)
| where EventName in ("CreateImage", "RegisterImage", "PutImage")
| extend ImageId = tostring(parse_json(ResponseElements).imageId)
| project CreationTime=TimeGenerated, ImageId, CreatorArn=UserIdentityArn, CreationSourceIP=SourceIpAddress;
let InstanceLaunches = AWSCloudTrail
| where TimeGenerated > ago(7d)
| where EventName == "RunInstances"
| extend UsedImageId = tostring(parse_json(RequestParameters).imageId)
| project LaunchTime=TimeGenerated, UsedImageId, LauncherArn=UserIdentityArn, LaunchSourceIP=SourceIpAddress, InstanceDetails=RequestParameters;
ImageCreations
| join kind=inner InstanceLaunches on $left.ImageId == $right.UsedImageId
| extend MinutesToDeploy = datetime_diff('minute', LaunchTime, CreationTime)
| where MinutesToDeploy between (0 .. 60)
| project CreationTime, LaunchTime, MinutesToDeploy, ImageId, CreatorArn, LauncherArn, CreationSourceIP, LaunchSourceIP
| sort by CreationTime desc
Hunting — SPL
spl
index=main sourcetype="aws:cloudtrail" (eventName="CreateImage" OR eventName="RegisterImage" OR eventName="RunInstances")
| eval ImageId=case(
    eventName="CreateImage" OR eventName="RegisterImage", 'responseElements.imageId',
    eventName="RunInstances", 'requestParameters.imageId',
    true(), null()
  )
| eval EventType=case(
    eventName="CreateImage" OR eventName="RegisterImage", "ImageCreated",
    eventName="RunInstances", "InstanceLaunched",
    true(), "Other"
  )
| where isnotnull(ImageId)
| stats min(_time) as FirstSeen, max(_time) as LastSeen, values(EventType) as EventTypes, values('userIdentity.arn') as Actors by ImageId
| where mvcount(EventTypes) > 1
| eval DeploySeconds=LastSeen - FirstSeen
| where DeploySeconds < 3600
| table ImageId, FirstSeen, LastSeen, DeploySeconds, EventTypes, Actors
| sort DeploySeconds

Hunt for AMIs that have had their launch permissions modified to allow external AWS accounts or the public ('all') to launch them. Adversaries may implant an image and then share it with their own external account for persistent access, or make it public to establish a supply chain attack vector targeting other organizations using that image.

Hunting — KQL
kql
// Hunt for images shared with external AWS accounts or made public — a common exfiltration vector
AWSCloudTrail
| where TimeGenerated > ago(30d)
| where EventName == "ModifyImageAttribute"
| extend Params = parse_json(RequestParameters)
| extend AttributeName = tostring(Params.attribute)
| extend OperationType = tostring(Params.operationType)
| extend LaunchPermissions = tostring(Params.launchPermission)
| where AttributeName =~ "launchPermission"
| where LaunchPermissions has "all" or LaunchPermissions has "group" or OperationType =~ "add"
| project TimeGenerated, UserIdentityArn, SourceIpAddress, RequestParameters, LaunchPermissions
| sort by TimeGenerated desc
Hunting — SPL
spl
index=main sourcetype="aws:cloudtrail" eventName="ModifyImageAttribute"
| spath input=requestParameters path=attribute output=AttributeName
| spath input=requestParameters path=operationType output=OperationType
| spath input=requestParameters path=launchPermission output=LaunchPermissions
| where AttributeName="launchPermission"
| where (match(LaunchPermissions, "all") OR match(LaunchPermissions, "group") OR OperationType="add")
| table _time, 'userIdentity.arn', sourceIPAddress, requestParameters, LaunchPermissions
| sort - _time

Atomic Red Team Tests

Test 1 AWS AMI Creation from Existing Instance
linux

Creates an AMI from an existing EC2 instance using the AWS CLI, simulating the first step in an image implanting workflow where an adversary uses a compromised instance to generate a backdoored image. Replace the instance ID with a valid test instance. This generates CloudTrail CreateImage events that should be detected.

Command

bash
aws ec2 create-image --instance-id i-0123456789abcdef0 --name 'df00tech-implant-test-$(date +%s)' --description 'Detection validation test image - safe to delete' --no-reboot --tag-specifications 'ResourceType=image,Tags=[{Key=Purpose,Value=DetectionTest}]' --region us-east-1

Cleanup

bash
# Retrieve AMI ID from previous command output and deregister
AMI_ID=$(aws ec2 describe-images --owners self --filters 'Name=name,Values=df00tech-implant-test-*' --query 'Images[0].ImageId' --output text --region us-east-1)
aws ec2 deregister-image --image-id $AMI_ID --region us-east-1
# Also delete the associated snapshot
SNAP_ID=$(aws ec2 describe-snapshots --owner-ids self --filters 'Name=description,Values=*df00tech-implant-test*' --query 'Snapshots[0].SnapshotId' --output text --region us-east-1)
aws ec2 delete-snapshot --snapshot-id $SNAP_ID --region us-east-1

Expected Telemetry

AWS CloudTrail event: EventName=CreateImage, EventSource=ec2.amazonaws.com. The event will include requestParameters with instanceId, name, and noReboot fields. A follow-up DescribeImages event will appear as the AMI status is checked. The actor's IAM ARN, source IP, and user agent (aws-cli) will be captured in UserIdentityArn, SourceIpAddress, and UserAgent fields.

Expected Detection

KQL: AWSCloudTrail query matches EventName=CreateImage with EventSource=ec2.amazonaws.com. SPL: sourcetype=aws:cloudtrail with eventName=CreateImage matched by the image operations filter. IsExternalIP will be 1 if run from outside RFC-1918 space. Alert should fire within the 24-hour detection window.

Test 2 Docker Image Modification and Push to Local Registry
linux

Builds a modified Docker image based on an official base image and pushes it to a local test registry, simulating an adversary backdooring a container image within an internal registry. Requires Docker and a running local registry (docker run -d -p 5000:5000 registry:2). The modification adds a harmless marker file to simulate a backdoor layer insertion.

Command

bash
# Start a local test registry if not running
docker run -d -p 5000:5000 --name df00tech-test-registry registry:2 2>/dev/null || true
# Pull a base image
docker pull alpine:latest
# Create a Dockerfile that adds a 'backdoor' marker layer
cat > /tmp/Dockerfile.implant << 'EOF'
FROM alpine:latest
RUN echo 'implanted-backdoor-marker' > /tmp/.persistence && chmod 755 /tmp/.persistence
CMD ["/bin/sh"]
EOF
# Build the implanted image
docker build -t localhost:5000/alpine:implanted -f /tmp/Dockerfile.implant /tmp
# Push to local registry (simulates internal registry push)
docker push localhost:5000/alpine:implanted

Cleanup

bash
docker rmi localhost:5000/alpine:implanted alpine:latest 2>/dev/null || true
docker stop df00tech-test-registry 2>/dev/null || true
docker rm df00tech-test-registry 2>/dev/null || true
rm -f /tmp/Dockerfile.implant

Expected Telemetry

Docker daemon logs will record the build and push operations. If Docker events are forwarded to Splunk via a log shipper (Filebeat, Splunk UF), events will show image build and push with the image name and tag. In Kubernetes environments, admission controller logs (OPA, Kyverno) will record any attempt to run this image. Container runtime security tools (Falco, Sysdig) will generate events for the image push.

Expected Detection

In environments with Docker audit logging or Falco rules, the push to an internal registry generates an image push event. If the local registry is behind an authenticated proxy with audit logging enabled, the push event including actor and image digest will be captured. In AWS environments using ECR, equivalent events appear in CloudTrail as PutImage and CompleteLayerUpload.

Test 3 AWS ECR Image Push with Modified Tag
linux

Tags an existing image with a name mimicking a legitimate base image and pushes it to an AWS ECR repository, simulating an adversary using masquerading to make a backdoored image appear legitimate. Replace account ID, region, and repository name with valid test values. Requires aws CLI configured with ECR push permissions.

Command

bash
# Set test variables
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
REGION=us-east-1
REPO_NAME=df00tech-detection-test
# Create test ECR repository
aws ecr create-repository --repository-name $REPO_NAME --region $REGION 2>/dev/null || true
# Authenticate Docker to ECR
aws ecr get-login-password --region $REGION | docker login --username AWS --password-stdin $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com
# Pull alpine as a stand-in for an 'implanted' image
docker pull alpine:latest
# Tag it to look like a legitimate internal base image
docker tag alpine:latest $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$REPO_NAME:ubuntu-20.04-base
# Push the 'implanted' image to ECR
docker push $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$REPO_NAME:ubuntu-20.04-base

Cleanup

bash
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
REGION=us-east-1
REPO_NAME=df00tech-detection-test
# Delete the image
aws ecr batch-delete-image --repository-name $REPO_NAME --image-ids imageTag=ubuntu-20.04-base --region $REGION
# Delete the repository
aws ecr delete-repository --repository-name $REPO_NAME --force --region $REGION
docker rmi $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$REPO_NAME:ubuntu-20.04-base alpine:latest 2>/dev/null || true

Expected Telemetry

AWS CloudTrail events: GetAuthorizationToken (ECR login), InitiateLayerUpload (begin push), UploadLayerPart (each image layer), CompleteLayerUpload (layer commit), and PutImage (finalize image with tag) — all with EventSource=ecr.amazonaws.com. All events include the actor IAM ARN, source IP, repository ARN, and user agent. The PutImage event includes imageManifest in requestParameters.

Expected Detection

KQL: AWSCloudTrail query matches PutImage and CompleteLayerUpload with EventSource=ecr.amazonaws.com. SPL: sourcetype=aws:cloudtrail with eventName matching ECR push operations. If pushed from outside RFC-1918 space, IsExternalIP=1 and RiskScore is elevated. The tag name mimicking a different OS (ubuntu-20.04-base on an alpine image) may be caught by image scanning tools.

Test 4 Azure Container Registry Image Import
linux

Uses the Azure CLI to import a public image into a private Azure Container Registry, simulating an adversary using the ImportImage operation to bring a backdoored external image into an internal registry. Requires az CLI authenticated with ACR push permissions. Replace the registry name and resource group with test values.

Command

bash
# Set test variables
REGISTRY_NAME=df00techdetectiontest
RESOURCE_GROUP=df00tech-rg-test
LOCATION=eastus
# Create test ACR (or use existing)
az acr create --resource-group $RESOURCE_GROUP --name $REGISTRY_NAME --sku Basic --location $LOCATION 2>/dev/null || true
# Import a public image into the internal registry (simulates adversary importing a backdoored external image)
az acr import \
  --name $REGISTRY_NAME \
  --source docker.io/library/alpine:latest \
  --image alpine:implanted-test \
  --resource-group $RESOURCE_GROUP

Cleanup

bash
REGISTRY_NAME=df00techdetectiontest
RESOURCE_GROUP=df00tech-rg-test
# Delete the imported image
az acr repository delete --name $REGISTRY_NAME --image alpine:implanted-test --yes 2>/dev/null || true
# Optionally delete the test registry
# az acr delete --name $REGISTRY_NAME --resource-group $RESOURCE_GROUP --yes

Expected Telemetry

Azure Activity Log event: OperationName=microsoft.containerregistry/registries/importimage/action, ResourceType=Microsoft.ContainerRegistry/registries, ActivityStatus=Succeeded. Includes Caller (UPN or service principal), CallerIpAddress, and ResourceId. The Azure Monitor diagnostic logs for ACR will also record the image push with repository, tag, and digest details.

Expected Detection

KQL: AzureActivity query matches tolower(OperationNameValue) containing 'microsoft.containerregistry/registries/importimage' with ActivityStatusValue=Succeeded. SPL: sourcetype=azure:activity with operationName matching the ACR importimage operation. IsExternalIP flag will be set based on CallerIpAddress origin.

Related Detections