T1612

Build Image on Host

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.

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

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