Query Details

Copilot Studio - Exploit or RCE intent followed by MCP execution

Copilot Studio Mcp Exploit Execution Chain

Query

let IsExploitIntent = (Content:string) {
    isnotempty(Content) and (
        Content has_any ("remote code execution", "reverse shell", "metasploit",
            "run_shell_command", "vulnerabilities/exec", "kali linux",
            "execute command", "ejecuta el comando", "ejecuta un comando")
        or Content matches regex @"(?i)(execute|ejecuta|run).{0,40}(command|comando|shell)"
    )
};
let IsCommandTool = (Value:string) {
    tolower(Value) matches regex @"(run[_ -]?(shell|command|code)|execute[_ -]?(shell|command|code)|powershell|cmd\.exe|terminal|reverse[_ -]?shell|metasploit|kali|ssh[_ -]?exec|remote[_ -]?code[_ -]?execution|vulnerabilities/exec)"
};
let LegacyPrompts = AppEvents
| where Name == "BotMessageReceived"
| extend ConvId = tostring(Properties["conversationId"]),
         Content = tostring(Properties["text"])
| where IsExploitIntent(Content)
| summarize PromptSignals = count(), PromptFirstSeen = min(TimeGenerated),
    PromptLastSeen = max(TimeGenerated), UserId = take_any(UserId),
    ClientIP = take_any(ClientIP), ChannelId = take_any(tostring(Properties["channelId"])) by ConvId;
let LegacyTools = AppDependencies
| where AppRoleName == "Microsoft Copilot Studio" or DependencyType == "Connector"
| extend ConvId = tostring(Properties["conversationId"]), Tool = Name,
         ToolTarget = tostring(Target)
| where IsCommandTool(strcat(Tool, " ", ToolTarget))
| summarize ToolCalls = count(), ToolFailures = countif(Success == false),
    Tools = make_set(Tool, 20), Targets = make_set(ToolTarget, 20),
    ToolLastSeen = max(TimeGenerated) by ConvId;
let LegacyChain = LegacyPrompts
| join kind=inner LegacyTools on ConvId
| project TimeGenerated = max_of(PromptLastSeen, ToolLastSeen),
    FirstSeen = PromptFirstSeen, AccountName = iff(isempty(UserId), "unknown-agent", UserId),
    ClientIP, ConvId, OperationId = "", Agent = "", ChannelId,
    PromptSignals, ToolCalls, ToolFailures, Tools, Targets, Source = "Agent-level telemetry";
let ModernPrompts = AppDependencies
| where tostring(Properties["gen_ai.operation.name"]) == "invoke_agent"
| extend Content = tostring(Properties["gen_ai.input.messages"])
| where IsExploitIntent(Content)
| summarize PromptSignals = count(), PromptFirstSeen = min(TimeGenerated),
    PromptLastSeen = max(TimeGenerated),
    Agent = take_any(tostring(Properties["gen_ai.agent.name"])),
    ConvId = take_any(tostring(Properties["gen_ai.conversation.id"])),
    AccountName = take_any(coalesce(tostring(Properties["user.email"]),
        tostring(Properties["user.id"]), tostring(Properties["gen_ai.agent.name"]))),
    ClientIP = take_any(ClientIP),
    ChannelId = take_any(tostring(Properties["microsoft.channel.name"])) by OperationId;
let ModernTools = AppDependencies
| where tostring(Properties["gen_ai.operation.name"]) == "execute_tool"
| extend Tool = tostring(Properties["gen_ai.tool.name"]),
         ToolTarget = tostring(Target), ToolType = tostring(Properties["gen_ai.tool.type"])
| where IsCommandTool(strcat(Tool, " ", ToolType, " ", ToolTarget))
| summarize ToolCalls = count(), ToolFailures = countif(Success == false),
    Tools = make_set(Tool, 20), Targets = make_set(ToolTarget, 20),
    ToolLastSeen = max(TimeGenerated) by OperationId;
let ModernChain = ModernPrompts
| join kind=inner ModernTools on OperationId
| project TimeGenerated = max_of(PromptLastSeen, ToolLastSeen),
    FirstSeen = PromptFirstSeen, AccountName, ClientIP, ConvId, OperationId,
    Agent, ChannelId, PromptSignals, ToolCalls, ToolFailures, Tools, Targets,
    Source = "Environment telemetry";
union LegacyChain, ModernChain
| project TimeGenerated, FirstSeen, AccountName, ClientIP, Agent, ConvId,
    OperationId, ChannelId, PromptSignals, ToolCalls, ToolFailures, Tools,
    Targets, Source
| order by TimeGenerated desc

Explanation

This query is designed to detect potential security threats in a system by monitoring for specific patterns of behavior that indicate an exploit or remote code execution (RCE) attempt. Here's a simplified breakdown of what the query does:

  1. Purpose: The query identifies scenarios where there is an intent to exploit or execute remote commands, followed by the execution of a command-capable tool. This is particularly focused on activities within Copilot Studio and related tools.

  2. Data Sources: It uses data from Application Insights, specifically looking at AppEvents and AppDependencies.

  3. Detection Logic:

    • Exploit Intent: It checks for certain keywords or patterns in the content of messages that suggest an attempt to execute commands or use offensive tools (e.g., "remote code execution", "reverse shell").
    • Command Tool Usage: It identifies when tools capable of executing commands are used (e.g., PowerShell, cmd.exe, Metasploit).
  4. Correlation:

    • Legacy Systems: It correlates events and dependencies based on conversation IDs for older systems.
    • Modern Systems: It uses operation IDs for newer systems to correlate agent invocation and tool execution.
  5. Alerting:

    • If both exploit intent and command tool usage are detected in the same conversation or operation, it raises an alert.
    • The alert includes details like the time of the event, user account, client IP, and tools used.
  6. Severity and Frequency: The query is set to run every hour and has a high severity level, meaning it is considered a significant security risk.

  7. Incident Management: When an alert is triggered, it creates an incident in the system, grouping similar alerts to manage them efficiently.

Overall, this query is part of a security monitoring system that helps detect and respond to potential cyber threats by identifying suspicious activities related to remote command execution.