A365 AI agents sending HTTP requests to non-standard ports may indicate covert communication channels used by adversaries to exfiltrate data or establish command and control. SOC teams should proactively hunt for this behavior in Azure Sentinel to identify potential lateral movement or data exfiltration attempts leveraging unusual network patterns.
KQL Query
let IdentityIdtoUPN = materialize (
IdentityInfo
| distinct AccountObjectId, AccountUpn
| extend AccountObjectId = tostring(AccountObjectId)
| where isnotempty(AccountObjectId) and isnotempty(AccountUpn));
AIAgentsInfo
| where RegistrySource == "A365"
| summarize arg_max(Timestamp, *) by AIAgentId
| extend RawAgentInfoJson = parse_json(RawAgentInfo)
| extend DeveloperName = RawAgentInfoJson.developerName
| extend OwnerId = tostring(RawAgentInfoJson.owners[0].entityId)
| extend CreatorId = tostring(RawAgentInfoJson.creatorId)
| join kind=leftouter IdentityIdtoUPN on $left.OwnerId == $right.AccountObjectId
| project-rename OwnerUpn = AccountUpn
| join kind=leftouter IdentityIdtoUPN on $left.CreatorId == $right.AccountObjectId
| project-rename CreatorUpn = AccountUpn
| where isnotempty(AgentActionTriggers)
| extend AgentActionTriggersJson = parse_json(AgentActionTriggers)
| where array_length(AgentActionTriggersJson) > 1
| mv-expand Trigger = AgentActionTriggersJson
| extend ServerUrls = Trigger.serverUrls
| mv-expand Url = ServerUrls
| extend ParsedUrl = parse_url(tostring(Url))
| extend Port = tostring(ParsedUrl["Port"])
| where isnotempty(Port) and Port != "443"
| project-away RawAgentInfoJson, AgentActionTriggersJson, ParsedUrl, ServerUrls, OwnerId, CreatorId, AccountObjectId, AccountObjectId1
| project-reorder AgentCreationTime, AIAgentId, AIAgentName, Url, Port, OwnerUpn, CreatorUpn, DeveloperName
id: 9d0e1f2a-3b4c-5d6e-7f8a-9b0c1d2e3f4a
name: A365 AI Agents - HTTP Requests to Non-standard Ports
description: |
This query identifies A365 AI agents that send HTTP requests to endpoints using non-standard ports (other than 443).
Communication over uncommon ports can indicate suspicious activity, unauthorized network communication, or attempts to bypass security controls.
Such behavior may expose sensitive data or create opportunities for attackers to exploit less-monitored channels.
Recommended Action: Review these agents to confirm whether using non-standard ports is necessary for the business scenario.
If not required, update configurations to use standard secure ports (443 for HTTPS).
For legitimate use cases, document the justification and apply compensating controls such as network monitoring and firewall rules.
requiredDataConnectors: []
tactics:
- CommandAndControl
- Exfiltration
relevantTechniques:
- T1071
- T1041
query: |
let IdentityIdtoUPN = materialize (
IdentityInfo
| distinct AccountObjectId, AccountUpn
| extend AccountObjectId = tostring(AccountObjectId)
| where isnotempty(AccountObjectId) and isnotempty(AccountUpn));
AIAgentsInfo
| where RegistrySource == "A365"
| summarize arg_max(Timestamp, *) by AIAgentId
| extend RawAgentInfoJson = parse_json(RawAgentInfo)
| extend DeveloperName = RawAgentInfoJson.developerName
| extend OwnerId = tostring(RawAgentInfoJson.owners[0].entityId)
| extend CreatorId = tostring(RawAgentInfoJson.creatorId)
| join kind=leftouter IdentityIdtoUPN on $left.OwnerId == $right.AccountObjectId
| project-rename OwnerUpn = AccountUpn
| join kind=leftouter IdentityIdtoUPN on $left.CreatorId == $right.AccountObjectId
| project-rename CreatorUpn = AccountUpn
| where isnotempty(AgentActionTriggers)
| extend AgentActionTriggersJson = parse_json(AgentActionTriggers)
| where array_length(AgentActionTriggersJson) > 1
| mv-expand Trigger = AgentActionTriggersJson
| extend ServerUrls = Trigger.serverUrls
| mv-expand Url = ServerUrls
| extend ParsedUrl = parse_url(tostring(Url))
| extend Port = tostring(ParsedUrl["Port"])
| where isnotempty(Port) and Port != "443"
| project-away RawAgentInfoJson, AgentActionTriggersJson, ParsedUrl, ServerUrls, OwnerId, CreatorId, AccountObjectId, AccountObjectId1
| project-reorder AgentCreationTime, AIAgentId, AIAgentName, Url, Port, OwnerUpn, CreatorUpn, DeveloperName
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: CreatorUpn
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: AIAgentName
- entityType: URL
fieldMappings:
- identifier: Url
columnName: Url
version: 1.0.0
| Sentinel Table | Notes |
|---|---|
IdentityInfo | Ensure this data connector is enabled |
Scenario: Microsoft Teams Scheduled Backup Job
Description: A scheduled backup job for Microsoft Teams uses a non-standard port (e.g., 8080) to communicate with an internal proxy or load balancer.
Filter/Exclusion: where ProcessName == "Teams" and ProcessCommandLine contains "backup" or ProcessCommandLine contains "scheduled"
Scenario: Azure DevOps Pipeline with Custom Agent
Description: A custom Azure DevOps agent running a pipeline may use a non-standard port (e.g., 8080) for internal communication with a private registry or artifact store.
Filter/Exclusion: where ProcessName == "AzureDevOpsAgent" and ProcessCommandLine contains "pipeline" or ProcessCommandLine contains "custom"
Scenario: Microsoft Intune Device Compliance Scan
Description: An Intune compliance scan might use a non-standard port (e.g., 8080) to communicate with a custom endpoint for policy enforcement or reporting.
Filter/Exclusion: where ProcessName == "IntuneClient" and ProcessCommandLine contains "compliance" or ProcessCommandLine contains "scan"
Scenario: Microsoft Exchange Online PowerShell Remote Connection
Description: A PowerShell script connecting to Exchange Online might use a non-standard port (e.g., 8080) due to a proxy configuration or custom gateway setup.
Filter/Exclusion: where ProcessName == "powershell.exe" and CommandLine contains "ExchangeOnline" or CommandLine contains "Connect-ExchangeOnline"
Scenario: Microsoft Defender for Endpoint Agent Communication
Description: The Microsoft Defender for Endpoint agent may use a non-standard port (e.g., 8080) to communicate with a private cloud instance or internal monitoring system.
Filter/Exclusion: `where ProcessName == “MsDefenderAgent” or ProcessName == “Microsoft Defender