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.
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