Az - Function Apps
Reading time: 14 minutes
tip
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos su github.
Informazioni di Base
Azure Function Apps sono un servizio di calcolo serverless che consente di eseguire piccoli pezzi di codice, chiamati funzioni, senza gestire l'infrastruttura sottostante. Sono progettate per eseguire codice in risposta a vari trigger, come richieste HTTP, timer o eventi da altri servizi Azure come Blob Storage o Event Hubs. Le Function Apps supportano più linguaggi di programmazione, tra cui C#, Python, JavaScript e Java, rendendole versatili per costruire applicazioni basate su eventi, automatizzare flussi di lavoro o integrare servizi. Sono economiche, poiché di solito si paga solo per il tempo di calcolo utilizzato quando il codice viene eseguito.
note
Nota che le Funzioni sono un sottoinsieme dei Servizi App, pertanto, molte delle funzionalità discusse qui saranno utilizzate anche dalle applicazioni create come Azure Apps (webapp
in cli).
Piani Differenti
- Piano di Consumo Flessibile: Offre scalabilità dinamica e basata su eventi con prezzi pay-as-you-go, aggiungendo o rimuovendo istanze di funzione in base alla domanda. Supporta rete virtuale e istanze pre-provisionate per ridurre i cold start, rendendolo adatto per carichi di lavoro variabili che non richiedono supporto per container.
- Piano di Consumo Tradizionale: L'opzione serverless predefinita, dove si paga solo per le risorse di calcolo quando le funzioni vengono eseguite. Si scala automaticamente in base agli eventi in arrivo e include ottimizzazioni per i cold start, ma non supporta il deployment di container. Ideale per carichi di lavoro intermittenti che richiedono scalabilità automatica.
- Piano Premium: Progettato per prestazioni costanti, con lavoratori pre-riscaldati per eliminare i cold start. Offre tempi di esecuzione estesi, rete virtuale e supporta immagini Linux personalizzate, rendendolo perfetto per applicazioni mission-critical che necessitano di alte prestazioni e funzionalità avanzate.
- Piano Dedicato: Esegue su macchine virtuali dedicate con fatturazione prevedibile e supporta scalabilità manuale o automatica. Consente di eseguire più app sullo stesso piano, fornisce isolamento di calcolo e garantisce accesso sicuro alla rete tramite App Service Environments, rendendolo ideale per applicazioni a lungo termine che necessitano di allocazione costante delle risorse.
- Container Apps: Consente di distribuire app di funzione containerizzate in un ambiente gestito, insieme a microservizi e API. Supporta librerie personalizzate, migrazione di app legacy e elaborazione GPU, eliminando la gestione del cluster Kubernetes. Ideale per applicazioni containerizzate scalabili e basate su eventi.
Storage Buckets
Quando si crea una nuova Function App non containerizzata (ma si fornisce il codice da eseguire), il codice e altri dati relativi alla Funzione saranno memorizzati in un account di Storage. Per impostazione predefinita, la console web creerà un nuovo account per ogni funzione per memorizzare il codice.
Inoltre, modificando il codice all'interno del bucket (nei diversi formati in cui potrebbe essere memorizzato), il codice dell'app verrà modificato con il nuovo e verrà eseguito la prossima volta che la Funzione viene chiamata.
caution
Questo è molto interessante dal punto di vista di un attaccante poiché l'accesso in scrittura su questo bucket consentirà a un attaccante di compromettere il codice e aumentare i privilegi alle identità gestite all'interno della Function App.
Maggiori informazioni su questo nella sezione sull'escalation dei privilegi.
È anche possibile trovare le chiavi master e delle funzioni memorizzate nell'account di storage nel contenitore azure-webjobs-secrets
all'interno della cartella <app-name>
nei file JSON che puoi trovare all'interno.
Nota che le Funzioni consentono anche di memorizzare il codice in una posizione remota semplicemente indicando l'URL.
Networking
Utilizzando un trigger HTTP:
- È possibile dare accesso a una funzione da tutto Internet senza richiedere alcuna autenticazione o dare accesso basato su IAM. Anche se è possibile limitare questo accesso.
- È anche possibile dare o limitare l'accesso a una Function App da una rete interna (VPC).
caution
Questo è molto interessante dal punto di vista di un attaccante poiché potrebbe essere possibile pivotare verso reti interne da una Function vulnerabile esposta a Internet.
Impostazioni della Function App & Variabili d'Ambiente
È possibile configurare variabili d'ambiente all'interno di un'app, che potrebbero contenere informazioni sensibili. Inoltre, per impostazione predefinita, le variabili d'ambiente AzureWebJobsStorage
e WEBSITE_CONTENTAZUREFILECONNECTIONSTRING
(tra le altre) vengono create. Queste sono particolarmente interessanti perché contengono la chiave dell'account per controllare con PERMESSI COMPLETI l'account di storage contenente i dati dell'applicazione. Queste impostazioni sono anche necessarie per eseguire il codice dall'Account di Storage.
Queste variabili d'ambiente o parametri di configurazione controllano anche come la Funzione esegue il codice, ad esempio se WEBSITE_RUN_FROM_PACKAGE
esiste, indicherà l'URL dove si trova il codice dell'applicazione.
Function Sandbox
All'interno della sandbox linux il codice sorgente si trova in /home/site/wwwroot
nel file function_app.py
(se viene utilizzato python) l'utente che esegue il codice è app
(senza permessi sudo).
In una funzione Windows che utilizza NodeJS il codice si trovava in C:\home\site\wwwroot\HttpTrigger1\index.js
, il nome utente era mawsFnPlaceholder8_f_v4_node_20_x86
ed era parte dei gruppi: 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
.
Identità Gestite & Metadati
Proprio come VM, le Funzioni possono avere Identità Gestite di 2 tipi: Assegnate dal sistema e Assegnate dall'utente.
L'identità assegnata dal sistema sarà un'identità gestita che solo la funzione a cui è assegnata potrà utilizzare, mentre le identità gestite assegnate dall'utente sono identità gestite che qualsiasi altro servizio Azure potrà utilizzare.
note
Proprio come in VM, le Funzioni possono avere 1 identità gestita assegnata dal sistema e diverse identità assegnate dall'utente, quindi è sempre importante cercare di trovare tutte se si compromette la funzione perché si potrebbe essere in grado di aumentare i privilegi a diverse identità gestite da una sola Funzione.
Se non viene utilizzata un'identità gestita dal sistema ma una o più identità gestite dall'utente sono collegate a una funzione, per impostazione predefinita non sarà possibile ottenere alcun token.
È possibile utilizzare gli script PEASS per ottenere token dall'identità gestita predefinita dall'endpoint dei metadati. Oppure potresti ottenerli manualmente come spiegato in:
Nota che è necessario trovare un modo per controllare tutte le Identità Gestite a cui una funzione è collegata poiché se non lo indichi, l'endpoint dei metadati utilizzerà solo quella predefinita (controlla il link precedente per ulteriori informazioni).
Chiavi di Accesso
note
Nota che non ci sono permessi RBAC per dare accesso agli utenti per invocare le funzioni. L'invocazione della funzione dipende dal trigger selezionato quando è stata creata e se è stato selezionato un Trigger HTTP, potrebbe essere necessario utilizzare una chiave di accesso.
Quando si crea un endpoint all'interno di una funzione utilizzando un trigger HTTP, è possibile indicare il livello di autorizzazione della chiave di accesso necessario per attivare la funzione. Sono disponibili tre opzioni:
- ANONYMOUS: Tutti possono accedere alla funzione tramite l'URL.
- FUNCTION: L'endpoint è accessibile solo agli utenti che utilizzano una chiave di funzione, host o master.
- ADMIN: L'endpoint è accessibile solo agli utenti con una chiave master.
Tipo di chiavi:
- Chiavi di Funzione: Le chiavi di funzione possono essere predefinite o definite dall'utente e sono progettate per concedere accesso esclusivamente a endpoint di funzione specifici all'interno di una Function App consentendo un accesso più dettagliato sugli endpoint.
- Chiavi Host: Le chiavi host, che possono essere anch'esse predefinite o definite dall'utente, forniscono accesso a tutti gli endpoint di funzione all'interno di una Function App con livello di accesso FUNCTION.
- Chiave Master: La chiave master (
_master
) funge da chiave amministrativa che offre permessi elevati, incluso l'accesso a tutti gli endpoint di funzione (incluso il livello di accesso ADMIN). Questa chiave non può essere revocata. - Chiavi di Sistema: Le chiavi di sistema sono gestite da estensioni specifiche e sono necessarie per accedere agli endpoint webhook utilizzati dai componenti interni. Esempi includono il trigger Event Grid e le Funzioni Durature, che utilizzano chiavi di sistema per interagire in modo sicuro con le rispettive API.
tip
Esempio per accedere a un endpoint API di funzione utilizzando una chiave:
https://<function_uniq_name>.azurewebsites.net/api/<endpoint_name>?code=<access_key>
Autenticazione di Base
Proprio come nei Servizi App, le Funzioni supportano anche l'autenticazione di base per connettersi a SCM e FTP per distribuire codice utilizzando un nome utente e una password in un URL fornito da Azure. Maggiori informazioni su questo in:
Distribuzioni Basate su Github
Quando una funzione è generata da un repo Github, la console web di Azure consente di creare automaticamente un Workflow Github in un repository specifico in modo che ogni volta che questo repository viene aggiornato, il codice della funzione venga aggiornato. In realtà, il file yaml dell'azione Github per una funzione python appare così:
Github Action 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 }}
Inoltre, viene creata un'Identità Gestita affinché l'azione Github del repository possa accedere ad Azure con essa. Questo avviene generando una credenziale Federata sull'Identità Gestita che consente all'Emittente https://token.actions.githubusercontent.com
e all'Identificatore del Soggetto repo:<org-name>/<repo-name>:ref:refs/heads/<branch-name>
.
caution
Pertanto, chiunque comprometta quel repository sarà in grado di compromettere la funzione e le Identità Gestite ad essa collegate.
Distribuzioni Basate su Container
Non tutti i piani consentono di distribuire container, ma per quelli che lo fanno, la configurazione conterrà l'URL del container. Nell'API, l'impostazione linuxFxVersion
avrà qualcosa come: DOCKER|mcr.microsoft.com/...
, mentre nella console web, la configurazione mostrerà le impostazioni dell'immagine.
Inoltre, nessun codice sorgente sarà memorizzato nell'account di archiviazione relativo alla funzione poiché non è necessario.
Enumerazione
# List all the functions
az functionapp list
# 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 \
--name <app-name> \
--resource-group <res-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 <name> \
--resource-group <res-group>
# 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>
# Get SSL certificates
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 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>"
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"
Escalation dei privilegi
Riferimenti
tip
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos su github.