Query Details

MDE Click Fix Triage Query

Query

# ClickFix Triage Query

## Query Information

#### Description
To efficiently triage ClickFix incidents the *ClickFix Triage KQL Query* below is developed. The KQL query has the following input:
- VictimDeviceId: DeviceId of the device that triggered the ClickFix incident
- TopXEvents: Amount of events you want to collect before and after the Windows Run execution.
- TimeFrame: Min and max timeframe between the Windows Run execution and the last event collected.

These variables can be adjusted to your needs.

```KQL
let VictimDeviceId = "xxxxxxxxx";
let TopXEvents = 15;
let TimeFrame = 5m;
```
Based on these variables the KQL query collects the following information:
- 🛜 The *TopXEvents* network events before the compromise, they will most likely point to the infected (WordPress) site that hosted the fake captcha.
- ☢️ The RUNMRU event itself and the related registry key changes.
- 🛜 The *TopXEvents* post-compromise network events.
- ♻️ The *TopXEvents* post-compromise process events.
- 📁 The *TopXEvents* post-compromise file events.

## Defender XDR
```KQL
// Input variables
let VictimDeviceId = "xxxxxxxxx";
let TopXEvents = 15;
let TimeFrame = 5m;
// Input parameters for the forensic hunting query
let Parameters = dynamic(['http', 'https', 'Encoded', 'EncodedCommand', '-e', '-eC', '-enc', "-w", "Hidden"]);
let Executables = dynamic(["cmd", "powershell", "curl", "mshta"]);
let FilteredSIDs = dynamic(["S-1-5-18"]);
let RegKeyEvents =
    DeviceRegistryEvents
    | where DeviceId =~ VictimDeviceId
    | where ActionType == "RegistryValueSet"
    | where RegistryKey has "RunMRU"
    | where RegistryValueData has_any (Parameters) and RegistryValueData has_any (Executables)
    | extend LogType = "☢️ RunMRU Event"
    | project Timestamp, DeviceId, DeviceName, RegistryValueData, RegistryKey, LogType;
let RegKeyEventTimestamp = toscalar (RegKeyEvents | summarize Timestamp = max(Timestamp));
let NetworkEventsParser = materialize (DeviceNetworkEvents
    | where DeviceId =~ VictimDeviceId
    | where not(InitiatingProcessAccountSid in~ (FilteredSIDs))
    | where isnotempty(RemoteUrl)
    | extend MatchTimeStamp = RegKeyEventTimestamp
    | project Timestamp, RemoteIP, RemoteUrl, ReportId, DeviceId, DeviceName, MatchTimeStamp, InitiatingProcessCommandLine);
let PreInfectionNetworkEvents =
    NetworkEventsParser
    | where Timestamp between ((MatchTimeStamp - TimeFrame) .. MatchTimeStamp)
    | top TopXEvents by Timestamp desc
    | extend LogType = "🛜 Pre Infection Network Event";
let PostInfectionNetworkEvents =
    NetworkEventsParser
    | where Timestamp between (MatchTimeStamp .. (MatchTimeStamp + TimeFrame))
    | top TopXEvents by Timestamp asc
    | extend LogType = "🛜 Post Infection Network Event";
let PostInfectionProcessEvents = DeviceProcessEvents
    | where Timestamp between (RegKeyEventTimestamp .. (RegKeyEventTimestamp + TimeFrame))
    | top TopXEvents by Timestamp asc
    | where not(InitiatingProcessAccountSid in~ (FilteredSIDs))
    | extend LogType = "♻️ Post Infection Process Event"
    | project Timestamp, ReportId, LogType, DeviceId, DeviceName, ProcessCommandLine, InitiatingProcessCommandLine;
let PostInfectionFileEvents = DeviceFileEvents
    | where Timestamp between (RegKeyEventTimestamp .. (RegKeyEventTimestamp + TimeFrame))
    | top TopXEvents by Timestamp asc
    | where not(InitiatingProcessAccountSid in~ (FilteredSIDs))
    | extend LogType = "📁 Post Infection File Event"
    | project Timestamp, ReportId, LogType, DeviceId, DeviceName, ActionType, InitiatingProcessCommandLine, FolderPath;
union isfuzzy=false PreInfectionNetworkEvents,RegKeyEvents, PostInfectionNetworkEvents, PostInfectionProcessEvents, PostInfectionFileEvents
| sort by Timestamp asc
| project-reorder Timestamp, DeviceId, DeviceName, LogType, RemoteUrl, RegistryValueData, ProcessCommandLine, FolderPath, InitiatingProcessCommandLine
```

## Sentinel
```KQL
// Input variables
let VictimDeviceId = "xxxxxxxxx";
let TopXEvents = 15;
let TimeFrame = 5m;
// Input parameters for the forensic hunting query
let Parameters = dynamic(['http', 'https', 'Encoded', 'EncodedCommand', '-e', '-eC', '-enc', "-w", "Hidden"]);
let Executables = dynamic(["cmd", "powershell", "curl", "mshta"]);
let FilteredSIDs = dynamic(["S-1-5-18"]);
let RegKeyEvents =
    DeviceRegistryEvents
    | where DeviceId =~ VictimDeviceId
    | where ActionType == "RegistryValueSet"
    | where RegistryKey has "RunMRU"
    | where RegistryValueData has_any (Parameters) and RegistryValueData has_any (Executables)
    | extend LogType = "☢️ RunMRU Event"
    | project TimeGenerated, DeviceId, DeviceName, RegistryValueData, RegistryKey, LogType;
let RegKeyEventTimestamp = toscalar (RegKeyEvents | summarize Timestamp = max(TimeGenerated));
let NetworkEventsParser = materialize (DeviceNetworkEvents
    | where DeviceId =~ VictimDeviceId
    | where not(InitiatingProcessAccountSid in~ (FilteredSIDs))
    | where isnotempty(RemoteUrl)
    | extend MatchTimeStamp = RegKeyEventTimestamp
    | project TimeGenerated, RemoteIP, RemoteUrl, ReportId, DeviceId, DeviceName, MatchTimeStamp, InitiatingProcessCommandLine);
let PreInfectionNetworkEvents =
    NetworkEventsParser
    | where TimeGenerated between ((MatchTimeStamp - TimeFrame) .. MatchTimeStamp)
    | top TopXEvents by TimeGenerated desc
    | extend LogType = "🛜 Pre Infection Network Event";
let PostInfectionNetworkEvents =
    NetworkEventsParser
    | where TimeGenerated between (MatchTimeStamp .. (MatchTimeStamp + TimeFrame))
    | top TopXEvents by TimeGenerated asc
    | extend LogType = "🛜 Post Infection Network Event";
let PostInfectionProcessEvents = DeviceProcessEvents
    | where TimeGenerated between (RegKeyEventTimestamp .. (RegKeyEventTimestamp + TimeFrame))
    | top TopXEvents by TimeGenerated asc
    | where not(InitiatingProcessAccountSid in~ (FilteredSIDs))
    | extend LogType = "♻️ Post Infection Process Event"
    | project TimeGenerated, ReportId, LogType, DeviceId, DeviceName, ProcessCommandLine, InitiatingProcessCommandLine;
let PostInfectionFileEvents = DeviceFileEvents
    | where TimeGenerated between (RegKeyEventTimestamp .. (RegKeyEventTimestamp + TimeFrame))
    | top TopXEvents by TimeGenerated asc
    | where not(InitiatingProcessAccountSid in~ (FilteredSIDs))
    | extend LogType = "📁 Post Infection File Event"
    | project TimeGenerated, ReportId, LogType, DeviceId, DeviceName, ActionType, InitiatingProcessCommandLine, FolderPath;
union isfuzzy=false PreInfectionNetworkEvents,RegKeyEvents, PostInfectionNetworkEvents, PostInfectionProcessEvents, PostInfectionFileEvents
| sort by TimeGenerated asc
| project-reorder TimeGenerated, DeviceId, DeviceName, LogType, RemoteUrl, RegistryValueData, ProcessCommandLine, FolderPath, InitiatingProcessCommandLine
```

Explanation

This KQL query is designed to help investigate and triage incidents related to a specific device that triggered a ClickFix incident. Here's a simplified breakdown of what the query does:

  1. Input Variables: The query starts by defining three key inputs:

    • VictimDeviceId: The ID of the device involved in the incident.
    • TopXEvents: The number of events to collect before and after a suspicious activity.
    • TimeFrame: The time window around the suspicious activity to consider for event collection.
  2. Event Collection: The query gathers different types of events related to the incident:

    • Pre-Infection Network Events: It collects network events that happened before the suspicious activity, which might indicate how the device got compromised.
    • RunMRU Event: It identifies the specific registry changes related to the suspicious activity, particularly focusing on the "RunMRU" registry key, which logs commands executed via the Windows Run dialog.
    • Post-Infection Network Events: It collects network events that occurred after the suspicious activity to see what connections were made.
    • Post-Infection Process Events: It gathers information about processes that ran after the suspicious activity to identify any malicious processes.
    • Post-Infection File Events: It collects file-related events to see if any files were created or modified after the suspicious activity.
  3. Filtering and Sorting: The query filters out irrelevant events and sorts the collected data by time to provide a chronological view of the incident.

  4. Output: The final output is a unified list of events, sorted by time, that provides a comprehensive view of what happened before, during, and after the incident. This helps in understanding the incident's timeline and identifying potential threats or malicious activities.

Overall, this query is a forensic tool used to analyze and understand security incidents involving a specific device, helping security teams to quickly identify and respond to potential threats.

Details

Bert-Jan Pals profile picture

Bert-Jan Pals

Released: May 2, 2025

Tables

DeviceRegistryEventsDeviceNetworkEventsDeviceProcessEventsDeviceFileEvents

Keywords

DeviceNetworkRegistryProcessFileEventTimestampCommandLineActionTypeReportIdRemoteIPRemoteUrlDeviceIdDeviceNameRegistryKeyRegistryValueDataFolderPath

Operators

letdynamic=~==hashas_anyextendprojecttoscalarsummarizematerializein~isnotemptybetweentopunionisfuzzysort byproject-reorder

Actions