# Az - Storage Accounts & Blobs

{{#include ../../../banners/hacktricks-training.md}}

## 基本情報

Azure Storage Accounts は、スケーラブルで安全かつ高可用なクラウド **storage for various data types** を提供する Microsoft Azure の基本サービスで、blobs (binary large objects)、files、queues、tables を含みます。これらは単一の namespace 配下でこれらの異なる storage services をまとめるコンテナとして機能し、管理を容易にします。

**主な設定オプション**:

- すべてのストレージアカウントは **Azure 全体で一意の名前** を持つ必要があります。
- すべてのストレージアカウントは **リージョン** または Azure extended zone にデプロイされます
- より良いパフォーマンスのためにストレージアカウントの **premium** バージョンを選択可能です
- ラック、ディスク、データセンターの**障害**から保護するために **4 種類の冗長化** から選択可能です。

**セキュリティ設定オプション**:

- **Require secure transfer for REST API operations**: ストレージとの通信に TLS を必須にします
- **Allows enabling anonymous access on individual containers**: 無効にすると、将来的にコンテナ単位での匿名アクセスを有効にできなくなります
- **Enable storage account key access**: 無効化すると Shared Keys によるアクセスが禁止されます
- **Minimum TLS version**
- **Permitted scope for copy operations**: 任意のストレージアカウントから、同一 Entra テナント内の任意のストレージアカウントから、あるいは同一仮想ネットワーク内の private endpoints を持つストレージアカウントから許可する、などの選択が可能です。

**Blob Storage オプション**:

- **Allow cross-tenant replication**
- **Access tier**: Hot（頻繁にアクセスされるデータ）、Cool、Cold（稀にアクセスされるデータ）

**ネットワーク設定オプション**:

- **Network access**:
- 全ネットワークから許可
- 選択した virtual networks と IP アドレスから許可
- パブリックアクセスを無効にしてプライベートアクセスを使用
- **Private endpoints**: 仮想ネットワークからストレージアカウントへのプライベート接続を許可します

**データ保護オプション**:

- **Point-in-time restore for containers**: コンテナを以前の状態に復元可能にします
- これは versioning、change feed、blob soft delete の有効化を必要とします。
- **Enable soft delete for blobs**: 削除された blob（上書きされたものを含む）に対して日単位の保持期間を設定します
- **Enable soft delete for containers**: 削除されたコンテナに対して日単位の保持期間を設定します
- **Enable soft delete for file shares**: 削除された file shares に対して日単位の保持期間を設定します
- **Enable versioning for blobs**: blob の以前のバージョンを保持します
- **Enable blob change feed**: blob の作成、変更、削除の変更ログを保持します
- **Enable version-level immutability support**: アカウント レベルでの時間ベースの保持ポリシーを設定し、すべての blob バージョンに適用することを可能にします。
- Version-level immutability support と point-in-time restore for containers は同時に有効にできません。

**暗号化設定オプション**:

- **Encryption type**: Microsoft-managed keys (MMK) または Customer-managed keys (CMK) を使用可能です
- **Enable infrastructure encryption**: データを「より安全に」二重に暗号化することを可能にします

### Storage endpoints

<table data-header-hidden><thead><tr><th width="197">Storage Service</th><th>Endpoint</th></tr></thead><tbody><tr><td><strong>Blob storage</strong></td><td><code>https://<storage-account>.blob.core.windows.net</code><br><br><code>https://<stg-acc>.blob.core.windows.net/<container-name>?restype=container&comp=list</code></td></tr><tr><td><strong>Data Lake Storage</strong></td><td><code>https://<storage-account>.dfs.core.windows.net</code></td></tr><tr><td><strong>Azure Files</strong></td><td><code>https://<storage-account>.file.core.windows.net</code></td></tr><tr><td><strong>Queue storage</strong></td><td><code>https://<storage-account>.queue.core.windows.net</code></td></tr><tr><td><strong>Table storage</strong></td><td><code>https://<storage-account>.table.core.windows.net</code></td></tr></tbody></table>

### Public Exposure

"Allow Blob public access" が **有効**（デフォルトは無効）の場合、コンテナ作成時に以下が可能です:

- **public access to read blobs**（名前を知っていれば読み取り可能）を許可
- **List container blobs** および **read** する
- 完全に **private** にする

<figure><img src="https://lh7-rt.googleusercontent.com/slidesz/AGV_vUfoetUnYBPWQpRrWNnnlbqWpl8Rdoaeg5uBrCVlvcNDlnKwQHjZe8nUb2SfPspBgbu-lCZLmUei-hFi_Jl2eKbaxUtBGTjdUSDmkrcwr90VZkmuMjk9tyh92p75btfyzGiUTa0-=s2048?key=m8TV59TrCFPlkiNnmhYx3aZt" alt=""><figcaption></figcaption></figure>

### Static website (`$web`) exposure & leaked secrets

- **Static websites** は特別な `$web` コンテナからリージョン固有のエンドポイント（例: `https://<account>.z13.web.core.windows.net/`）経由で配信されます。
- `$web` コンテナは blob API 経由で `publicAccess: null` を返す場合がありますが、static site エンドポイント経由でファイルに到達できるため、そこに config/IaC アーティファクトを置くと secrets が leak する可能性があります。
- クイック監査ワークフロー:
```bash
# Identify storage accounts with static website hosting enabled
az storage blob service-properties show --account-name <acc-name> --auth-mode login
# Enumerate containers (including $web) and their public flags
az storage container list --account-name <acc-name> --auth-mode login
# List files served by the static site even when publicAccess is null
az storage blob list --container-name '$web' --account-name <acc-name> --auth-mode login
# Pull suspicious files directly (e.g., IaC tfvars containing secrets/SAS)
az storage blob download -c '$web' --name iac/terraform.tfvars --file /dev/stdout --account-name <acc-name> --auth-mode login
```
### 匿名 blob の公開を監査

- **データを公開する可能性のある storage accounts を特定する**: `az storage account list | jq -r '.[] | select(.properties.allowBlobPublicAccess==true) | .name'`。`allowBlobPublicAccess` が `false` の場合、コンテナを公開に設定できません。
- **リスクのあるアカウントを確認してフラグや他の脆弱な設定を検証する**: `az storage account show --name <acc> --query '{allow:properties.allowBlobPublicAccess, minTls:properties.minimumTlsVersion}'`。
- **フラグが有効なアカウントでのコンテナ単位の公開状況を列挙する**:
```bash
az storage container list --account-name <acc> \
--query '[].{name:name, access:properties.publicAccess}'
```
- `"Blob"`: 匿名読み取りが許可される **ただし blob の名前が分かっている場合のみ**（一覧表示不可）。
- `"Container"`: 匿名で **一覧取得 + 読み取り** が可能（全ての blob）。
- `null`: 非公開; 認証が必要。
- **資格情報なしでアクセスを証明する**:
- もし `publicAccess` が `Container` の場合、匿名での一覧取得が可能です: `curl "https://<acc>.blob.core.windows.net/<container>?restype=container&comp=list"`.
- `Blob` と `Container` の両方について、名前が判明している場合は匿名での blob ダウンロードが可能です:
```bash
az storage blob download -c <container> -n <blob> --account-name <acc> --file /dev/stdout
# or via raw HTTP
curl "https://<acc>.blob.core.windows.net/<container>/<blob>"
```
### Storage に接続する

接続できる **storage** を見つけた場合、ツール [**Microsoft Azure Storage Explorer**](https://azure.microsoft.com/es-es/products/storage/storage-explorer/) を使用できます。

## Storage へのアクセス <a href="#about-blob-storage" id="about-blob-storage"></a>

### RBAC

Entra ID プリンシパルを **RBAC roles** と組み合わせて storage accounts にアクセスすることが可能で、これは推奨される方法です。

### Access Keys

storage accounts にはアクセスに使用できる access keys があり、これは **完全なアクセス権** を storage account に与えます。

<figure><img src="../../../images/image (5).png" alt=""><figcaption></figcaption></figure>

### **Shared Keys & Lite Shared Keys**

access keys で署名された [**generate Shared Keys**](https://learn.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key) を生成して、signed URL 経由で特定のリソースへのアクセスを認可することが可能です。

> [!NOTE]
> `CanonicalizedResource` 部分は storage services のリソース (URI) を表します。URL の任意の部分がエンコードされている場合、`CanonicalizedResource` 内でもエンコードされている必要があります。

> [!NOTE]
> これは **デフォルトで `az` cli によって使用されます**（リクエストの認証のため）。Entra ID プリンシパルの資格情報を使わせるにはパラメータ `--auth-mode login` を指定してください。

- 次の情報に署名して、**shared key for blob, queue and file services** を生成できます:
```bash
StringToSign = VERB + "\n" +
Content-Encoding + "\n" +
Content-Language + "\n" +
Content-Length + "\n" +
Content-MD5 + "\n" +
Content-Type + "\n" +
Date + "\n" +
If-Modified-Since + "\n" +
If-Match + "\n" +
If-None-Match + "\n" +
If-Unmodified-Since + "\n" +
Range + "\n" +
CanonicalizedHeaders +
CanonicalizedResource;
```
- 次の情報に署名することで、**テーブルサービス用の共有キー**を生成できます:
```bash
StringToSign = VERB + "\n" +
Content-MD5 + "\n" +
Content-Type + "\n" +
Date + "\n" +
CanonicalizedResource;
```
- 次の情報に署名することで、**lite shared key for blob, queue and file services** を生成できます:
```bash
StringToSign = VERB + "\n" +
Content-MD5 + "\n" +
Content-Type + "\n" +
Date + "\n" +
CanonicalizedHeaders +
CanonicalizedResource;
```
- 次の情報に署名することで、**lite shared key for table services** を生成できます:
```bash
StringToSign = Date + "\n"
CanonicalizedResource
```
次に、キーを使用するには、次の構文に従って Authorization header に指定します:
```bash
Authorization="[SharedKey|SharedKeyLite] <AccountName>:<Signature>"
#e.g.
Authorization: SharedKey myaccount:ctzMq410TV3wS7upTBcunJTDLEJwMAZuFPfr0mrrA08=

PUT http://myaccount/mycontainer?restype=container&timeout=30 HTTP/1.1
x-ms-version: 2014-02-14
x-ms-date: Fri, 26 Jun 2015 23:39:12 GMT
Authorization: SharedKey myaccount:ctzMq410TV3wS7upTBcunJTDLEJwMAZuFPfr0mrrA08=
Content-Length: 0
```
### **Shared Access Signature** (SAS)

Shared Access Signatures (SAS) は、ストレージアカウントのアクセスキーを公開することなく、特定のリソースに対するアクセス権限を限定的かつ時間制限付きで付与する安全なURLです。アクセスキーがすべてのリソースに対するフル管理アクセスを提供する一方で、SAS は読み取りや書き込みなどの権限を指定し、有効期限を設定することできめ細かい制御を可能にします。

#### SAS Types

- **User delegation SAS**: これは **Entra ID principal** から作成され、SAS に署名してユーザーからSASへ権限を委譲します。**blob and data lake storage** でのみ使用できます ([docs](https://learn.microsoft.com/en-us/rest/api/storageservices/create-user-delegation-sas)). 生成された user delegated SAS をすべて **revoke** することが可能です。
- ユーザーが持つ権限より「多い」権限を持つ delegation SAS を生成できる場合があっても、principal 自身にその権限がなければ動作しません（no privesc）。
- **Service SAS**: これはストレージアカウントのいずれかの **access keys** を使って署名されます。単一のストレージサービス内の特定のリソースへのアクセスを付与するために使用できます。キーが更新されると、SAS は無効になります。
- **Account SAS**: これもストレージアカウントの **access keys** で署名されます。Blob, Queue, Table, File といったストレージアカウントのサービス全体に対するリソースアクセスを付与でき、サービスレベルの操作を含めることができます。

A SAS URL signed by an **access key** looks like this:

- `https://<container_name>.blob.core.windows.net/newcontainer?sp=r&st=2021-09-26T18:15:21Z&se=2021-10-27T02:14:21Z&spr=https&sv=2021-07-08&sr=c&sig=7S%2BZySOgy4aA3Dk0V1cJyTSIf1cW%2Fu3WFkhHV32%2B4PE%3D`

A SAS URL signed as a **user delegation** looks like this:

- `https://<container_name>.blob.core.windows.net/testing-container?sp=r&st=2024-11-22T15:07:40Z&se=2024-11-22T23:07:40Z&skoid=d77c71a1-96e7-483d-bd51-bd753aa66e62&sktid=fdd066e1-ee37-49bc-b08f-d0e152119b04&skt=2024-11-22T15:07:40Z&ske=2024-11-22T23:07:40Z&sks=b&skv=2022-11-02&spr=https&sv=2022-11-02&sr=c&sig=7s5dJyeE6klUNRulUj9TNL0tMj2K7mtxyRc97xbYDqs%3D`

Note some **http params**:

- The **`se`** param indicates the **expiration date** of the SAS
- The **`sp`** param indicates the **permissions** of the SAS
- The **`sig`** is the **signature** validating the SAS

#### SAS permissions

SAS を生成する際には付与する権限を指定する必要があります。SAS を生成するオブジェクトによって含められる権限は異なります。例えば：

- (a)dd, (c)reate, (d)elete, (e)xecute, (f)ilter_by_tags, (i)set_immutability_policy, (l)ist, (m)ove, (r)ead, (t)ag, (w)rite, (x)delete_previous_version, (y)permanent_delete

## SFTP Support for Azure Blob Storage

Azure Blob Storage は現在 SSH File Transfer Protocol (SFTP) をサポートしており、カスタムソリューションやサードパーティ製品を必要とせずに Blob Storage へ直接セキュアなファイル転送と管理が可能です。

### Key Features

- Protocol Support: SFTP は hierarchical namespace (HNS) を有効化した Blob Storage アカウントで動作します。これにより blobs をディレクトリやサブディレクトリで整理し、ナビゲーションが容易になります。
- Security: SFTP は認証に local user identities を使用し、RBAC や ABAC と統合しません。各ローカルユーザーは以下の方法で認証できます:
  - Azure-generated passwords
  - Public-private SSH key pairs
- Granular Permissions: Read, Write, Delete, List といった権限をローカルユーザーに対して最大 100 コンテナまで割り当てることができます。
- Networking Considerations: SFTP 接続はポート 22 を通じて行われます。Azure はファイアウォール、private endpoints、virtual networks などのネットワーク構成で SFTP トラフィックを保護することをサポートします。

### Setup Requirements

- Hierarchical Namespace: HNS はストレージアカウント作成時に有効にする必要があります。
- Supported Encryption: Microsoft Security Development Lifecycle (SDL) 承認済みの暗号アルゴリズムが必要です（例: rsa-sha2-256, ecdsa-sha2-nistp256）。
- SFTP Configuration:
  - Enable SFTP on the storage account.
  - Create local user identities with appropriate permissions.
  - Configure home directories for users to define their starting location within the container.

### Permissions

| Permission             | Symbol | Description                          |
| ---------------------- | ------ | ------------------------------------ |
| **Read**               | `r`    | ファイル内容の読み取り。             |
| **Write**              | `w`    | ファイルのアップロードおよびディレクトリ作成。 |
| **List**               | `l`    | ディレクトリの内容を一覧表示。       |
| **Delete**             | `d`    | ファイルやディレクトリの削除。       |
| **Create**             | `c`    | ファイルやディレクトリの作成。       |
| **Modify Ownership**   | `o`    | 所有ユーザーまたはグループの変更。   |
| **Modify Permissions** | `p`    | ファイルやディレクトリの ACL を変更。 |

## Enumeration

{{#tabs }}
{{#tab name="az cli" }}

<details>
<summary>az cli enumeration</summary>
```bash
# Get storage accounts
az storage account list #Get the account name from here

# BLOB STORAGE
## List containers
az storage container list --account-name <name>
## Check if public access is allowed
az storage container show-permission \
--account-name <acc-name> \
-n <container-name>
## Make a container public
az storage container set-permission \
--public-access container \
--account-name <acc-name> \
-n <container-name>
## List blobs in a container
az storage blob list \
--container-name <container name> \
--account-name <account name>
## Download blob
az storage blob download \
--account-name <account name> \
--container-name <container name> \
--name <blob name> \
--file </path/to/local/file>
## Create container policy
az storage container policy create \
--account-name mystorageaccount \
--container-name mycontainer \
--name fullaccesspolicy \
--permissions racwdl \
--start 2023-11-22T00:00Z \
--expiry 2024-11-22T00:00Z

# QUEUE
az storage queue list --account-name <name>
az storage message peek --account-name <name> --queue-name <queue-name>

# ACCESS KEYS
az storage account keys list --account-name <name>
## Check key policies (expiration time?)
az storage account show -n <name> --query "{KeyPolicy:keyPolicy}"
## Once having the key, it's possible to use it with the argument --account-key
## Enum blobs with account key
az storage blob list \
--container-name <container name> \
--account-name <account name> \
--account-key "ZrF40pkVKvWPUr[...]v7LZw=="
## Download a file using an account key
az storage blob download \
--account-name <account name> \
--account-key "ZrF40pkVKvWPUr[...]v7LZw==" \
--container-name <container name> \
--name <blob name> \
--file </path/to/local/file>
## Upload a file using an account key
az storage blob upload \
--account-name <account name> \
--account-key "ZrF40pkVKvWPUr[...]v7LZw==" \
--container-name <container name> \
--file </path/to/local/file>

# SAS
## List access policies
az storage <container|queue|share|table> policy list \
--account-name <acc name> \
--container-name <container name>

## Generate SAS with all permissions using an access key
az storage <container|queue|share|table|blob> generate-sas \
--permissions acdefilmrtwxy \
--expiry 2024-12-31T23:59:00Z \
--account-name <acc-name> \
-n <container-name>

## Generate SAS with all permissions using via user delegation
az storage <container|queue|share|table|blob> generate-sas \
--permissions acdefilmrtwxy \
--expiry 2024-12-31T23:59:00Z \
--account-name <acc-name> \
--as-user --auth-mode login \
-n <container-name>

## Generate account SAS
az storage account generate-sas \
--expiry 2024-12-31T23:59:00Z \
--account-name <acc-name>  \
--services qt \
--resource-types sco \
--permissions acdfilrtuwxy

## Use the returned SAS key with the param --sas-token
## e.g.
az storage blob show \
--account-name <account name> \
--container-name <container name> \
--sas-token 'se=2024-12-31T23%3A59%3A00Z&sp=racwdxyltfmei&sv=2022-11-02&sr=c&sig=ym%2Bu%2BQp5qqrPotIK5/rrm7EMMxZRwF/hMWLfK1VWy6E%3D' \
--name 'asd.txt'

#Local-Users
## List users
az storage account local-user list \
--account-name <storage-account-name> \
--resource-group <resource-group-name>
## Get user
az storage account local-user show \
--account-name <storage-account-name> \
--resource-group <resource-group-name> \
--name <local-user-name>

## List keys
az storage account local-user list \
--account-name <storage-account-name> \
--resource-group <resource-group-name>
```
</details>

{{#endtab }}

{{#tab name="Az PowerShell" }}

<details>
<summary>Az PowerShell enumeration</summary>
```powershell
# Get storage accounts
Get-AzStorageAccount | fl
# Get rules to access the storage account
Get-AzStorageAccount | select -ExpandProperty NetworkRuleSet
# Get IPs
(Get-AzStorageAccount | select -ExpandProperty NetworkRuleSet).IPRules
# Get containers of a storage account
Get-AzStorageContainer -Context (Get-AzStorageAccount -name <NAME> -ResourceGroupName <NAME>).context
# Get blobs inside container
Get-AzStorageBlob -Container epbackup-planetary -Context (Get-AzStorageAccount -name <name> -ResourceGroupName <name>).context
# Get a blob from a container
Get-AzStorageBlobContent -Container <NAME> -Context (Get-AzStorageAccount -name <NAME> -ResourceGroupName <NAME>).context -Blob <blob_name> -Destination .\Desktop\filename.txt

# Create a Container Policy
New-AzStorageContainerStoredAccessPolicy `
-Context (Get-AzStorageAccount -Name <NAME> -ResourceGroupName <NAME>).Context `
-Container <container-name> `
-Policy <policy-name> `
-Permission racwdl `
-StartTime (Get-Date "2023-11-22T00:00Z") `
-ExpiryTime (Get-Date "2024-11-22T00:00Z")
#Get Container policy
Get-AzStorageContainerStoredAccessPolicy `
-Context (Get-AzStorageAccount -Name <NAME> -ResourceGroupName <NAME>).Context `
-Container "storageaccount1994container"

# Queue Management
Get-AzStorageQueue -Context (Get-AzStorageAccount -Name <NAME> -ResourceGroupName <NAME>).Context
(Get-AzStorageQueue -Name <NAME> -Context (Get-AzStorageAccount -name <NAME> -ResourceGroupName <NAME>).Context).QueueClient.PeekMessage().Value

#Blob Container
Get-AzStorageBlob -Container <container-name> -Context $(Get-AzStorageAccount -name "teststorageaccount1998az" -ResourceGroupName "testStorageGroup").Context
Get-AzStorageBlobContent `
-Container <container-name> `
-Blob <blob-name> `
-Destination <local-path> `
-Context $(Get-AzStorageAccount -name "teststorageaccount1998az" -ResourceGroupName "testStorageGroup").Context

Set-AzStorageBlobContent `
-Container <container-name> `
-File <local-file-path> `
-Blob <blob-name> `
-Context $(Get-AzStorageAccount -name "teststorageaccount1998az" -ResourceGroupName "testStorageGroup").Context

# Shared Access Signatures (SAS)
Get-AzStorageContainerAcl `
-Container <container-name> `
-Context (Get-AzStorageAccount -Name <NAME> -ResourceGroupName <NAME>).Context

New-AzStorageBlobSASToken `
-Context $ctx `
-Container <container-name> `
-Blob <blob-name> `
-Permission racwdl `
-ExpiryTime (Get-Date "2024-12-31T23:59:00Z")
```
</details>

{{#endtab }}
{{#endtabs }}

### ファイル共有

{{#ref}}
az-file-shares.md
{{#endref}}

## Privilege Escalation

{{#ref}}
../az-privilege-escalation/az-storage-privesc.md
{{#endref}}

## Post Exploitation

{{#ref}}
../az-post-exploitation/az-blob-storage-post-exploitation.md
{{#endref}}

## Persistence

{{#ref}}
../az-persistence/az-storage-persistence.md
{{#endref}}

## 参考資料

- [https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction](https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- [https://learn.microsoft.com/en-us/azure/storage/common/storage-sas-overview](https://learn.microsoft.com/en-us/azure/storage/common/storage-sas-overview)
- [https://learn.microsoft.com/en-us/azure/storage/blobs/secure-file-transfer-protocol-support](https://learn.microsoft.com/en-us/azure/storage/blobs/secure-file-transfer-protocol-support)
- [Holiday Hack Challenge 2025 – Spare Key (Azure static website SAS leak)](https://0xdf.gitlab.io/holidayhack2025/act1/spare-key)
- [Holiday Hack Challenge 2025: Blob Storage (Storage Secrets)](https://0xdf.gitlab.io/holidayhack2025/act1/blob-storage)
- [https://learn.microsoft.com/en-us/cli/azure/storage/account](https://learn.microsoft.com/en-us/cli/azure/storage/account)
- [https://learn.microsoft.com/en-us/cli/azure/storage/container](https://learn.microsoft.com/en-us/cli/azure/storage/container)
- [https://learn.microsoft.com/en-us/cli/azure/storage/blob](https://learn.microsoft.com/en-us/cli/azure/storage/blob)

{{#include ../../../banners/hacktricks-training.md}}
