Az - App Services
Reading time: 12 minutes
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
App Service Basic Information
Azure App Services enables developers to build, deploy, and scale web applications, mobile app backends, and APIs seamlessly. It supports multiple programming languages and integrates with various Azure tools and services for enhanced functionality and management.
Each app runs inside a sandbox but isolation depends upon App Service plans:
- Apps in Free and Shared tiers run on shared VMs
- Apps in Standard and Premium tiers run on dedicated VMs shared only by apps in the same App Service plan.
- The Isolated tiers run on dedicated VMs on dedicated virtual networks, improving the isolation of the apps.
warning
Note that none of those isolations prevents other common web vulnerabilities (such as file upload, or injections). And if a management identity is used, it could be able to escalate privileges to them.
Apps have some interesting configurations:
- Always On: Ensures that the app is always running. If not enabled, the app will stop running after 20 minutes of inactivity and will start again when a request is received.
- This is essential if you have a webjob that needs to run continuously as the webjob will stop if the app stops.
- SSH: If enabled, a user with enough permissions can connect to the app using SSH.
- Debugging: If enabled, a user with enough permissions can debug the app. However, this is disabled automatically every 48h.
- Web App + Database: The web console allows to create an App with a database. In this case it's possible to select the database to use (SQLAzure, PostgreSQL, MySQL, MongoDB) and it also allows you to create an Azure Cache for Redis.
- The URL containing the credentials for the database and Redis will be stored in the appsettings.
- Container: It's possible to deploy a container to the App Service by indicating the URL of the container and the credentials to access it.
- Mounts: It's possible to create 5 mounts from Storage accounts being these Azure Blob (Read-Only) or Azure Files. The configuration will store the access key over the Storage Account.
Basic Authentication
When creating a web app (and a Azure function usually) it's possible to indicate if you want Basic Authentication to be enabled (disabled by default). This basically enables SCM (Source Control Manager) and FTP (File Transfer Protocol) for the application so it'll be possible to deploy the application using those technologies.
In order to access the SCM and the FTP servers, a username and password is required. Therefore, Azure provides some APIs to get the URLs to these platforms and the credentials.
The FTP server doesn’t have any special magic, just with the valid URL, username and password it’s possible to connect and get read and write permissions over the App environment.
The SCM
It's possible to connect to the SCM using a web browser in https://<SMC-URL>/BasicAuth
and check all files and deployments in there.
Kudu
Kudu is the platform that manages both the SCM and a web and API interface to manage an App Service, and provides Git-based deployments, remote debugging, and file management capabilities. It's accessible through the SCM URL of defined in the web app.
Note that the Kudu versions used by App Services and by Function Apps are different, being the version of the Function apps much more limited.
Some interesting endpoints you can find in Kudu are:
/BasicAuth
: You need to access this path to login inside Kudu./DebugConsole
: A console that allows you to execute commands in the environment where Kudu is running.- Note that this environment doesn't have access to the metadata service to get tokens.
/webssh/host
: A web-based SSH client that allows you to connect inside the container where the app is running.- This environment has access to the metadata service in order to obtain tokens from the assigned managed identities.
/Env
: Get information about the system, app settings, env variables, connection strings and HTTP headers./wwwroot/
: The root directory of the web app. You can download all the files from here.
Moreover, Kudu used to by opensource in https://github.com/projectkudu/kudu but the project was deprecated and comparing the behavior of the current Kudu in Azure with the old one it's possible to see that several things have already changed.
Sources
App Services allow to upload the code as a zip file by default, but it also allows to connect to a third party service and get the code from there.
- The currently supported third party sources are Github and Bitbucket.
- You can get the authentication tokens running
az rest --url "https://management.azure.com/providers/Microsoft.Web/sourcecontrols?api-version=2024-04-01"
- Azure by default will setup a Github Action to deploy the code to the App Service every time the code is updated.
- You can get the authentication tokens running
- It's also possible to indicate a remote git repository (with username and password) to get the code from there.
- You can get the credentials to the remote repo running
az webapp deployment source show --name <app-name> --resource-group <res-group>
oraz 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"
- You can get the credentials to the remote repo running
- It's also possible to use an Azure Repository.
- It's also possible to configure a local git repository.
- You can get the URL of the git repo with
az webapp deployment source show --name <app-name> --resource-group <res-group>
and it's going to be the SCM URL of the app. - To clone it you will need the SCM credentials that you can get with
az webapp deployment list-publishing-profiles --resource-group <res-group> -n <name>
- You can get the URL of the git repo with
Webjobs
Azure WebJobs are background tasks that run in the Azure App Service environment. They allow developers to execute scripts or programs alongside their web applications, making it easier to handle asynchronous or time-intensive operations such as file processing, data handling, or scheduled tasks. There are 2 types of web jobs:
- Continuous: Runs indefinitely in a loop and it’s triggered as soon as it’s created. It’s ideal for tasks that require constant processing. However, if the app stops running because Always On is disabled and it hasn’t received a request in the last 20mins, the web job will also stop.
- Triggered: Runs on-demand or based on a schedule. It’s best suited for periodic tasks, such as batch data updates or maintenance routines.
Webjobs are very interesting from an attackers perspective as they could be used to execute code in the environment and escalate privileges to the attached managed identities.
Moreover, it's always interesting to check the logs generated by the Webjobs as they could contain sensitive information.
Slots
Azure App Service Slots are used to deploy different versions of the application to the same App Service. This allows developers to test new features or changes in a separate environment before deploying them to the production environment.
Moreover, it's possible to route a percentage of the traffic to a specific slot, which is useful for A/B testing, and for backdoor purposes.
Azure Function Apps
Basically Azure Function apps are a subset of Azure App Service in the web console and if you go to the web console and list all the app services or execute az webapp list
in az cli you will be able to see the Function apps also listed in there.
Therefore, both services actually have mostly the same configurations, features and options in the az cli, although they might configure them a bit differently (like default values of appsettings or the use of an Storage Account in the Function apps).
Enumeration
# List webapps
az webapp list
## Less information
az webapp list --query "[].{hostName: defaultHostName, state: state, name: name, resourcegroup: resourceGroup}" -o table
## Get SCM URL of each webapp
az webapp list | grep '"name"' | grep "\.scm\." | awk '{print $2}' | sed 's/"//g'
# Get info about 1 app
az webapp show --name <name> --resource-group <res-group>
# Get instances of a webapp
az webapp list-instances --name <name> --resource-group <res-group>
## If you have enough perm you can go to the "consoleUrl" and access a shell inside the instance form the web
# Get access restrictions of an app
az webapp config access-restriction show --name <name> --resource-group <res-group>
# Remove access restrictions
az webapp config access-restriction remove --resource-group <res-group> -n <name> --rule-name <rule-name>
# Get connection strings of a webapp
az webapp config connection-string list --name <name> --resource-group <res-group>
# Get appsettings of an app
az webapp config appsettings list --name <name> --resource-group <res-group>
# Get SCM and FTP credentials
az webapp deployment list-publishing-profiles --name <name> --resource-group <res-group>
# Get configured Auth information
az webapp auth show --name <app-name> --resource-group <res-group>
# Get backups of a webapp
az webapp config backup list --webapp-name <name> --resource-group <res-group>
# Get backups scheduled for a webapp
az webapp config backup show --webapp-name <name> --resource-group <res-group>
# Get snapshots
az webapp config snapshot list --resource-group <res-group> -n <name>
# Restore snapshot
az webapp config snapshot restore -g <res-group> -n <name> --time 2018-12-11T23:34:16.8388367
# Get slots
az webapp deployment slot list --name <AppName> --resource-group <ResourceGroupName> --output table
az webapp show --slot <SlotName> --name <AppName> --resource-group <ResourceGroupName>
# Get traffic-routing
az webapp traffic-routing show --name <AppName> --resource-group <ResourceGroupName>
# Get used container by the app
az webapp config container show --name <name> --resource-group <res-group>
# Get storage account configurations of a webapp (contains access key)
az webapp config storage-account list --name <name> --resource-group <res-group>
# Get configured container (if any) in the webapp, it could contain credentials
az webapp config container show --name <name> --resource-group <res-group>
# Get git URL to access the code
az webapp deployment source config-local-git --resource-group <res-group> -n <name>
# Get Webjobs
az webapp webjob continuous list --resource-group <res-group> --name <app-name>
az webapp webjob triggered list --resource-group <res-group> --name <app-name>
# Read webjobs logs with Azure permissions
az rest --method GET --url "<SCM-URL>/vfs/data/jobs/<continuous | triggered>/rev5/job_log.txt" --resource "https://management.azure.com/"
az rest --method GET --url "https://lol-b5fyaeceh4e9dce0.scm.canadacentral-01.azurewebsites.net/vfs/data/jobs/continuous/rev5/job_log.txt" --resource "https://management.azure.com/"
# Read webjobs logs with SCM credentials
curl "https://windowsapptesting-ckbrg3f0hyc8fkgp.scm.canadacentral-01.azurewebsites.net/vfs/data/jobs/continuous/lala/job_log.txt" \
--user '<username>:<password>' -v
# Get connections of a webapp
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>
Examples to generate Web Apps
Python from local
This tutorial is based on the one from https://learn.microsoft.com/en-us/azure/app-service/quickstart-python.
# Clone repository
git clone https://github.com/Azure-Samples/msdocs-python-flask-webapp-quickstart
cd msdocs-python-flask-webapp-quickstart
# Create webapp from this code
az webapp up --runtime PYTHON:3.9 --sku B1 --logs
Logging into the SCM portal or logging via FTP it's possible to see in /wwwroot
the compressed file output.tar.gz
that contains the code of the webapp.
tip
Just connecting via FTP and modifying the file output.tar.gz
isn't enough to change the code executed by the webapp.
An attacker could download this file, modify it, and upload it again to execute arbitrary code in the webapp.
Python from Github
This tutorial is based on the previous one but using a Github repository.
- Fork the repo msdocs-python-flask-webapp-quickstart in your Github account.
- Create a new python Web App in Azure
- In
Deployment Center
change the source, login with Github, select the forked repo and clickSave
.
Like in the previous case, logging into the SCM portal or logging via FTP it's possible to see in /wwwroot
the compressed file output.tar.gz
that contains the code of the webapp.
tip
Just connecting via FTP and modifying the file output.tar.gz
and retriggering a deployment isn't enough to change the code executed by the webapp.
Privilege Escalation
References
- https://learn.microsoft.com/en-in/azure/app-service/overview
- https://learn.microsoft.com/en-us/azure/app-service/overview-hosting-plans
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.