# Az - App Services

{{#include ../../../banners/hacktricks-training.md}}

## App Service Basic Information

Azure App Services omogućava programerima da **prave, implementiraju i skaliraju web aplikacije, mobilne aplikacije i API-je bez problema**. Podržava više programskih jezika i integriše se sa raznim Azure alatima i uslugama za poboljšanu funkcionalnost i upravljanje.

Svaka aplikacija radi unutar sandbox-a, ali izolacija zavisi od App Service planova:

- Aplikacije u Free i Shared nivoima rade na **deljenim VM-ovima**
- Aplikacije u Standard i Premium nivoima rade na **posvećenim VM-ovima koje dele samo aplikacije** u istom App Service planu.
- Izolovani nivoi rade na **posvećenim VM-ovima na posvećenim virtuelnim mrežama**, poboljšavajući izolaciju aplikacija.

> [!WARNING]
> Imajte na umu da **nijedna** od tih izolacija **ne sprečava** druge uobičajene **web ranjivosti** (kao što su upload fajlova ili injekcije). I ako se koristi **identitet za upravljanje**, može biti u mogućnosti da **poveća privilegije na njih**.

Aplikacije imaju neke zanimljive konfiguracije:

- **Always On**: Osigurava da aplikacija uvek radi. Ako nije omogućeno, aplikacija će prestati da radi nakon 20 minuta neaktivnosti i ponovo će se pokrenuti kada se primi zahtev.
- Ovo je bitno ako imate webjob koji treba da radi kontinuirano, jer će webjob prestati ako aplikacija prestane.
- **SSH**: Ako je omogućeno, korisnik sa dovoljno dozvola može se povezati na aplikaciju koristeći SSH.
- **Debugging**: Ako je omogućeno, korisnik sa dovoljno dozvola može da debaguje aplikaciju. Međutim, ovo se automatski onemogućava svake 48h.
- **Web App + Database**: Web konzola omogućava kreiranje aplikacije sa bazom podataka. U ovom slučaju, moguće je odabrati bazu podataka koja će se koristiti (SQLAzure, PostgreSQL, MySQL, MongoDB) i takođe omogućava kreiranje Azure Cache za Redis.
- URL koji sadrži kredencijale za bazu podataka i Redis biće sačuvan u **appsettings**.
- **Container**: Moguće je implementirati kontejner na App Service tako što ćete navesti URL kontejnera i kredencijale za pristup.
- **Mounts**: Moguće je kreirati 5 mount-ova iz Storage naloga, a to su Azure Blob (samo za čitanje) ili Azure Files. Konfiguracija će sačuvati pristupni ključ preko Storage naloga.
- **Networking**: Može biti javno dostupno ili samo dostupno privatnim krajnjim tačkama iz VNet-a.

## Basic Authentication

Kada kreirate web aplikaciju (i Azure funkciju obično), moguće je naznačiti da želite da **osnovna autentifikacija bude omogućena** (podrazumevano onemogućena). Ovo u suštini **omogućava SCM (Source Control Manager) i FTP (File Transfer Protocol)** za aplikaciju, tako da će biti moguće implementirati aplikaciju koristeći te tehnologije.

Da biste pristupili SCM i FTP serverima, potrebni su **korisničko ime i lozinka**. Stoga, Azure pruža neke **API-je za dobijanje URL-ova** za te platforme i kredencijale.

**FTP server nema nikakvu posebnu magiju**, samo sa validnim URL-om, korisničkim imenom i lozinkom moguće je povezati se i dobiti dozvole za čitanje i pisanje u App okruženju.

SCM
Moguće je povezati se na SCM koristeći web pregledač na `https://<SMC-URL>/BasicAuth` i proveriti sve fajlove i implementacije tamo.

### Kudu

Kudu je platforma koja **upravlja i SCM-om i web i API interfejsom** za upravljanje App Service-om, i pruža Git-bazirane implementacije, daljinsko debagovanje i mogućnosti upravljanja fajlovima. Dostupan je kroz SCM URL definisan u web aplikaciji.

Imajte na umu da su Kudu verzije koje koriste App Services i Function Apps različite, pri čemu je verzija Function aplikacija mnogo ograničenija.

Neki zanimljivi krajnji tačke koje možete pronaći u Kudu su:
- `/BasicAuth`: Morate pristupiti ovom putu da **prijavite u Kudu**.
- `/DebugConsole`: Konzola koja vam omogućava da izvršavate komande u okruženju gde Kudu radi.
- Imajte na umu da ovo okruženje **nema pristup** metapodacima za dobijanje tokena.
- `/webssh/host`: Web-bazirani SSH klijent koji vam omogućava da se povežete unutar kontejnera gde aplikacija radi.
- Ovo okruženje **ima pristup** metapodacima kako bi dobilo tokene od dodeljenih upravljanih identiteta.
- `/Env`: Dobijte informacije o sistemu, postavkama aplikacije, env varijablama, konekcionim stringovima i HTTP header-ima.
- `/wwwroot/`: Glavni direktorijum web aplikacije. Možete preuzeti sve fajlove odavde.

Pored toga, Kudu je nekada bio otvoren izvor u [https://github.com/projectkudu/kudu](https://github.com/projectkudu/kudu), ali je projekat ukinut i upoređujući ponašanje trenutnog Kudu u Azure-u sa starim, moguće je primetiti da su **neke stvari već promenjene**.

## Sources

App Services omogućava da se kod učita kao zip fajl po defaultu, ali takođe omogućava povezivanje sa trećom stranom i dobijanje koda odatle.

- Trenutno podržani izvori trećih strana su **Github** i **Bitbucket**.
- Možete dobiti tokene za autentifikaciju pokretanjem `az rest --url "https://management.azure.com/providers/Microsoft.Web/sourcecontrols?api-version=2024-04-01"`
- Azure će po defaultu postaviti **Github Action** za implementaciju koda na App Service svaki put kada se kod ažurira.
- Takođe je moguće naznačiti **daljinski git repozitorij** (sa korisničkim imenom i lozinkom) da biste dobili kod odatle.
- Možete dobiti kredencijale za daljinski repozitorij pokretanjem `az webapp deployment source show --name <app-name> --resource-group <res-group>` ili `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"`
- Takođe je moguće koristiti **Azure Repository**.
- Takođe je moguće konfigurisati **lokalni git repozitorij**.
- Možete dobiti URL git repozitorija sa `az webapp deployment source show --name <app-name> --resource-group <res-group>` i to će biti SCM URL aplikacije.
- Da biste ga klonirali, biće vam potrebne SCM kredencijale koje možete dobiti sa `az webapp deployment list-publishing-profiles --resource-group <res-group> -n <name>`

## Webjobs

Azure WebJobs su **pozadinski zadaci koji se izvršavaju u Azure App Service okruženju**. Omogućavaju programerima da izvršavaju skripte ili programe zajedno sa svojim web aplikacijama, olakšavajući rukovanje asinhronim ili vremenski intenzivnim operacijama kao što su obrada fajlova, rukovanje podacima ili zakazani zadaci.
Postoje 2 tipa web jobova:
- **Continuous**: Radi neprekidno u petlji i aktivira se čim se kreira. Idealno je za zadatke koji zahtevaju konstantno procesiranje. Međutim, ako aplikacija prestane da radi jer je Always On onemogućen i nije primila zahtev u poslednjih 20 minuta, web job će takođe prestati.
- **Triggered**: Radi na zahtev ili na osnovu rasporeda. Najbolje je prilagođen za periodične zadatke, kao što su ažuriranja podataka ili rutinske održavanja.

Webjobs su veoma zanimljivi iz perspektive napadača jer se mogu koristiti za **izvršavanje koda** u okruženju i **povećanje privilegija** na dodeljene upravljane identitete.

Pored toga, uvek je zanimljivo proveriti **logove** koje generišu Webjobs jer mogu sadržati **osetljive informacije**.

## Slots

Azure App Service Slots se koriste za **implementaciju različitih verzija aplikacije** na istom App Service-u. Ovo omogućava programerima da testiraju nove funkcije ili promene u odvojenom okruženju pre nego što ih implementiraju u produkcijsko okruženje.

Pored toga, moguće je usmeriti **procenat saobraćaja** na određeni slot, što je korisno za A/B testiranje i za **backdoor svrhe**.

## Azure Function Apps

U suštini, **Azure Function aplikacije su podskup Azure App Service** u web konzoli i ako odete u web konzolu i navedete sve app servise ili izvršite `az webapp list` u az cli, moći ćete da **vidite i Function aplikacije navedene tamo**.

Stoga, obe usluge zapravo imaju većinom **iste konfiguracije, funkcije i opcije u az cli**, iako ih možda malo drugačije konfigurišu (kao što su podrazumevane vrednosti appsettings ili korišćenje Storage naloga u Function aplikacijama).

## Enumeration

{{#tabs }}
{{#tab name="az" }}
```bash
# 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>

# 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 }}

{{#tab name="Az Powershell" }}
```bash
Get-Command -Module Az.Websites

# Get App Services and Function Apps
Get-AzWebApp
# Get only App Services
Get-AzWebApp | ?{$_.Kind -notmatch "functionapp"}

# Retrieves details of a specific App Service Environment in the specified resource group.
Get-AzAppServiceEnvironment -ResourceGroupName <ResourceGroupName> -Name <Name>
# Retrieves the access restriction configuration for a specified Web App.
Get-AzWebAppAccessRestrictionConfig -ResourceGroupName <ResourceGroupName> -Name <Name>
# Retrieves the SSL certificates for a specified resource group.
Get-AzWebAppCertificate -ResourceGroupName <ResourceGroupName>
# Retrieves the continuous deployment URL for a containerized Web App.
Get-AzWebAppContainerContinuousDeploymentUrl -ResourceGroupName <ResourceGroupName> -Name <Name>
# Retrieves the list of continuous WebJobs for a specified Web App.
Get-AzWebAppWebJob -ResourceGroupName <ResourceGroupName> -AppName <AppName>
# Retrieves the list of triggered WebJobs for a specified Web App.
Get-AzWebAppTriggeredWebJob -ResourceGroupName <ResourceGroupName> -AppName <AppName>

# Retrieves details of a deleted Web App in the specified resource group.
Get-AzDeletedWebApp -ResourceGroupName <ResourceGroupName> -Name <Name>
# Retrieves a list of snapshots for a specified Web App.
Get-AzWebAppSnapshot -ResourceGroupName <ResourceGroupName> -Name <Name>
# Retrieves the history of a specific triggered WebJob for a Web App.
Get-AzWebAppTriggeredWebJobHistory -ResourceGroupName <ResourceGroupName> -AppName <AppName> -Name <Name>

# Retrieves information about deployment slots for a specified Web App.
Get-AzWebAppSlot -ResourceGroupName <ResourceGroupName> -Name <Name>
# Retrieves the continuous WebJobs for a specific deployment slot of a Web App.
Get-AzWebAppSlotWebJob -ResourceGroupName <ResourceGroupName> -AppName <AppName> -SlotName <SlotName>
# Retrieves the triggered WebJobs for a specific deployment slot of a Web App.
Get-AzWebAppSlotTriggeredWebJob -ResourceGroupName <ResourceGroupName> -AppName <AppName> -SlotName <SlotName>
# Retrieves the history of a specific triggered WebJob for a deployment slot of a Web App.
Get-AzWebAppSlotTriggeredWebJobHistory -ResourceGroupName <ResourceGroupName> -AppName <AppName> -SlotName <SlotName> -Name <Name>
# Retrieves the continuous WebJobs for a Web App.
Get-AzWebAppContinuousWebJob -ResourceGroupName <ResourceGroupName> -AppName <AppName>
# Retrieves the continuous WebJobs for a specific deployment slot of a Web App.
Get-AzWebAppSlotContinuousWebJob -ResourceGroupName <ResourceGroupName> -AppName <AppName> -SlotName <SlotName>

# Retrieves the traffic routing rules for a Web App.
Get-AzWebAppTrafficRouting -ResourceGroupName <ResourceGroupName> -WebAppName <WebAppName> -RuleName <RuleName>

# Retrieves details of a specific backup for a Web App.
Get-AzWebAppBackup -ResourceGroupName <ResourceGroupName> -Name <Name> -BackupId <BackupId>
# Retrieves the backup configuration for a Web App.
Get-AzWebAppBackupConfiguration -ResourceGroupName <ResourceGroupName> -Name <Name>
# Retrieves the list of all backups for a Web App.
Get-AzWebAppBackupList -ResourceGroupName <ResourceGroupName> -Name <Name>
```
{{#endtab }}

{{#tab name="az get all" }}
```bash
#!/bin/bash

# Get all App Service and Function Apps

# Define Azure subscription ID
azure_subscription="your_subscription_id"

# Log in to Azure
az login

# Select Azure subscription
az account set --subscription $azure_subscription

# Get all App Services in the specified subscription
list_app_services=$(az appservice list --query "[].{appServiceName: name, group: resourceGroup}" -o tsv)

# Iterate over each App Service
echo "$list_app_services" | while IFS=$'\t' read -r appServiceName group; do
# Get the type of the App Service
service_type=$(az appservice show --name $appServiceName --resource-group $group --query "kind" -o tsv)

# Check if it is a Function App and print its name
if [ "$service_type" == "functionapp" ]; then
echo "Function App Name: $appServiceName"
fi
done
```
{{#endtab }}
{{#endtabs }}


{{#ref}}
../az-privilege-escalation/az-app-services-privesc.md
{{#endref}}

## Primeri za generisanje Web Aplikacija

### Python sa lokalnog

Ovaj tutorijal se zasniva na onom sa [https://learn.microsoft.com/en-us/azure/app-service/quickstart-python](https://learn.microsoft.com/en-us/azure/app-service/quickstart-python?tabs=flask%2Cwindows%2Cazure-cli%2Cazure-cli-deploy%2Cdeploy-instructions-azportal%2Cterminal-bash%2Cdeploy-instructions-zip-azcli).
```bash
# 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
```
Prijavljivanje na SCM portal ili prijavljivanje putem FTP-a omogućava da se u `/wwwroot` vidi kompresovani fajl `output.tar.gz` koji sadrži kod web aplikacije.

> [!TIP]
> Samo povezivanje putem FTP-a i modifikovanje fajla `output.tar.gz` nije dovoljno da se promeni kod koji izvršava web aplikacija.

**Napadač bi mogao da preuzme ovaj fajl, modifikuje ga i ponovo ga otpremi da bi izvršio proizvoljan kod u web aplikaciji.**

### Python sa Github-a

Ovaj tutorijal se zasniva na prethodnom, ali koristi Github repozitorijum.

1. Forkujte repozitorijum msdocs-python-flask-webapp-quickstart na vašem Github nalogu.
2. Kreirajte novu python Web aplikaciju u Azure-u.
3. U `Deployment Center` promenite izvor, prijavite se sa Github-om, izaberite forkovani repozitorijum i kliknite na `Save`.

Kao u prethodnom slučaju, prijavljivanje na SCM portal ili prijavljivanje putem FTP-a omogućava da se u `/wwwroot` vidi kompresovani fajl `output.tar.gz` koji sadrži kod web aplikacije.

> [!TIP]
> Samo povezivanje putem FTP-a i modifikovanje fajla `output.tar.gz` i ponovo pokretanje implementacije nije dovoljno da se promeni kod koji izvršava web aplikacija.

## Eskalacija privilegija

{{#ref}}
../az-privilege-escalation/az-app-services-privesc.md
{{#endref}}

## Reference

- [https://learn.microsoft.com/en-in/azure/app-service/overview](https://learn.microsoft.com/en-in/azure/app-service/overview)
- [https://learn.microsoft.com/en-us/azure/app-service/overview-hosting-plans](https://learn.microsoft.com/en-us/azure/app-service/overview-hosting-plans)

{{#include ../../../banners/hacktricks-training.md}}
