Query Details

HUNT 03 Storage Blob Exfiltration

Query

// Hunt     : Hunt - Storage Blob High-Volume Read by Single IP (Potential Exfiltration)
// Tactics  : Exfiltration
// MITRE    : T1530
// Purpose  : Identify IPs that performed high-volume blob reads (>500 reads/hr or >1 GB/hr). Correlate with SAS token generation (Rule-04) to confirm exfiltration via ephemeral SAS credentials.
//==========================================================================================

StorageBlobLogs
| where TimeGenerated > ago(30d)
| where OperationName == "GetBlob"
| where StatusCode == "200"
| where isnotempty(CallerIpAddress)
| where CallerIpAddress !startswith "168.63." and CallerIpAddress !startswith "169.254."
| summarize
    ReadCount = count(),
    TotalBytesGB = round(sum(ResponseBodySize) / 1073741824.0, 2),
    DistinctBlobs = dcount(ObjectKey),
    AuthTypes = make_set(AuthenticationType, 3),
    Requesters = make_set(RequesterObjectId, 5),
    StorageAccounts = make_set(AccountName, 5),
    EarliestRead = min(TimeGenerated),
    LatestRead = max(TimeGenerated)
    by CallerIpAddress, bin(TimeGenerated, 1h)
// Tuned: raised read-count floor 500 -> 1000/hr (busy app/CDN tiers routinely exceed 500);
// kept the 1 GB/hr byte floor; added DistinctBlobs >= 200 to catch broad low-byte object
// enumeration that stays under both volume floors. Surfaces RequesterObjectId + AuthTypes
// so anonymous/SAS egress can be separated from AAD-authenticated app reads.
| where ReadCount > 1000 or TotalBytesGB > 1.0 or DistinctBlobs >= 200
| order by TotalBytesGB desc

Explanation

This query is designed to detect potential data exfiltration from storage blobs by identifying IP addresses that perform a high volume of blob reads. Here's a simplified breakdown:

  1. Data Source: The query analyzes logs from storage blob operations over the past 30 days.

  2. Operation Focus: It specifically looks at successful "GetBlob" operations, which indicate data reads.

  3. IP Filtering: It excludes internal Azure IP addresses (those starting with "168.63." and "169.254.") to focus on potential external threats.

  4. Data Aggregation: For each IP address, the query calculates:

    • The total number of blob reads (ReadCount).
    • The total data volume read in gigabytes (TotalBytesGB).
    • The number of distinct blobs accessed (DistinctBlobs).
    • The types of authentication used (AuthTypes).
    • The IDs of requesters (Requesters).
    • The storage accounts accessed (StorageAccounts).
    • The time range of the reads (EarliestRead and LatestRead).
  5. Thresholds for Alerts: It flags IPs that:

    • Perform more than 1000 reads per hour.
    • Read more than 1 GB of data per hour.
    • Access 200 or more distinct blobs.
  6. Purpose: The goal is to identify potential data exfiltration activities, especially those using ephemeral SAS credentials, by correlating high-volume reads with SAS token generation.

  7. Output: The results are sorted by the total data volume read, highlighting the most significant potential threats first.

Details

David Alonso profile picture

David Alonso

Released: July 27, 2026

Tables

StorageBlobLogs

Keywords

StorageBlobLogsCallerIpAddressResponseBodySizeObjectKeyAuthenticationTypeRequesterIdAccountNameTimeGeneratedStatusCodeOperation

Operators

StorageBlobLogswhereago==isnotempty!startswithsummarizecountroundsum/dcountmake_setminmaxbybinorder bydesc

MITRE Techniques

Actions

GitHub