Adversaries may exfiltrate mailbox data by accessing suspicious files on an IIS/OWA server, leveraging T1567 to covertly transfer sensitive information. SOC teams should proactively hunt for this behavior to detect potential data exfiltration attempts in their Azure Sentinel environment.
KQL Query
let excludeIps = dynamic(["127.0.0.1", "::1"]);
let scriptingExt = dynamic(["aspx", "ashx", "asp"]);
W3CIISLog
| where csUriStem contains "/owa/"
//The actor pulls a file back but won't send it any URI params
| where isempty(csUriQuery)
| extend file_ext = tostring(split(csUriStem, ".")[-1])
//Giving your file a known scripting extension will throw an error
//rather than just serving the file as it will try to interpret the script
| where file_ext !in~ (scriptingExt)
//The actor was seen using image files, but we go wider in case they change this behaviour
//| where file_ext in~ ("jpg", "jpeg", "png", "bmp")
| extend file_name = tostring(split(csUriStem, "/")[-1])
| where file_name != ""
| where cIP !in~ (excludeIps)
//Exclude local addresses, using the ipv4_is_private operator
| where ipv4_is_private(cIP) == false and cIP !startswith "fe80" and cIP !startswith "::" and cIP !startswith "127."
| project file_ext, csUriStem, file_name, Computer, cIP, sIP, TenantId, TimeGenerated
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), dcount(cIP), AccessingIPs=make_set(cIP), AccessTimes=make_set(TimeGenerated), Access=count() by TenantId, file_name, Computer, csUriStem
//Collection of the exfiltration will occur only once, lets check for 2 accesses in case they mess up
//Tailor this for hunting
| where Access <= 2 and dcount_cIP == 1
| extend timestamp = StartTime, HostCustomEntity = Computer
id: a523786c-8382-4029-80e9-f1a7ecd067c1
name: Suspect Mailbox Export on IIS/OWA
description: |
'The hunting query looks for suspicious files accessed on a IIS server that might indicate exfiltration hosting. This technique has been observed when exporting mailbox files from OWA servers.'
description_detailed: |
'The hunting query looks for suspicious files accessed on a IIS server that might indicate exfiltration hosting.
This technique has been observed when exporting mailbox files from OWA servers.
Reference: https://www.volexity.com/blog/2020/12/14/dark-halo-leverages-solarwinds-compromise-to-breach-organizations/'
severity: Low
requiredDataConnectors:
- connectorId: AzureMonitor(IIS)
dataTypes:
- W3CIISLog
tactics:
- Exfiltration
relevantTechniques:
- T1567
tags:
- Solorigate
- NOBELIUM
query: |
let excludeIps = dynamic(["127.0.0.1", "::1"]);
let scriptingExt = dynamic(["aspx", "ashx", "asp"]);
W3CIISLog
| where csUriStem contains "/owa/"
//The actor pulls a file back but won't send it any URI params
| where isempty(csUriQuery)
| extend file_ext = tostring(split(csUriStem, ".")[-1])
//Giving your file a known scripting extension will throw an error
//rather than just serving the file as it will try to interpret the script
| where file_ext !in~ (scriptingExt)
//The actor was seen using image files, but we go wider in case they change this behaviour
//| where file_ext in~ ("jpg", "jpeg", "png", "bmp")
| extend file_name = tostring(split(csUriStem, "/")[-1])
| where file_name != ""
| where cIP !in~ (excludeIps)
//Exclude local addresses, using the ipv4_is_private operator
| where ipv4_is_private(cIP) == false and cIP !startswith "fe80" and cIP !startswith "::" and cIP !startswith "127."
| project file_ext, csUriStem, file_name, Computer, cIP, sIP, TenantId, TimeGenerated
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), dcount(cIP), AccessingIPs=make_set(cIP), AccessTimes=make_set(TimeGenerated), Access=count() by TenantId, file_name, Computer, csUriStem
//Collection of the exfiltration will occur only once, lets check for 2 accesses in case they mess up
//Tailor this for hunting
| where Access <= 2 and dcount_cIP == 1
| extend timestamp = StartTime, HostCustomEntity = Computer
entityMappings:
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: Computer
version: 1.0.1
metadata:
source:
kind: Community
author:
name: Pete Bryan
support:
tier: Community
categories:
domains: [ "Security - Threat Protection" ]
| Sentinel Table | Notes |
|---|---|
W3CIISLog | Ensure this data connector is enabled |
Scenario: Scheduled Backup Job Exporting Mailbox Data
Description: A legitimate scheduled backup job uses a tool like Veeam Backup & Replication or Microsoft Data Protection Manager (DPM) to export mailbox data from Exchange through IIS/OWA.
Filter/Exclusion: Exclude activity associated with known backup tools or processes using the process.name field, e.g., process.name:"VeeamBackup.exe" or process.name:"DPM.exe".
Scenario: Admin Performing Mailbox Export for Compliance
Description: An administrator uses Microsoft Exchange Management Shell (EMS) or PowerShell to export mailbox data for compliance or legal reasons.
Filter/Exclusion: Exclude activity initiated by admin accounts with elevated privileges using the user.account field, e.g., user.account:"[email protected]" or user.account:"DomainAdmins".
Scenario: Integration with Third-Party Email Archiving Tool
Description: A third-party email archiving tool like Sparrow Mail Archiving or Zimbra Collaboration connects to IIS/OWA to archive mailbox data.
Filter/Exclusion: Exclude traffic from known archiving tools using the process.name or destination.address field, e.g., process.name:"SparrowArchiver.exe" or destination.address:"192.168.1.100".
Scenario: System Maintenance Task Exporting Mailbox Data
Description: A system maintenance task, such as Exchange Online PowerShell or Exchange Management Console (EMC), is used to export mailbox data for system health checks or migration.
Filter/Exclusion: Exclude activity related to system maintenance tasks using the process.name or command_line field, e.g., `process