GCP - Token Persistence

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

Tokens de usuario autenticado

Para obtener el current token de un usuario puedes ejecutar:

Obtener access token desde la base de datos SQLite ```bash sqlite3 $HOME/.config/gcloud/access_tokens.db "select access_token from access_tokens where account_id='';" ```

Consulta en esta página cómo usar directamente este token con gcloud:

Cloud SSRF - HackTricks

Para obtener los detalles para generar un nuevo access token ejecuta:

Obtener el refresh token desde la base de datos SQLite ```bash sqlite3 $HOME/.config/gcloud/credentials.db "select value from credentials where account_id='';" ```

También es posible encontrar refresh tokens en $HOME/.config/gcloud/application_default_credentials.json y en $HOME/.config/gcloud/legacy_credentials/*/adc.json.

Para obtener un nuevo access token renovado con el refresh token, client ID y client secret, ejecute:

Obtener nuevo access token usando refresh token ```bash curl -s --data client_id= --data client_secret= --data grant_type=refresh_token --data 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 ```

La validez de los refresh tokens puede gestionarse en Admin > Security > Google Cloud session control, y por defecto está establecida en 16h aunque puede configurarse para que nunca expire:

Flujo de autenticación

El flujo de autenticación al usar algo como gcloud auth login abrirá un prompt en el navegador y, tras aceptar todos los scopes, el navegador enviará una petición como esta al puerto http abierto por la herramienta:

/?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

Luego, gcloud usará el state y el code con un client_id (32555940559.apps.googleusercontent.com) y un client_secret (ZmssLNjJy2998hD4CTg2ejr2) codificados para obtener los datos finales del refresh token.

Caution

Ten en cuenta que la comunicación con localhost es por HTTP, por lo que es posible interceptar los datos para obtener un refresh token; sin embargo, estos datos son válidos solo una vez, así que eso sería inútil — es más sencillo simplemente leer el refresh token del archivo.

Alcances OAuth

Puedes encontrar todos los alcances de Google en https://developers.google.com/identity/protocols/oauth2/scopes o obtenerlos ejecutando:

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

Es posible ver qué scopes puede admitir la aplicación que gcloud usa para autenticarse con este script:

Probar scopes soportados por gcloud ```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 ```

Después de ejecutarlo, se comprobó que esta app admite estos 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

Es interesante ver cómo esta app soporta el scope drive, lo que podría permitir a un usuario escalar de GCP a Workspace si un atacante logra forzar al usuario a generar un token con ese scope.

Consulta cómo abuse this here.

Cuentas de servicio

Al igual que con usuarios autenticados, si consigues comprometer el private key file de un service account podrás acceder a él normalmente todo el tiempo que quieras.
Sin embargo, si robas el OAuth token de un service account esto puede ser aún más interesante, porque, aunque por defecto estos tokens sólo son útiles durante una hora, si la víctima elimina la private api key, el OAuth token seguirá siendo válido hasta que expire.

Metadatos

Obviamente, mientras estés dentro de una máquina que se ejecute en el entorno de GCP podrás acceder al service account adjunto a esa máquina contactando el metadata endpoint (nota que los OAuth tokens a los que puedes acceder en este endpoint suelen estar restringidos por scopes).

Remediaciones

Algunas remediaciones para estas técnicas se explican en https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2

Referencias

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks