T1221

Template Injection

Adversaries abuse template references embedded in Office Open XML (OOXML) documents and RTF files to conceal and deliver malicious payloads. DOCX, XLSX, and PPTX files are ZIP archives containing an XML relationship file (word/_rels/document.xml.rels) that can reference an external template URL via an attachedTemplate relationship. When the document is opened, the Office application fetches the remote template, which may deliver VBA macros, exploits, or shellcode that are absent from the original lure document — bypassing static file analysis. RTF files can be modified to include a \*\template control word pointing to a remote URL, triggering a fetch on open. Both vectors are used to deliver malicious macros (APT28 remote template macro delivery), execute exploits (Confucius, WarzoneRAT via RTF exploit embedding), or capture NTLM credentials by injecting SMB UNC paths that trigger forced authentication (Dragonfly, DarkHydrus/Phishery). Real-world campaigns frequently deliver these lures via phishing (T1566) or tainted shared content (T1080). The technique is effective because the initial document contains no traditional indicators — no embedded VBA, no OLE streams, no scripts — making gateway scanning and sandboxes that do not perform dynamic network fetching ineffective.

Microsoft Sentinel / Defender
kusto
let OfficeApps = dynamic(["winword.exe", "excel.exe", "powerpnt.exe", "mspub.exe", "msaccess.exe", "visio.exe"]);
let MicrosoftInfra = dynamic([
  "microsoft.com", "office.com", "live.com", "microsoftonline.com",
  "windows.net", "sharepoint.com", "officecdn.microsoft.com",
  "officecdna.microsoft.com", "skype.com", "bing.com", "msecnd.net",
  "msftncsi.com", "trafficmanager.net", "azure.com", "azurefd.net"
]);
// Branch 1: Office apps fetching remote templates via HTTP/HTTPS from non-Microsoft hosts
let RemoteHTTPFetch = DeviceNetworkEvents
| where Timestamp > ago(24h)
| where InitiatingProcessFileName in~ (OfficeApps)
| where RemotePort in (80, 443, 8080, 8443)
| where RemoteIPType == "Public"
| where not(RemoteUrl has_any (MicrosoftInfra))
| extend AlertType = "RemoteTemplateFetch"
| extend RiskDetail = strcat("Office process ", InitiatingProcessFileName, " fetched external URL: ", RemoteUrl)
| project Timestamp, DeviceName, AccountName, InitiatingProcessFileName,
          InitiatingProcessCommandLine, InitiatingProcessId,
          RemoteIP, RemotePort, RemoteUrl, AlertType, RiskDetail;
// Branch 2: Office apps connecting to SMB port — forced NTLM authentication
let ForcedAuthSMB = DeviceNetworkEvents
| where Timestamp > ago(24h)
| where InitiatingProcessFileName in~ (OfficeApps)
| where RemotePort == 445
| where RemoteIPType in ("Public", "Private")
| extend AlertType = "ForcedAuthSMB_NTLMCapture"
| extend RiskDetail = strcat("Office process ", InitiatingProcessFileName, " initiated SMB connection to ", RemoteIP, ":445 — potential NTLM hash capture")
| project Timestamp, DeviceName, AccountName, InitiatingProcessFileName,
          InitiatingProcessCommandLine, InitiatingProcessId,
          RemoteIP, RemotePort, RemoteUrl, AlertType, RiskDetail;
// Branch 3: Child process spawned directly by Office — indicates payload execution post-template-load
let OfficeChildExec = DeviceProcessEvents
| where Timestamp > ago(24h)
| where InitiatingProcessFileName in~ (OfficeApps)
| where FileName in~ ("cmd.exe", "powershell.exe", "pwsh.exe", "wscript.exe",
                       "cscript.exe", "mshta.exe", "rundll32.exe", "regsvr32.exe",
                       "certutil.exe", "bitsadmin.exe", "wmic.exe", "msiexec.exe",
                       "svchost.exe", "conhost.exe")
| extend AlertType = "OfficeChildProcess_PostTemplateExec"
| extend RiskDetail = strcat("Office process ", InitiatingProcessFileName, " spawned ", FileName, " — possible macro/exploit execution after template load")
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine,
          InitiatingProcessFileName, InitiatingProcessCommandLine,
          AlertType, RiskDetail;
RemoteHTTPFetch
| union ForcedAuthSMB
| union (OfficeChildExec | project Timestamp, DeviceName, AccountName,
          InitiatingProcessFileName, InitiatingProcessCommandLine,
          InitiatingProcessId = "", RemoteIP = "", RemotePort = 0,
          RemoteUrl = "", AlertType, RiskDetail)
| sort by Timestamp desc
high severity high confidence

Data Sources

Network Traffic: Network Connection Creation Process: Process Creation Microsoft Defender for Endpoint

Required Tables

DeviceNetworkEvents DeviceProcessEvents

False Positives

  • Corporate document management systems (SharePoint on-premise, Confluence, custom DMS) that serve legitimate .dotx/.dotm template files to Office clients — add their hostnames/IPs to the exclusion list
  • Office Click-to-Run (C2R) update and telemetry processes share the same process names and may make external connections — validate against known Microsoft CDN IP ranges
  • Macro-enabled templates in enterprise environments where business workflows legitimately use remote templates (e.g., HR or finance template servers) — allowlist specific internal template server FQDNs
  • Branch 3 child process detection will fire on legitimate Office add-ins, COM automation, and scripted Office workflows (e.g., VBA calling WScript for file operations) — baseline expected parent-child pairs per environment
  • RTF documents produced by legal or financial software platforms that embed legitimate template references to external servers

Unlock Pro Content

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

Response PlaybookInvestigation GuideHunting QueriesAtomic Red Team TestsTuning Guidance

Related Detections