Azure defense evasion: deleted logs and disabled Defender
Deleted diagnostic settings, removed Activity Log export, Defender plans set to Free, locks and NSG rules: spotting Azure defense evasion, and what survives.
TL;DR. Attackers in Azure do not delete the Activity Log — they cannot; Azure does not let anyone change or delete its entries. They cut the pipes instead: microsoft.insights/diagnosticSettings/delete on a Key Vault or storage account (resource logs stop), the same operation at subscription scope (the Activity Log export stops), Microsoft.Security/pricings/write with pricingTier: Free (a Defender plan is switched off), Microsoft.Authorization/locks/delete, and NSG or storage firewall rules opened. Every one of those actions is itself recorded in the Activity Log, which Azure keeps for 90 days. The gap they create starts at the timestamp of the deletion.
The most telling event in many Azure intrusions is not the theft, it is the cleanup. A diagnostic setting deleted at 02:55 on a Sunday by the same service principal that read twelve secrets at 02:24 is about as close to a confession as cloud logs get.
Why the Activity Log survives
Microsoft states that Activity Log entries are generated by the system and "you can't change or delete them" (Activity Log in Azure Monitor). They stay available for 90 days regardless of any export configuration. What an attacker can do is:
| Target | Operation | Effect | Recovery |
|---|---|---|---|
| Resource logs of a vault, storage account, NSG… | microsoft.insights/diagnosticSettings/delete on the resource | Data-plane logs stop being written from that moment | Recreate the setting; the gap is permanent |
| Activity Log export (subscription diagnostic setting) | microsoft.insights/diagnosticSettings/delete at subscription scope | The long-term copy (Log Analytics, storage, Event Hubs) stops | The 90-day copy in Azure is still there — export it now |
| Legacy Activity Log export | microsoft.insights/logProfiles/delete | Same, for the legacy mechanism | Same |
| Microsoft Defender for Cloud | Microsoft.Security/pricings/write → Free tier | Plan-specific detections stop | Re-enable; alerts during the gap are lost |
| Resource locks | Microsoft.Authorization/locks/delete | Protected resources become deletable | Restore locks |
| Network controls | NSG rule allowing inbound from * / Internet; storage defaultAction: Allow | Access paths opened | Revert |
Existing log blobs in a storage account can of course be deleted by someone with rights on that account. That shows up as StorageDelete in the storage account's own logs — if those logs were enabled and went elsewhere. This is why the log archive should live in a separate subscription with its own access control.
MITRE ATT&CK tracks these as T1562.008 Disable or Modify Cloud Logs, T1562.001 Disable or Modify Tools and T1562.007 Disable or Modify Cloud Firewall.
Reading a diagnosticSettings/delete event
The resourceId tells you what went dark:
…/providers/Microsoft.KeyVault/vaults/<vault>/providers/microsoft.insights/diagnosticSettings/<name>— a Key Vault stopped sendingAuditEvent.…/providers/Microsoft.Storage/storageAccounts/<account>/…/diagnosticSettings/<name>— storage logs stopped./subscriptions/<id>/providers/microsoft.insights/diagnosticSettings/<name>— no resource group in the path: this is the subscription setting, i.e. the Activity Log export.
The setting's name is often descriptive (kv-audit-to-storage, export-activity-to-sentinel) and helps you find where the logs used to go. Then:
- Note the exact timestamp. It is the end of your data-plane visibility for that resource.
- Look at what the same caller did in the hour before. Deleting logging is usually the last step, not the first.
- If the setting was recreated later, you have a gap, not an absence. Report it as such.
A diagnosticSettings/write can be evasive too: pointing the logs to an attacker-controlled workspace or removing a category silently degrades collection. Review the request body.
Defender for Cloud plans
Defender for Cloud plans are configured per subscription through the pricings API. Switching a plan back to the Free tier appears as Microsoft.Security/pricings/write with "pricingTier": "Free" in the request body. The resource name tells you which plan (VirtualMachines, StorageAccounts, KeyVaults, Arm…). Cost-reduction decisions produce the same event, so check with the owner, then check the timing against other findings.
Defender alerts raised before the plan was disabled are still in the alerts API; export them (export guide). The Azure Forensics analyzer reads that export and turns each alert into an AZ-DEF-001 finding, with the alert severity carried over.
What the analyzer flags
| Rule | Detects | Level |
|---|---|---|
AZ-DE-001 | Diagnostic setting deleted on a resource (path contains a resource group) | High |
AZ-DE-002 | Activity Log export removed (subscription-level diagnostic setting or legacy log profile deleted) | High |
AZ-DE-003 | Defender for Cloud plan set to the Free tier | High |
AZ-DE-004 | Resource lock removed | Medium |
AZ-DE-005 | NSG rule allowing inbound traffic from any source / Internet | Medium |
AZ-ST-004 | Storage firewall opened to all networks | Medium |
AZ-KV-004 | Soft delete or purge protection disabled on a vault, or objects purged | High |
Because the verdict needs at least two high findings for "Compromised", a lone AZ-DE-003 from a finance-driven change leaves you at "Suspicious" — which is the right answer until someone confirms the reason.
Recognising the gap in your own data
Evasion shows up in the data you load, not only in the events:
- A source that stops abruptly. The coverage block shows the first and last event per source. A Key Vault log that ends at 02:55 while the Activity Log continues to 03:30 matches a deletion at 02:55.
- Hourly blobs that stop. In a storage export, the
h=folders for that resource simply end. - Duplicates that end. If you loaded both the storage export and a fresh
azCLI export, the CLI copy continues after the export was cut: that is the 90-day Azure copy doing its job.
In the fictional sample, the Key Vault diagnostic setting is deleted at 02:55:12 and the subscription export at 02:55:40; the storage-exported Activity Log stops there, and only the CLI export shows the deletion of the export itself.
Remediation and hardening
- Recreate deleted diagnostic settings and the Activity Log export; verify data flows again.
- Re-enable Defender plans; review alerts during and after the gap.
- Enforce logging with Azure Policy (deploy-if-not-exists for diagnostic settings) so missing settings are flagged as non-compliant and can be redeployed by a remediation task.
- Keep the log archive in a separate subscription, with delete rights held by very few identities; consider immutable storage for the archive container.
- Restore locks on critical resources and restrict
Microsoft.Authorization/locks/delete.