T1612

Build Image on Host

Defense Evasion Last updated:

This detection identifies adversaries building custom container images directly on a compromised host to evade registry-based defenses. Rather than pulling a pre-built malicious image — which would trigger image scanning alerts — attackers issue docker build commands referencing Dockerfiles that download malware or backdoors at build time using RUN curl/wget instructions. The detection monitors for docker build process execution with suspicious argument patterns (temporary directory Dockerfiles, no-cache flags, external URL fetches), Dockerfile creation in writable system directories, and Docker daemon network connections to unexpected destinations during image construction. Correlation across process telemetry, file events, and network activity surfaces the build-then-deploy attack chain used by groups like TeamTNT and WatchDog cryptomining campaigns.

What is T1612 Build Image on Host?

Build Image on Host (T1612) maps to the Defense Evasion tactic — the adversary is trying to avoid being detected in MITRE ATT&CK.

This page provides production-ready detection logic for Build Image on Host, covering the data sources and telemetry it touches: Microsoft Defender for Endpoint. 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
Defense Evasion
Technique
T1612 Build Image on Host
Canonical reference
https://attack.mitre.org/techniques/T1612/
Microsoft Sentinel / Defender
kusto
let TimeWindow = 1d;
let TempPaths = dynamic(["/tmp/", "/dev/shm/", "/var/tmp/", "/run/user/", "\\Temp\\", "\\AppData\\Local\\Temp\\"]);
let SuspiciousParents = dynamic(["bash", "sh", "zsh", "python", "python3", "perl", "ruby", "curl", "wget"]);
// Detect suspicious docker build executions
let DockerBuilds = DeviceProcessEvents
| where TimeGenerated > ago(TimeWindow)
| where (FileName =~ "docker" or FileName =~ "docker.exe")
    and ProcessCommandLine has_any ("build", "image build")
| extend BuildFromTemp = ProcessCommandLine has_any (TempPaths)
| extend BuildNoCache = ProcessCommandLine has "--no-cache"
| extend BuildExternalFile = ProcessCommandLine matches regex @"-f\s+https?://"
| extend SuspiciousParentProc = InitiatingProcessFileName has_any (SuspiciousParents)
| extend RiskScore = toint(BuildFromTemp) * 3
    + toint(BuildNoCache) * 1
    + toint(BuildExternalFile) * 4
    + toint(SuspiciousParentProc) * 2
| where RiskScore >= 2
| project TimeGenerated, DeviceName, AccountName, AccountDomain,
          ProcessCommandLine, InitiatingProcessCommandLine, InitiatingProcessFileName,
          BuildFromTemp, BuildNoCache, BuildExternalFile, SuspiciousParentProc, RiskScore;
// Detect Dockerfile written to suspicious locations
let SuspiciousDockerfiles = DeviceFileEvents
| where TimeGenerated > ago(TimeWindow)
| where (FileName =~ "Dockerfile" or FileName endswith ".dockerfile" or FileName endswith ".Dockerfile")
    and FolderPath has_any (TempPaths)
| extend RiskScore = 3
| project TimeGenerated, DeviceName, AccountName, FolderPath, FileName,
          InitiatingProcessCommandLine, RiskScore;
// Detect docker daemon making external connections during potential build phase
let DockerNetworkBuild = DeviceNetworkEvents
| where TimeGenerated > ago(TimeWindow)
| where InitiatingProcessFileName =~ "dockerd"
    and RemotePort in (80, 443, 8080, 8443)
    and not(ipv4_is_private(RemoteIP))
    and not(RemoteUrl has_any ("docker.io", "hub.docker.com", "registry-1.docker.io",
                               "production.cloudflare.docker.com", "auth.docker.io",
                               "registry.k8s.io", "gcr.io", "mcr.microsoft.com",
                               "quay.io", "ghcr.io"))
| extend RiskScore = 2
| project TimeGenerated, DeviceName, RemoteIP, RemoteUrl, RemotePort,
          InitiatingProcessCommandLine, RiskScore;
// Union all findings
DockerBuilds
| project TimeGenerated, DeviceName, AccountName, Description = "Suspicious docker build execution",
          Detail = ProcessCommandLine, RiskScore
| union (
    SuspiciousDockerfiles
    | project TimeGenerated, DeviceName, AccountName, Description = "Dockerfile written to temp path",
              Detail = strcat(FolderPath, FileName), RiskScore
)
| union (
    DockerNetworkBuild
    | project TimeGenerated, DeviceName, AccountName = "", Description = "Docker daemon external connection during build",
              Detail = strcat(RemoteIP, " (", RemoteUrl, "):", tostring(RemotePort)), RiskScore
)
| order by TimeGenerated desc

Detects suspicious container image builds on the host by monitoring docker build process executions with high-risk argument patterns (Dockerfiles from temp directories, external file references, no-cache flags combined with suspicious parent processes), Dockerfile creation in writable system paths, and Docker daemon making network connections to non-registry external hosts during what may be a build phase. Risk scoring prioritizes combinations most consistent with adversary build-to-deploy workflows.

high severity medium confidence

Data Sources

Microsoft Defender for Endpoint

Required Tables

DeviceProcessEvents DeviceFileEvents DeviceNetworkEvents

False Positives

  • Legitimate CI/CD pipeline agents (Jenkins, GitLab Runner, GitHub Actions self-hosted) that build images on the host using --no-cache for reproducibility
  • Developer workstations with Docker Desktop where developers routinely build images from ~/Downloads or temp directories during testing
  • Container security scanning tools (Trivy, Grype, Snyk) that build test images from temporary Dockerfiles to verify vulnerability detection coverage
  • Infrastructure-as-code tools like Packer or Terraform using Docker builder that create Dockerfiles in temp locations as part of their workflow

Sigma rule & cross-platform mapping

The detection logic for Build Image on Host (T1612) 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:
  category: process_creation
  product: windows

Browse the community-maintained Sigma rules for this technique:


Testing Methodology

Validate this detection against 3 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 1Build Custom Image with Embedded Payload Simulation

    Expected signal: DeviceProcessEvents: FileName=docker, ProcessCommandLine contains 'build --no-cache -t atomictest_t1612' and '/tmp/atomictest_t1612/Dockerfile'. DeviceNetworkEvents: dockerd process making connection to example.com:443 during RUN curl step.

  2. Test 2Docker API Remote Build Request Simulation

    Expected signal: Auditd: access to /var/run/docker.sock by curl process. Docker daemon logs (journalctl -u docker): POST /v1.43/build request logged. DeviceProcessEvents may not show docker CLI — hunting via socket access rules is required for API-based builds.

  3. Test 3Build Privileged Escape-Ready Container Image

    Expected signal: DeviceProcessEvents: docker run with ProcessCommandLine containing '-v /var/run/docker.sock:/var/run/docker.sock'. Sysmon EventCode 11: file access to /var/run/docker.sock from container process namespace.

Unlock Pro Content

Get the full detection package for T1612 including response playbook, investigation guide, and atomic red team tests.

Response PlaybookInvestigation GuideHunting QueriesAtomic Red Team TestsTuning Guidance

Related Detections