Az - Function Apps

Reading time: 20 minutes

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

基本情報

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の設定と環境変数

アプリ内で環境変数を設定することが可能で、これには機密情報が含まれる場合があります。さらに、デフォルトで環境変数**AzureWebJobsStorageWEBSITE_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 LabelEveryoneBUILTIN\UsersNT AUTHORITY\INTERACTIVECONSOLE LOGONNT AUTHORITY\Authenticated UsersNT AUTHORITY\This OrganizationBUILTIN\IIS_IUSRSLOCAL10-30-4-99\Dwas Site Usersが含まれていました。

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

VMsと同様に、Functionsは2種類の管理されたIDを持つことができます:システム割り当てとユーザー割り当て。

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

note

VMsと同様に、Functionsは1つのシステム割り当ての管理されたIDと複数のユーザー割り当ての管理されたIDを持つことができるため、関数を妥協した場合は、すべての管理されたIDを見つけることが常に重要です。1つのFunctionから複数の管理されたIDに権限を昇格させることができるかもしれません。

システム管理されたIDが使用されていないが、1つ以上のユーザー管理されたIDが関数に添付されている場合、デフォルトではトークンを取得することはできません。

PEASSスクリプトを使用して、メタデータエンドポイントからデフォルトの管理されたIDのトークンを取得することが可能です。また、以下のように手動で取得することもできます:

Cloud SSRF - HackTricks

関数に添付されているすべての管理された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を使用します。詳細については以下を参照してください:

Az - Azure App Services

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

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

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

さらに、Managed Identityも作成されるため、リポジトリのGithub Actionはそれを使用してAzureにログインできるようになります。これは、Managed Identity上にフェデレーテッド資格情報を生成することによって行われ、Issuer https://token.actions.githubusercontent.comSubject Identifier repo:<org-name>/<repo-name>:ref:refs/heads/<branch-name> が許可されます。

caution

したがって、そのリポジトリを侵害した者は、関数およびそれに関連付けられたManaged Identitiesを侵害することができます。

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

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

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

列挙

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"

権限昇格

Az - Functions App Privesc

参考文献

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする