# Az - Table Storage

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

## Basic Information

**Azure Table Storage** is a NoSQL key-value store designed for storing large volumes of structured, non-relational data. It offers high availability, low latency, and scalability to handle large datasets efficiently. Data is organized into tables, with each entity identified by a partition key and row key, enabling fast lookups. It supports features like encryption at rest, role-based access control, and shared access signatures for secure, managed storage suitable for a wide range of applications.

There **isn't built-in backup mechanism** for table storage.

### Keys

#### **PartitionKey**

- The **PartitionKey groups entities into logical partitions**. Entities with the same PartitionKey are stored together, which improves query performance and scalability.
- Example: In a table storing employee data, `PartitionKey` might represent a department, e.g., `"HR"` or `"IT"`.

#### **RowKey**

- The **RowKey is the unique identifier** for an entity within a partition. When combined with the PartitionKey, it ensures that each entity in the table has a globally unique identifier.
- Example: For the `"HR"` partition, `RowKey` might be an employee ID, e.g., `"12345"`.

#### **Other Properties (Custom Properties)**

- Besides the PartitionKey and RowKey, an entity can have additional **custom properties to store data**. These are user-defined and act like columns in a traditional database.
- Properties are stored as **key-value pairs**.
- Example: `Name`, `Age`, `Title` could be custom properties for an employee.

## Enumeration

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

```bash
# Get storage accounts
az storage account list

# List tables
az storage table list --account-name <name>

# Read table
az storage entity query \
  --account-name <name> \
  --table-name <t-name> \
  --top 10

# Write table
az storage entity insert \
  --account-name <STORAGE_ACCOUNT_NAME> \
  --table-name <TABLE_NAME> \
  --entity PartitionKey=<PARTITION_KEY> RowKey=<ROW_KEY> <PROPERTY_KEY>=<PROPERTY_VALUE>

# Write example
az storage entity insert \
  --account-name mystorageaccount \
  --table-name mytable \
  --entity PartitionKey=HR RowKey=12345 Name="John Doe" Age=30 Title="Manager"

# Update row
az storage entity merge \
  --account-name mystorageaccount \
  --table-name mytable \
  --entity PartitionKey=pk1 RowKey=rk1 Age=31
```

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

```bash
# Get storage accounts
Get-AzStorageAccount

# List tables
Get-AzStorageTable -Context (Get-AzStorageAccount -Name <mystorageaccount> -ResourceGroupName <ResourceGroupName>).Context

Get-AzStorageTableStoredAccessPolicy -Table <Table> -Context (Get-AzStorageAccount -Name <mystorageaccount -ResourceGroupName <ResourceGroupName>).Context
```

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

> [!NOTE]
> By default `az` cli will use an account key to sign a key and perform the action. To use the Entra ID principal privileges use the parameters `--auth-mode login`.

> [!TIP]
> Use the param `--account-key` to indicate the account key to use\
> Use the param `--sas-token` with the SAS token to access via a SAS token

## Privilege Escalation

Same as storage privesc:

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

## Post Exploitation

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

## Persistence

Same as storage persistence:

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

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



