Files
hacktricks-cloud/src/pentesting-cloud/azure-security/az-services/az-function-apps.md

23 KiB
Raw Blame History

Az - Function Apps

{{#include ../../../banners/hacktricks-training.md}}

Basic Information

Azure Function Apps - це безсерверна обчислювальна служба, яка дозволяє запускати невеликі фрагменти коду, звані функціями, без управління підлягаючою інфраструктурою. Вони призначені для виконання коду у відповідь на різні тригери, такі як HTTP запити, таймери або події з інших служб Azure, таких як Blob Storage або Event Hubs. Function Apps підтримують кілька мов програмування, включаючи C#, Python, JavaScript та Java, що робить їх універсальними для створення додатків, орієнтованих на події, автоматизації робочих процесів або інтеграції служб. Вони є економічно вигідними, оскільки зазвичай ви платите лише за час обчислень, коли ваш код виконується.

Note

Зверніть увагу, що Functions є підмножиною App Services, тому багато функцій, обговорюваних тут, також будуть використовуватися додатками, створеними як Azure Apps (webapp в cli).

Different Plans

  • Flex Consumption Plan: Пропонує динамічне, орієнтоване на події масштабування з оплатою за фактом використання, додаючи або видаляючи екземпляри функцій залежно від попиту. Підтримує віртуальне мережеве з'єднання та попередньо підготовлені екземпляри, щоб зменшити холодні старти, що робить його підходящим для змінних навантажень, які не потребують підтримки контейнерів.
  • Traditional Consumption Plan: За замовчуванням безсерверний варіант, де ви платите лише за обчислювальні ресурси, коли функції виконуються. Автоматично масштабується на основі вхідних подій і включає оптимізації холодного старту, але не підтримує розгортання контейнерів. Ідеально підходить для періодичних навантажень, які потребують автоматичного масштабування.
  • Premium Plan: Призначений для послідовної продуктивності, з попередньо прогрітими працівниками, щоб усунути холодні старти. Пропонує подовжені часи виконання, віртуальне мережеве з'єднання та підтримує кастомізовані образи Linux, що робить його ідеальним для додатків критичного призначення, які потребують високої продуктивності та розширених функцій.
  • Dedicated Plan: Виконується на виділених віртуальних машинах з передбачуваним білінгом і підтримує ручне або автоматичне масштабування. Дозволяє запускати кілька додатків на одному плані, забезпечує ізоляцію обчислень і гарантує безпечний доступ до мережі через App Service Environments, що робить його ідеальним для додатків з тривалим виконанням, які потребують послідовного виділення ресурсів.
  • Container Apps: Дозволяє розгортати контейнеризовані функціональні додатки в керованому середовищі, поряд з мікросервісами та API. Підтримує кастомні бібліотеки, міграцію спадкових додатків та обробку GPU, усуваючи управління кластерами Kubernetes. Ідеально підходить для додатків, орієнтованих на події, масштабованих контейнеризованих додатків.

Storage Buckets

При створенні нового Function App, який не контейнеризований (але надає код для виконання), код та інші дані, пов'язані з функцією, будуть зберігатися в обліковому записі зберігання. За замовчуванням веб-консоль створить новий обліковий запис для кожної функції для зберігання коду.

Більше того, модифікуючи код всередині кошика (в різних форматах, в яких він може бути збережений), код програми буде змінено на новий і виконано наступного разу, коли функція буде викликана.

Caution

Це дуже цікаво з точки зору атакуючого, оскільки доступ на запис до цього кошика дозволить атакуючому компрометувати код і підвищити привілеї до керованих ідентичностей всередині Function App.

Більше про це в розділі підвищення привілеїв.

Також можливо знайти ключі майстра та функцій, збережені в обліковому записі зберігання в контейнері azure-webjobs-secrets всередині папки <app-name> у JSON-файлах, які ви можете знайти всередині.

Зверніть увагу, що Functions також дозволяють зберігати код у віддаленому місці, просто вказуючи URL на нього.

Networking

Використовуючи HTTP тригер:

  • Можливо надати доступ до функції з усієї Інтернету без вимоги будь-якої аутентифікації або надати доступ на основі IAM. Хоча також можливо обмежити цей доступ.
  • Також можливо надати або обмежити доступ до Function App з внутрішньої мережі (VPC).

Caution

Це дуже цікаво з точки зору атакуючого, оскільки може бути можливим перемикання на внутрішні мережі з вразливої функції, відкритої для Інтернету.

Function App Settings & Environment Variables

Можливо налаштувати змінні середовища всередині програми, які можуть містити чутливу інформацію. Більше того, за замовчуванням змінні середовища AzureWebJobsStorage та WEBSITE_CONTENTAZUREFILECONNECTIONSTRING (серед інших) створюються. Ці змінні особливо цікаві, оскільки вони містять ключ облікового запису для контролю з ПОВНИМИ правами доступу до облікового запису зберігання, що містить дані програми. Ці налаштування також потрібні для виконання коду з облікового запису зберігання.

Ці змінні середовища або параметри конфігурації також контролюють, як функція виконує код, наприклад, якщо WEBSITE_RUN_FROM_PACKAGE існує, це вказує на URL, де розташований код програми.

Function Sandbox

Всередині linux пісочниці вихідний код розташований у /home/site/wwwroot у файлі function_app.py (якщо використовується python), користувач, що виконує код, - app (без прав sudo).

У Windows функції, що використовує NodeJS, код розташовувався у C:\home\site\wwwroot\HttpTrigger1\index.js, ім'я користувача було mawsFnPlaceholder8_f_v4_node_20_x86 і він був частиною груп: Mandatory Label\High Mandatory Level Label, Everyone, BUILTIN\Users, NT AUTHORITY\INTERACTIVE, CONSOLE LOGON, NT AUTHORITY\Authenticated Users, NT AUTHORITY\This Organization, BUILTIN\IIS_IUSRS, LOCAL, 10-30-4-99\Dwas Site Users.

Managed Identities & Metadata

Так само, як і VMs, Functions можуть мати Managed Identities двох типів: системно призначені та призначені користувачем.

Системно призначена ідентичність буде керованою ідентичністю, яку тільки функція, якій вона призначена, зможе використовувати, тоді як призначені користувачем керовані ідентичності - це керовані ідентичності, які будь-яка інша служба Azure зможе використовувати.

Note

Так само, як і в VMs, Functions можуть мати 1 системно призначену керовану ідентичність і кілька призначених користувачем, тому завжди важливо намагатися знайти всі з них, якщо ви компрометуєте функцію, оскільки ви можете підвищити привілеї до кількох керованих ідентичностей з однієї функції.

Якщо не використовується системно призначена ідентичність, але одна або кілька призначених користувачем ідентичностей прикріплені до функції, за замовчуванням ви не зможете отримати жоден токен.

Можливо використовувати PEASS скрипти для отримання токенів з за замовчуванням керованої ідентичності з кінцевої точки метаданих. Або ви можете отримати їх вручну, як пояснено в:

{% embed url="https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html#azure-vm" %}

Зверніть увагу, що вам потрібно знайти спосіб перевірити всі керовані ідентичності, прикріплені до функції, оскільки якщо ви цього не вкажете, кінцева точка метаданих використовуватиме лише за замовчуванням (перевірте попереднє посилання для отримання додаткової інформації).

Access Keys

Note

Зверніть увагу, що немає дозволів RBAC для надання доступу користувачам для виклику функцій. Виклик функції залежить від тригера, вибраного під час її створення, і якщо був вибраний HTTP тригер, можливо, знадобиться використовувати ключ доступу.

При створенні кінцевої точки всередині функції за допомогою HTTP тригера можливо вказати рівень авторизації ключа доступу, необхідний для виклику функції. Доступні три варіанти:

  • ANONYMOUS: Кожен може отримати доступ до функції за URL.
  • FUNCTION: Кінцева точка доступна лише користувачам, які використовують ключ функції, хоста або майстра.
  • ADMIN: Кінцева точка доступна лише користувачам з ключем майстра.

Типи ключів:

  • Function Keys: Ключі функцій можуть бути або за замовчуванням, або визначеними користувачем і призначені для надання доступу виключно до конкретних кінцевих точок функцій в рамках Function App, що дозволяє більш детально контролювати доступ до кінцевих точок.
  • Host Keys: Ключі хоста, які також можуть бути за замовчуванням або визначеними користувачем, надають доступ до всіх кінцевих точок функцій в рамках Function App з рівнем доступу FUNCTION.
  • Master Key: Ключ майстра (_master) служить адміністративним ключем, який пропонує підвищені права, включаючи доступ до всіх кінцевих точок функцій (включаючи рівень доступу ADMIN). Цей ключ не може бути відкликаний.
  • System Keys: Системні ключі керуються конкретними розширеннями і потрібні для доступу до кінцевих точок вебхуків, які використовуються внутрішніми компонентами. Прикладами є тригер Event Grid та Durable Functions, які використовують системні ключі для безпечної взаємодії зі своїми відповідними API.

Tip

Приклад доступу до кінцевої точки API функції за допомогою ключа:

https://<function_uniq_name>.azurewebsites.net/api/<endpoint_name>?code=<access_key>

Basic Authentication

Так само, як і в App Services, Functions також підтримують базову аутентифікацію для підключення до SCM та FTP для розгортання коду, використовуючи ім'я користувача та пароль у URL, наданому Azure. Більше інформації про це в:

{{#ref}} az-app-services.md {{#endref}}

Github Based Deployments

Коли функція генерується з репозиторію Github, веб-консоль Azure дозволяє автоматично створити робочий процес Github у конкретному репозиторії, тому що щоразу, коли цей репозиторій оновлюється, код функції оновлюється. Насправді YAML дії Github для функції на python виглядає так:

Github Action Yaml ```yaml # Docs for the Azure Web Apps Deploy action: https://github.com/azure/functions-action # More GitHub Actions for Azure: https://github.com/Azure/actions # More info on Python, GitHub Actions, and Azure Functions: https://aka.ms/python-webapps-actions

name: Build and deploy Python project to Azure Function App - funcGithub

on: push: branches:

  • main workflow_dispatch:

env: AZURE_FUNCTIONAPP_PACKAGE_PATH: "." # set this to the path to your web app project, defaults to the repository root PYTHON_VERSION: "3.11" # set this to the python version to use (supports 3.6, 3.7, 3.8)

jobs: build: runs-on: ubuntu-latest steps:

  • name: Checkout repository uses: actions/checkout@v4

  • name: Setup Python version uses: actions/setup-python@v5 with: python-version: ${{ env.PYTHON_VERSION }}

  • name: Create and start virtual environment run: | python -m venv venv source venv/bin/activate

  • name: Install dependencies run: pip install -r requirements.txt

Optional: Add step to run tests here

  • name: Zip artifact for deployment run: zip release.zip ./* -r

  • name: Upload artifact for deployment job uses: actions/upload-artifact@v4 with: name: python-app path: | release.zip !venv/

deploy: runs-on: ubuntu-latest needs: build

permissions: id-token: write #This is required for requesting the JWT

steps:

  • name: Download artifact from build job uses: actions/download-artifact@v4 with: name: python-app

  • name: Unzip artifact for deployment run: unzip release.zip

  • name: Login to Azure uses: azure/login@v2 with: client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_6C3396368D954957BC58E4C788D37FD1 }} tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_7E50AEF6222E4C3DA9272D27FB169CCD }} subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_905358F484A74277BDC20978459F26F4 }}

  • name: "Deploy to Azure Functions" uses: Azure/functions-action@v1 id: deploy-to-function with: app-name: "funcGithub" slot-name: "Production" package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}

</details>

Більше того, **Managed Identity** також створюється, щоб Github Action з репозиторію міг увійти в Azure за його допомогою. Це робиться шляхом генерації федеративних облікових даних через **Managed Identity**, що дозволяє **Issuer** `https://token.actions.githubusercontent.com` та **Subject Identifier** `repo:<org-name>/<repo-name>:ref:refs/heads/<branch-name>`.

> [!CAUTION]
> Отже, будь-хто, хто скомпрометує цей репозиторій, зможе скомпрометувати функцію та пов'язані з нею Managed Identities.

### Container Based Deployments

Не всі плани дозволяють розгортати контейнери, але для тих, що дозволяють, конфігурація міститиме URL контейнера. В API налаштування **`linuxFxVersion`** матиме щось на зразок: `DOCKER|mcr.microsoft.com/...`, тоді як у веб-консолі конфігурація відображатиме **image settings**.

Більше того, **жоден вихідний код не буде зберігатися в обліковому записі зберігання**, пов'язаному з функцією, оскільки це не потрібно.

## Enumeration

{% tabs %}
{% tab title="az cli" %}
{% code overflow="wrap" %}
```bash
# List all the functions
az functionapp list

# Get info of 1 funciton (although in the list you already get this info)
az functionapp show --name <app-name> --resource-group <res-group>
## If "linuxFxVersion" has something like: "DOCKER|mcr.microsoft.com/..."
## This is using a container

# Get details about the source of the function code
az functionapp deployment source show \
--name <app-name> \
--resource-group <res-group>
## If error like "This is currently not supported."
## Then, this is probalby using a container

# Get more info if a container is being used
az functionapp config container show \
--name <name> \
--resource-group <res-group>

# Get settings (and privesc to the sorage account)
az functionapp config appsettings list --name <app-name> --resource-group <res-group>

# Check if a domain was assigned to a function app
az functionapp config hostname list --webapp-name <app-name> --resource-group <res-group>

# Get SSL certificates
az functionapp config ssl list --resource-group <res-group>

# Get network restrictions
az functionapp config access-restriction show --name <app-name> --resource-group <res-group>

# Get more info about a function (invoke_url_template is the URL to invoke and script_href allows to see the code)
az rest --method GET \
--url "https://management.azure.com/subscriptions/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/functions?api-version=2024-04-01"

# Get source code with Master Key of the function
curl "<script_href>?code=<master-key>"
## Python example
curl "https://newfuncttest123.azurewebsites.net/admin/vfs/home/site/wwwroot/function_app.py?code=<master-key>" -v

# Get source code
az rest --url "https://management.azure.com/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/hostruntime/admin/vfs/function_app.py?relativePath=1&api-version=2022-03-01"

{% endcode %} {% endtab %}

{% tab title="Az PowerShell" %} {% code overflow="wrap" %}

Get-Command -Module Az.Functions

# Lists all Function Apps in the current subscription or in a specific resource group.
Get-AzFunctionApp  -ResourceGroupName <String>

# Displays the regions where Azure Function Apps are available for deployment.
Get-AzFunctionAppAvailableLocation

# Retrieves details about Azure Function App plans in a subscription or resource group.
Get-AzFunctionAppPlan -ResourceGroupName <String> -Name <String>

# Retrieves the app settings for a specific Azure Function App.
Get-AzFunctionAppSetting -Name <FunctionAppName> -ResourceGroupName <ResourceGroupName>

{% endcode %} {% endtab %} {% endtabs %}

Підвищення Привілеїв

{{#ref}} ../az-privilege-escalation/az-functions-app-privesc.md {{#endref}}

Посилання

{{#include ../../../banners/hacktricks-training.md}}