# Az - Function Apps {{#include ../../../banners/hacktricks-training.md}} ## Osnovne Informacije **Azure Function Apps** su **serverless compute service** koje vam omogućavaju da pokrećete male delove koda, nazvane **functions**, bez upravljanja osnovnom infrastrukturom. Dizajnirane su da izvršavaju kod kao odgovor na različite okidače, kao što su **HTTP zahtevi, tajmeri ili događaji iz drugih Azure servisa** poput Blob Storage ili Event Hubs. Function Apps podržavaju više programskih jezika, uključujući C#, Python, JavaScript i Java, što ih čini svestranim za izgradnju **aplikacija vođenih događajima**, automatizaciju radnih tokova ili integraciju servisa. Troškovi su efikasni, jer obično plaćate samo vreme obrade kada se vaš kod izvršava. > [!NOTE] > Imajte na umu da su **Functions podskup App Services**, stoga će mnoge od funkcija o kojima se ovde govori koristiti i aplikacije kreirane kao Azure Apps (`webapp` u cli). ### Različiti Planovi - **Flex Consumption Plan**: Nudi **dinamičko, događajima vođeno skaliranje** sa plaćanjem po korišćenju, dodajući ili uklanjajući instance funkcija na osnovu potražnje. Podržava **virtuelno umrežavanje** i **pre-provisioned instances** kako bi se smanjili hladni startovi, što ga čini pogodnim za **varijabilne radne opterećenja** koja ne zahtevaju podršku kontejnera. - **Traditional Consumption Plan**: Podrazumevani serverless izbor, gde **plaćate samo za resurse obrade kada funkcije rade**. Automatski se skalira na osnovu dolaznih događaja i uključuje **optimizacije hladnog starta**, ali ne podržava implementacije kontejnera. Idealno za **intermitentna radna opterećenja** koja zahtevaju automatsko skaliranje. - **Premium Plan**: Dizajniran za **dosledne performanse**, sa **prewarmed workers** kako bi se eliminisali hladni startovi. Nudi **produžene vreme izvršenja, virtuelno umrežavanje**, i podržava **prilagođene Linux slike**, što ga čini savršenim za **aplikacije od kritične važnosti** koje zahtevaju visoke performanse i napredne funkcije. - **Dedicated Plan**: Radi na posvećenim virtuelnim mašinama sa **predvidljivim naplatama** i podržava ručno ili automatsko skaliranje. Omogućava pokretanje više aplikacija na istom planu, pruža **izolaciju obrade**, i osigurava **siguran pristup mreži** putem App Service Environments, što ga čini idealnim za **dugotrajne aplikacije** koje zahtevaju doslednu alokaciju resursa. - **Container Apps**: Omogućava implementaciju **kontejnerizovanih funkcija** u upravljanom okruženju, zajedno sa mikroservisima i API-ima. Podržava prilagođene biblioteke, migraciju nasleđenih aplikacija, i **GPU obradu**, eliminišući upravljanje Kubernetes klasterima. Idealno za **događajima vođene, skalabilne kontejnerizovane aplikacije**. ### **Storage Buckets** Kada kreirate novu Function App koja nije kontejnerizovana (ali daje kod za izvršavanje), **kod i drugi podaci vezani za funkciju biće pohranjeni u Storage nalogu**. Po defaultu, web konzola će kreirati novi za svaku funkciju kako bi pohranila kod. Štaviše, modifikovanjem koda unutar bucket-a (u različitim formatima u kojima može biti pohranjen), **kod aplikacije će biti modifikovan na novi i izvršen** sledeći put kada se funkcija pozove. > [!CAUTION] > Ovo je veoma zanimljivo iz perspektive napadača jer **pristup za pisanje preko ovog bucket-a** omogućava napadaču da **kompromituje kod i eskalira privilegije** na upravljane identitete unutar Function App-a. > > Više o ovome u **odeljku o eskalaciji privilegija**. Takođe je moguće pronaći **master i funkcijske ključeve** pohranjene u storage nalogu u kontejneru **`azure-webjobs-secrets`** unutar foldera **``** u JSON datotekama koje možete pronaći unutra. Imajte na umu da Functions takođe omogućavaju pohranu koda na udaljenoj lokaciji jednostavno ukazujući na URL. ### Mrežno Umrežavanje Korišćenjem HTTP okidača: - Moguće je dati **pristup funkciji sa celog Interneta** bez potrebe za bilo kakvom autentifikacijom ili dati pristup na osnovu IAM-a. Iako je takođe moguće ograničiti ovaj pristup. - Takođe je moguće **dati ili ograničiti pristup** Function App-u iz **internih mreža (VPC)**. > [!CAUTION] > Ovo je veoma zanimljivo iz perspektive napadača jer bi moglo biti moguće **pivotsati na interne mreže** iz ranjive funkcije izložene Internetu. ### **Podešavanja Function App-a & Varijable Okruženja** Moguće je konfigurisati varijable okruženja unutar aplikacije, koje mogu sadržati osetljive informacije. Štaviše, po defaultu se kreiraju varijable okruženja **`AzureWebJobsStorage`** i **`WEBSITE_CONTENTAZUREFILECONNECTIONSTRING`** (među ostalima). Ove su posebno zanimljive jer **sadrže ključ naloga za kontrolu sa POTPUNIM dozvolama nad storage nalogom koji sadrži podatke aplikacije**. Ova podešavanja su takođe potrebna za izvršavanje koda iz Storage naloga. Ove varijable okruženja ili parametri konfiguracije takođe kontrolišu kako funkcija izvršava kod, na primer, ako **`WEBSITE_RUN_FROM_PACKAGE`** postoji, to će ukazivati na URL gde se nalazi kod aplikacije. ### **Function Sandbox** Unutar linux sandbox-a, izvorni kod se nalazi u **`/home/site/wwwroot`** u datoteci **`function_app.py`** (ako se koristi python), korisnik koji pokreće kod je **`app`** (bez sudo dozvola). U **Windows** funkciji koja koristi NodeJS, kod se nalazio u **`C:\home\site\wwwroot\HttpTrigger1\index.js`**, korisničko ime je bilo **`mawsFnPlaceholder8_f_v4_node_20_x86`** i bio je deo **grupa**: `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`. ### **Upravljane Identitete & Metapodaci** Baš kao i [**VMs**](vms/index.html), Functions mogu imati **Upravljane Identitete** od 2 tipa: Sistem dodeljen i Korisnik dodeljen. **Sistem dodeljen** će biti upravljani identitet koji **samo funkcija** koja ga ima dodeljenog može koristiti, dok su **korisnik dodeljeni** upravljani identiteti upravljani identiteti koje **bilo koja druga Azure usluga može koristiti**. > [!NOTE] > Baš kao u [**VMs**](vms/index.html), Functions mogu imati **1 sistem dodeljen** upravljani identitet i **several korisnik dodeljenih**, tako da je uvek važno pokušati pronaći sve njih ako kompromitujete funkciju jer biste mogli biti u mogućnosti da eskalirate privilegije na nekoliko upravljanih identiteta iz samo jedne funkcije. > > Ako se ne koristi sistemski upravljani identitet, ali su jedan ili više korisničkih upravljanih identiteta povezani sa funkcijom, po defaultu nećete moći dobiti nijedan token. Moguće je koristiti [**PEASS skripte**](https://github.com/peass-ng/PEASS-ng) za dobijanje tokena iz podrazumevanog upravljanog identiteta sa metapodataka krajnje tačke. Ili ih možete dobiti **ručno** kao što je objašnjeno u: {% embed url="https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html#azure-vm" %} Imajte na umu da treba da pronađete način da **proverite sve Upravljane Identitete koje funkcija ima povezane** jer ako to ne naznačite, metapodataka krajnja tačka će **koristiti samo podrazumevani** (proverite prethodni link za više informacija). ## Ključevi Pristupa > [!NOTE] > Imajte na umu da ne postoje RBAC dozvole za davanje pristupa korisnicima da pozivaju funkcije. **Poziv funkcije zavisi od okidača** odabranog prilikom kreiranja i ako je odabran HTTP okidač, možda će biti potrebno koristiti **ključ pristupa**. Kada kreirate krajnju tačku unutar funkcije koristeći **HTTP okidač**, moguće je naznačiti **nivo autorizacije ključa pristupa** potreban za aktiviranje funkcije. Dostupne su tri opcije: - **ANONYMOUS**: **Svi** mogu pristupiti funkciji putem URL-a. - **FUNCTION**: Krajnja tačka je dostupna samo korisnicima koji koriste **ključ funkcije, hosta ili master ključa**. - **ADMIN**: Krajnja tačka je dostupna samo korisnicima sa **master ključem**. **Tipovi ključeva:** - **Funkcijski Ključevi:** Funkcijski ključevi mogu biti ili podrazumevani ili korisnički definisani i dizajnirani su da omogućavaju pristup isključivo **određenim funkcijskim krajnjim tačkama** unutar Function App-a, omogućavajući finiju kontrolu pristupa nad krajnjim tačkama. - **Host Ključevi:** Host ključevi, koji takođe mogu biti podrazumevani ili korisnički definisani, pružaju pristup **svim funkcijskim krajnjim tačkama unutar Function App-a sa FUNCTION nivoom pristupa**. - **Master Ključ:** Master ključ (`_master`) služi kao administrativni ključ koji nudi povišene dozvole, uključujući pristup svim funkcijskim krajnjim tačkama (uključujući ADMIN nivo pristupa). Ovaj **ključ se ne može opozvati.** - **Sistemski Ključevi:** Sistemski ključevi su **upravljani specifičnim ekstenzijama** i potrebni su za pristup webhook krajnjim tačkama koje koriste interni komponenti. Primeri uključuju Event Grid okidač i Durable Functions, koji koriste sistemske ključeve za sigurno interagovanje sa svojim API-ima. > [!TIP] > Primer za pristup funkciji API krajnjoj tački koristeći ključ: > > `https://.azurewebsites.net/api/?code=` ### Osnovna Autentifikacija Baš kao u App Services, Functions takođe podržavaju osnovnu autentifikaciju za povezivanje sa **SCM** i **FTP** za implementaciju koda koristeći **korisničko ime i lozinku u URL-u** koji pruža Azure. Više informacija o tome u: {{#ref}} az-app-services.md {{#endref}} ### Github Zasnovane Implementacije Kada se funkcija generiše iz Github repozitorijuma, Azure web konzola omogućava **automatsko kreiranje Github Workflow-a u specifičnom repozitorijumu** tako da kada god se ovaj repozitorijum ažurira, kod funkcije se ažurira. U stvari, Github Action yaml za python funkciju izgleda ovako:
Github Action Yaml ```yaml # Docs for the Azure Web Apps Deploy action: https://github.com/azure/functions-action # More GitHub Actions for Azure: https://github.com/Azure/actions # More info on Python, GitHub Actions, and Azure Functions: https://aka.ms/python-webapps-actions name: Build and deploy Python project to Azure Function App - funcGithub on: push: branches: - main workflow_dispatch: env: AZURE_FUNCTIONAPP_PACKAGE_PATH: "." # set this to the path to your web app project, defaults to the repository root PYTHON_VERSION: "3.11" # set this to the python version to use (supports 3.6, 3.7, 3.8) jobs: build: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Setup Python version uses: actions/setup-python@v5 with: python-version: ${{ env.PYTHON_VERSION }} - name: Create and start virtual environment run: | python -m venv venv source venv/bin/activate - name: Install dependencies run: pip install -r requirements.txt # Optional: Add step to run tests here - name: Zip artifact for deployment run: zip release.zip ./* -r - name: Upload artifact for deployment job uses: actions/upload-artifact@v4 with: name: python-app path: | release.zip !venv/ deploy: runs-on: ubuntu-latest needs: build permissions: id-token: write #This is required for requesting the JWT steps: - name: Download artifact from build job uses: actions/download-artifact@v4 with: name: python-app - name: Unzip artifact for deployment run: unzip release.zip - name: Login to Azure uses: azure/login@v2 with: client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_6C3396368D954957BC58E4C788D37FD1 }} tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_7E50AEF6222E4C3DA9272D27FB169CCD }} subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_905358F484A74277BDC20978459F26F4 }} - name: "Deploy to Azure Functions" uses: Azure/functions-action@v1 id: deploy-to-function with: app-name: "funcGithub" slot-name: "Production" package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }} ```
Pored toga, **Upravljani identitet** se takođe kreira kako bi Github akcija iz repozitorijuma mogla da se prijavi u Azure. To se postiže generisanjem Federated kredencijala preko **Upravljanog identiteta** koji omogućava **Izdavaču** `https://token.actions.githubusercontent.com` i **Identifikatoru subjekta** `repo:/:ref:refs/heads/`. > [!CAUTION] > Stoga, svako ko kompromituje taj repozitorijum će moći da kompromituje funkciju i Upravljene identitete povezane s njom. ### Implementacije zasnovane na kontejnerima Nisu svi planovi omogućili implementaciju kontejnera, ali za one koji to rade, konfiguracija će sadržati URL kontejnera. U API-ju, podešavanje **`linuxFxVersion`** će imati nešto poput: `DOCKER|mcr.microsoft.com/...`, dok će u web konzoli konfiguracija prikazivati **podešavanja slike**. Pored toga, **niti jedan izvorni kod neće biti pohranjen u skladištu** povezanu sa funkcijom jer to nije potrebno. ## Enumeracija {{#tabs }} {{#tab name="az cli" }} ```bash # 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 --resource-group ## If "linuxFxVersion" has something like: "DOCKER|mcr.microsoft.com/..." ## This is using a container # Get details about the source of the function code az functionapp deployment source show \ --name \ --resource-group ## If error like "This is currently not supported." ## Then, this is probalby using a container # Get more info if a container is being used az functionapp config container show \ --name \ --resource-group # Get settings (and privesc to the sorage account) az functionapp config appsettings list --name --resource-group # Check if a domain was assigned to a function app az functionapp config hostname list --webapp-name --resource-group # Get SSL certificates az functionapp config ssl list --resource-group # Get network restrictions az functionapp config access-restriction show --name --resource-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//resourceGroups//providers/Microsoft.Web/sites//functions?api-version=2024-04-01" # Get source code with Master Key of the function curl "?code=" ## Python example curl "https://newfuncttest123.azurewebsites.net/admin/vfs/home/site/wwwroot/function_app.py?code=" -v # Get source code az rest --url "https://management.azure.com//resourceGroups//providers/Microsoft.Web/sites//hostruntime/admin/vfs/function_app.py?relativePath=1&api-version=2022-03-01" ``` {{#endtab }} {{#tab name="Az Powershell" }} ```powershell Get-Command -Module Az.Functions # Lists all Function Apps in the current subscription or in a specific resource group. Get-AzFunctionApp -ResourceGroupName # Displays the regions where Azure Function Apps are available for deployment. Get-AzFunctionAppAvailableLocation # Retrieves details about Azure Function App plans in a subscription or resource group. Get-AzFunctionAppPlan -ResourceGroupName -Name # Retrieves the app settings for a specific Azure Function App. Get-AzFunctionAppSetting -Name -ResourceGroupName ``` {{#endtab }} {{#endtabs }} ## Eskalacija privilegija {{#ref}} ../az-privilege-escalation/az-functions-app-privesc.md {{#endref}} ## Reference - [https://learn.microsoft.com/en-us/azure/azure-functions/functions-openapi-definition](https://learn.microsoft.com/en-us/azure/azure-functions/functions-openapi-definition) {{#include ../../../banners/hacktricks-training.md}}