# Az - Function Apps

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

## 基本情報

**Azure Function Apps** は **サーバーレスコンピューティングサービス** で、基盤となるインフラを管理することなく、**関数**と呼ばれる小さなコードの断片を実行できます。これらは、**HTTPリクエスト、タイマー、またはBlob StorageやEvent Hubsなどの他のAzureサービスからのイベント**など、さまざまなトリガーに応じてコードを実行するように設計されています。Function AppsはC#、Python、JavaScript、Javaなど複数のプログラミング言語をサポートしており、**イベント駆動型アプリケーション**の構築、ワークフローの自動化、サービスの統合に適しています。通常、コードが実行されるときに使用されたコンピュート時間に対してのみ支払うため、コスト効率が高いです。

> [!NOTE]
> **FunctionsはApp Servicesのサブセット**であるため、ここで説明する多くの機能はAzure Apps（CLIでは`webapp`）として作成されたアプリケーションでも使用されます。

### 異なるプラン

- **Flex Consumption Plan**: **動的でイベント駆動型のスケーリング**を提供し、需要に応じて関数インスタンスを追加または削除する従量課金制です。**仮想ネットワーキング**と**事前プロビジョニングされたインスタンス**をサポートし、コールドスタートを減少させ、コンテナサポートを必要としない**変動するワークロード**に適しています。
- **Traditional Consumption Plan**: デフォルトのサーバーレスオプションで、関数が実行されるときにのみ**コンピュートリソースに対して支払います**。受信イベントに基づいて自動的にスケールし、**コールドスタートの最適化**が含まれていますが、コンテナデプロイメントはサポートしていません。自動スケーリングを必要とする**断続的なワークロード**に最適です。
- **Premium Plan**: **一貫したパフォーマンス**のために設計されており、コールドスタートを排除するための**事前ウォームされたワーカー**を提供します。**拡張実行時間、仮想ネットワーキング**を提供し、**カスタムLinuxイメージ**をサポートしており、高パフォーマンスと高度な機能を必要とする**ミッションクリティカルなアプリケーション**に最適です。
- **Dedicated Plan**: 専用の仮想マシン上で実行され、**予測可能な請求**を提供し、手動または自動スケーリングをサポートします。同じプランで複数のアプリを実行でき、**コンピュートの隔離**を提供し、App Service Environmentsを介して**安全なネットワークアクセス**を確保し、一貫したリソース割り当てを必要とする**長時間実行されるアプリケーション**に最適です。
- **Container Apps**: **コンテナ化された関数アプリ**を管理された環境でデプロイでき、マイクロサービスやAPIと共に使用できます。カスタムライブラリ、レガシーアプリの移行、**GPU処理**をサポートし、Kubernetesクラスターの管理を排除します。**イベント駆動型でスケーラブルなコンテナ化アプリケーション**に最適です。

### **ストレージバケット**

新しいFunction Appをコンテナ化せずに作成する際、**コードとその他のFunction関連データはストレージアカウントに保存されます**。デフォルトでは、Webコンソールはコードを保存するために関数ごとに新しいものを作成します。

さらに、バケット内のコードを変更すると（保存されるさまざまな形式で）、**アプリのコードは新しいものに変更され、次回Functionが呼び出されると実行されます**。

> [!CAUTION]
> これは攻撃者の視点から非常に興味深いものであり、**このバケットへの書き込みアクセス**があれば、攻撃者は**コードを妥協し、Function App内の管理されたIDの権限を昇格させる**ことができます。
>
> これについては**権限昇格セクション**で詳しく説明します。

ストレージアカウント内のコンテナ**`azure-webjobs-secrets`**に保存されている**マスターキーと関数キー**を見つけることも可能です。これは**`<app-name>`**フォルダ内のJSONファイルにあります。

Functionsは、リモートの場所にコードを保存することも可能で、そのURLを指定するだけです。

### ネットワーキング

HTTPトリガーを使用する場合：

- **インターネット全体から関数へのアクセスを提供**することが可能で、認証を必要としないか、IAMベースのアクセスを提供できます。ただし、このアクセスを制限することも可能です。
- **内部ネットワーク（VPC）**からFunction Appへのアクセスを**提供または制限**することも可能です。

> [!CAUTION]
> これは攻撃者の視点から非常に興味深いものであり、インターネットに公開された脆弱なFunctionから**内部ネットワークにピボットする**ことが可能かもしれません。

### **Function Appの設定と環境変数**

アプリ内で環境変数を設定することが可能で、これには機密情報が含まれる場合があります。さらに、デフォルトで環境変数**`AzureWebJobsStorage`**と**`WEBSITE_CONTENTAZUREFILECONNECTIONSTRING`**（他にもいくつか）が作成されます。これらは特に興味深いもので、**アプリケーションのデータを含むストレージアカウントを完全に制御するためのアカウントキーを含んでいます**。これらの設定は、ストレージアカウントからコードを実行するためにも必要です。

これらの環境変数や設定パラメータは、Functionがコードを実行する方法も制御します。たとえば、**`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`が含まれていました。

### **管理されたIDとメタデータ**

[**VMs**](vms/index.html)と同様に、Functionsは**2種類の管理されたID**を持つことができます：システム割り当てとユーザー割り当て。

**システム割り当て**のものは、**そのIDが割り当てられた関数のみが使用できる管理されたID**です。一方、**ユーザー割り当て**の管理されたIDは、**他のAzureサービスが使用できる管理されたID**です。

> [!NOTE]
> [**VMs**](vms/index.html)と同様に、Functionsは**1つのシステム割り当て**の管理されたIDと**複数のユーザー割り当て**の管理されたIDを持つことができるため、関数を妥協した場合は、すべての管理されたIDを見つけることが常に重要です。1つのFunctionから複数の管理されたIDに権限を昇格させることができるかもしれません。
>
> システム管理されたIDが使用されていないが、1つ以上のユーザー管理されたIDが関数に添付されている場合、デフォルトではトークンを取得することはできません。

[**PEASSスクリプト**](https://github.com/peass-ng/PEASS-ng)を使用して、メタデータエンドポイントからデフォルトの管理されたIDのトークンを取得することが可能です。また、以下のように**手動で**取得することもできます：

{{#ref}}
https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html#azure-vm
{{#endref}}

関数に添付されている**すべての管理されたIDを確認する方法を見つける**必要があることに注意してください。指定しない場合、メタデータエンドポイントは**デフォルトのもののみを使用します**（詳細については前のリンクを参照してください）。

## アクセスキー

> [!NOTE]
> ユーザーが関数を呼び出すためのアクセスを与えるRBAC権限はありません。**関数の呼び出しは、作成時に選択されたトリガーに依存します**。HTTPトリガーが選択された場合、**アクセスキー**を使用する必要があるかもしれません。

HTTPトリガーを使用して関数内にエンドポイントを作成する際、関数をトリガーするために必要な**アクセスキーの認証レベル**を指定することが可能です。3つのオプションがあります：

- **ANONYMOUS**: **誰でも**URLを通じて関数にアクセスできます。
- **FUNCTION**: エンドポイントは**関数、ホスト、またはマスターキー**を使用するユーザーのみがアクセスできます。
- **ADMIN**: エンドポイントは**マスターキー**を持つユーザーのみがアクセスできます。

**キーの種類：**

- **Function Keys:** 関数キーはデフォルトまたはユーザー定義のいずれかで、Function App内の**特定の関数エンドポイント**へのアクセスを独占的に付与するように設計されています。これにより、エンドポイントに対するより細かいアクセスが可能になります。
- **Host Keys:** ホストキーはデフォルトまたはユーザー定義のいずれかで、Function App内の**すべての関数エンドポイントにFUNCTIONアクセスレベルでアクセス**を提供します。
- **Master Key:** マスターキー（`_master`）は、すべての関数エンドポイントへのアクセスを含む管理キーで、権限が昇格されます。この**キーは取り消すことができません**。
- **System Keys:** システムキーは**特定の拡張機能によって管理され**、内部コンポーネントによって使用されるWebhookエンドポイントにアクセスするために必要です。例としては、Event GridトリガーやDurable Functionsがあり、これらはそれぞれのAPIと安全に対話するためにシステムキーを利用します。

> [!TIP]
> キーを使用して関数APIエンドポイントにアクセスする例：
>
> `https://<function_uniq_name>.azurewebsites.net/api/<endpoint_name>?code=<access_key>`

### 基本認証

App Servicesと同様に、Functionsも**SCM**および**FTP**に接続してコードをデプロイするための基本認証をサポートしています。これは、Azureが提供する**ユーザー名とパスワードを含むURL**を使用します。詳細については以下を参照してください：

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

### Githubベースのデプロイメント

関数がGithubリポジトリから生成されると、Azure Webコンソールは**特定のリポジトリにGithubワークフローを自動的に作成**することを許可します。これにより、このリポジトリが更新されるたびに関数のコードが更新されます。実際、Python関数のGithub Action yamlは次のようになります：

<details>

<summary>Github Action Yaml</summary>
```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を侵害することができます。

### コンテナベースのデプロイメント

すべてのプランがコンテナのデプロイを許可しているわけではありませんが、許可されているプランでは、設定にコンテナのURLが含まれます。APIでは、**`linuxFxVersion`**設定は次のようになります: `DOCKER|mcr.microsoft.com/...`、一方、ウェブコンソールでは、設定に**image settings**が表示されます。

さらに、**ソースコードは関数に関連するストレージ**アカウントに保存されることはありません。必要ないためです。

## 列挙

{{#tabs }}
{{#tab name="az cli" }}
```bash
# List all the functions
az functionapp list

# List functions in an function-app (endpoints)
az functionapp function list \
--name <app-name> \
--resource-group <res-group>

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

# Get access restrictions
az functionapp config access-restriction show --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 acess restrictions
az functionapp config access-restriction show --name <app-name> --resource-group <res-group>

# Get connection strings
az rest --method POST --uri "https://management.azure.com/subscriptions/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/config/connectionstrings/list?api-version=2022-03-01"
az rest --method GET --uri "https://management.azure.com/subscriptions/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/config/configreferences/connectionstrings?api-version=2022-03-01"

# Get SCM credentials
az functionapp deployment list-publishing-credentials --name <app-name> --resource-group <res-group>

# Get function, system and master keys
az functionapp keys list --name <app-name> --resource-group <res-group>

# Get Host key
az rest --method POST --uri "https://management.azure.com/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/functions/<function-endpoint-name>/listKeys?api-version=2022-03-01"

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

# Get source code using SCM access (Azure permissions or SCM creds)
az rest --method GET \
--url "https://<func-app-name>.azurewebsites.net/admin/vfs/home/site/wwwroot/function_app.py?code=<master-key>" \
--resource "https://management.azure.com/"

# Get source code with Azure permissions
az rest --url "https://management.azure.com/subscriptions/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/hostruntime/admin/vfs/function_app.py?relativePath=1&api-version=2022-03-01"
## Another example
az rest --url "https://management.azure.com/subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.Web/sites/ConsumptionExample/hostruntime/admin/vfs/HttpExample/index.js?relativePath=1&api-version=2022-03-01"

```
{{#endtab }}

{{#tab name="Az Powershell" }}
```bash
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>
```
{{#endtab }}
{{#endtabs }}


## 権限昇格

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

## 参考文献

- [https://learn.microsoft.com/en-us/azure/azure-functions/functions-openapi-definition](https://learn.microsoft.com/en-us/azure/azure-functions/functions-openapi-definition)

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