Terraforming The Cloud

Automating Red Team Infrastructure with Terraform

Following the instructions from my Rowdy Roddy Red Team [link] blog, let’s hit the easy button with Terraform. This documents how to use Terraform to build your Red Team Infrastructure.

Pre-Requisites

You’ll need an AWS account where you can create access keys, install Terraform, and install AWS CLI.

I already had an AWS account [root-account]. I created an additional user [terraform-redteam]. Gave them Power User permissions and disabled Console login.

Then I created an Access Key to be used in the AWS CLI. Be sure to stay on the final page to retrieve the Secret Key because it will not be visible again after you leave the page.

Finally, I installed Terraform and AWS Cli on my Kali box.

$ sudo apt update

$ sudo apt install terraform

$ sudo apt install awscli

Step 0 - Download the GitHub repo

I cloned the repo into my home directory.

$ git clone git@github.com:rbfp/redteam-infra.git

$ cd redteam-infra

Step 1 - Configure AWS CLI

Using the Access Key and Secret Key I ran aws configure to connect the CLI to my terraform-redteam account.

To keep things organized, I run the command with —profile redteam to keep the terraform-redteam account separate with any other AWS profile I use. If you don’t use awscli with other accounts, it’s fine to run aws configure without the —profile parameter. The details will be saved to the default profile.

Paste in your Access Key ID and Secret Access Key when prompted.

I chose us-west-2 as the Default region name because I knew I wanted servers on the west coast of the US.

I also included a screenshot of what it looks like if we don’t include the —profile redteam parameter.

$ aws configure —profile redteam

Step 2 - Configure the Region to deploy

Run ./infra_setup.sh to select the AWS Profile, input name of the project to prepend all AWS object names, and select our region.

The script will list all aws profiles you use on your box. I have default and redteam configured and I chose redteam because that’s the profile and key that match the terraform-redteam I created earlier.

I gave a project name of redwest20 because that’s what I want all my EC2s, VPCs, etc to be prepended with for easy identification.

Then selecting the Region, OS and Availability Zones. Region is based on physical location of the data center you want to use. OS, choosing Ubuntu because it’s what I’m used to running for red team operations while utilizing AWS. Finally, the Availability Zones isn’t important if you don’t know what it is so you can choose whichever you want.

$ ./infra_setup.sh

Step 3 - Terraform the Cloud

Terraform commands will automatically run for you.

You’ll see these statuses fly by in your terminal:

Terraform has been successfully initialized!

Apply complete! Resources: 30 added

Terraform will automatically create these users to SSH into for each EC2 and the associated SSH keys (.pem)

Bastion Host username: bastion

bastion user ssh key: {{ project_name }}-bastion.pem

Redirector username: redirector

redirector user ssh key: {{ project_name }}-internal.pem

C2 Server username: c2server

c2server user ssh key: {{ project_name }}-internal.pem

note: redirector and c2server can only ssh into their respective EC2 instances from within the Bastion Host. So you’ll have to chain SSH-ing into Bastion and then into Redirector or C2 Server.

Step 4 - Verify Deployment

Check with ./manage_aws.sh

You can go to AWS Console and check the EC2 > Instances and you’ll find the Redirector, Bastion-Host, and C2-Server. They should all have no Public IPv4 IPs. But the Bastion-Host and Redirector will have public IPv6 that you will use.

Running ./manage_aws.sh you’ll be given multiple options to start, stop, list and even how much your current bill is. Using option 2 and providing the region you chose you can get a quick view of your EC2 instances info.

Verify you can SSH into your Bastion-Host with {{ project_name }}-bastion.pem; and, from the Bastion-Host you’ll find the .ssh/internal.pem key to ssh into the Redirector and C2-Server.

$ .manage_aws.sh

$ ssh -i ~/redteaminfra/build/{{ projectname }}-bastion.pem bastion@{{ bastion_ipv6}}

From w/n your bastion ssh session…

$ ssh -i .ssh/internal.pem c2server@{{ c2_ipv4 }}

Step 5 - Cobalt Strike Install

Automate install with ./cobalt_setup.sh

At this point I like to set up my terminal to multiple terminal sessions open to quickly at each session. You can do this with multiple terminal windows, tabs, or use split-view (vert split [CTRL+SHIFT, R], hor split [CTRL+SHIFT, D], and close that split [CTRL+SHIFT, E])

Running ./cobalt_setup.sh will ask you for Redirector IPv6, C2 Server IPv4, Redirector IPv4, project name, and the password for the Cobalt Strike 7z. When successful, you’ll end with ok=12.

This installs the dependencies you’ll need to run the Cobalt Strike server and Redirector. It will also copy the files to the correct place to be ran. There are manual post script commands to start your operations.

note: for the cobaltstrike.7z, that is my personal setup files. you will have to tweak the download link and password in playbook.yml for your own cobaltstrike files.

$ ./cobalt_setup.sh

Step 7 - Cobalt Server Setup

Start your Cobalt Strike Server and Connect your client to the server

SSH into your C2 Server through the Bastion host. Again, I’m using the split view setup to see all my windows at once and feel 1337-af-bro.jpg

The post script commands are in the README for copy and paste ease.

But we’ll start on our C2 Server by chmod +x -ing our Cobalt Strike binaries. Then, run the teamserver binary with your C2 Server IPv4 address and create a password for your Cobalt Strike server. Leave it open.

$ chmod +x ./CS491/Server/teamserver ./CS491/Server/TeamServerImage

$ ./teamserver {{ c2_ipv4 }} {{ cobalt_server_pass }}

Then, in another terminal on your Attack box, we’ll start an SSH tunnel that will allow your Cobalt Strike client to authenticate to your Cobalt Strike server which is hiding in a private subnet in your AWS VPC. The tunnel opens up a strict path through SSH to allow the client and server to talk. Leave this open too.

$ ssh -i {{ project_name }}-bastion.pem -L 50050:{{ c2_ipv4 }}:50050 bastion@{{bastion-ipv6}}

In another window in your Redirector, you’ll run a socat command that will redirect all the traffic coming to the redirector in the form of IPv6 to your C2 Server that only uses IPv4. Leave this open as well.

$ sudo socat ICP6-LISTEN:443,reuseaddr,fork TCP4:{{ c2_ipv4 }}:443

In another terminal, start your Cobalt Strike Client by running the cobaltstrike-client.sh inside the Client folder. A successful start will pop up a Connect window. Fill in the Alias with whatever you want, Host as 127.0.0.1 and Port as 50050. Set the username to whatever you want and the Password will be the {{ cobalt_server_pass }} you set.

$ chmod +x ./cobaltstrike-client.sh

$ ./cobaltstrike-client.sh

Step 8 - Proof of Concept

Create a Listener, Payload, and spawn a shell on a victim computer

Create a Listener

  • Click on headphones icon

  • Click Add

  • Name: HTTPS

  • Payload: Beacon HTTPS

  • HTTPS Hosts: [redirector_ipv6]

    • ipv6 needs to be encapsulated in square brackets

  • Everything else leave default

  • Click Save

Create a Payload

  • Click Payloads > Windows Stageless Payload

  • Listener: HTTPS

  • System Call: Indirect

  • HTTP Library: winhttp

  • Everything else leave default

  • Click Generate

  • Save

On your victim computer. I have a Windows 11 VM with Windows Security turned off. In the most convenient way possible, transfer the .exe to the Windows computer and run it.

You’ll now see the beacon calling back to your CS Client. You can now rule the world.

Next steps are to work on domain fronting and an sop/script on what to do when our redirector public IPv6 gets burned.