Query Details
# *Advanced Multi-Stage Linux Enumeration & Post-Exploitation Detector*
## Query Information
#### MITRE ATT&CK Technique(s)
| Technique ID | Title | Link |
| --- | --- | --- |
| T1522 | Unsecured Credentials | https://attack.mitre.org/techniques/T1522 |
| T1548 | Abuse Elevation Control | https://attack.mitre.org/techniques/T1548 |
| T1016 | Network Config Discovery | https://attack.mitre.org/techniques/T1548 |
| T1613 | Cloud/Container Discovery | https://attack.mitre.org/techniques/T1548 |
| T1082 | System Info Discovery | https://attack.mitre.org/techniques/T1548 |
#### Description
This query identifies potential post-exploitation behavior on Linux systems by monitoring for clusters of discovery and enumeration commands. Instead of alerting on single, potentially benign commands, it utilizes a behavioral scoring engine that categorizes activities such as credential hunting, privilege escalation, and network scanning.
By implementing extensive allowlists for common administrative tools (e.g., Ansible, Zabbix, Monitoring Agents) and requiring a minimum threshold of unique activity categories, the query effectively filters out "noise." It calculates a dynamic Risk Score and assigns a Severity level based on the criticality of the commands and the speed of execution (Burst Detection), making it a highly reliable tool for SOC analysts to detect active hands-on-keyboard attacks.
#### Author <Optional>
- **Name: Benjamin Zulliger**
- **Github: https://github.com/benscha/KQLAdvancedHunting**
- **LinkedIn: https://www.linkedin.com/in/benjamin-zulliger/**
#### References
-
## Defender XDR
```KQL
// ============================================================================
// Linux Discovery & Enumeration Detection
// Detect post-exploitation discovery with minimal false positives
// ============================================================================
let timeframe = 4h;
let threshold = 6; // Change this threshold value for your needs
// --- ALLOWLISTS (adjust to your environment!) ---
// Known service accounts that routinely perform discovery commands
let excludedAccounts = dynamic([
"zabbix", "nagios", "icinga", "datadog", "telegraf", "prometheus",
"collectd", "splunk", "omsagent", "waagent", "nessus", "qualys",
"rapid7", "ansible", "puppet", "chef", "salt", "cfagent",
"pcp", "sysstat", "munin", "cacti", "xymon"
]);
// Automation and monitoring parent processes
let excludedParentImages = dynamic([
"ansible", "ansible-playbook", "puppet", "chef-client", "salt-minion",
"salt-call", "cfagent", "zabbix_agentd", "nagios", "nrpe",
"collectd", "telegraf", "datadog-agent", "omsagent",
"omi", "auoms", "qualys-cloud-agent", "nessus",
"cron", "crond", "anacron", "atd"
]);
// --- PATTERN DEFINITIONS (specific patterns only, no short generic ones) ---
let suspiciousPatterns = dynamic([
// User & Identity Discovery (specific, no short forms like "id " or "w ")
"whoami", "getent passwd", "cat /etc/passwd", "cat /etc/shadow",
"cat /etc/group", "lastlog",
// System Info Discovery
"uname -a", "cat /etc/os-release", "hostnamectl", "lsb_release",
"dmidecode", "cat /proc/version", "cat /proc/cpuinfo",
// Privilege Escalation Enumeration (highly suspicious)
"sudo -l", "find / -perm", "find / -suid", "find / -sgid",
"find / -writable", "getcap -r",
// Persistence Enumeration
"crontab -l", "cat /etc/crontab", "ls /etc/cron",
"systemctl list-unit-files", "service --status-all",
"ls /etc/init.d", "cat /etc/rc.local",
// Process & Service Discovery (specific)
"ps aux", "ps -ef", "pstree", "lsof -i",
// Network Discovery
"netstat -", "ss -tulpn", "ss -antp", "arp -a", "ip addr", "ip route",
"ifconfig", "route -n", "cat /etc/hosts", "cat /etc/resolv.conf",
"nmap ", "masscan ",
// Credential Hunting (highly suspicious)
"id_rsa", "id_dsa", "id_ecdsa", "id_ed25519",
"cat /etc/ssh", ".ssh/config", ".ssh/authorized_keys",
"find / -name *.pem", "find / -name *.key",
"find / -name *.pfx", "find / -name *.p12",
".bash_history", ".mysql_history", ".psql_history",
// Environment Discovery (specific)
"printenv", "cat /etc/environment", "cat /proc/net",
// Filesystem / Config Hunting
"cat /etc/fstab",
"find / -name wp-config", "find / -name config.php",
"find / -name .env", "find / -name database.yml",
"find / -name web.config",
// Software / Package Discovery
"dpkg -l", "rpm -qa", "apt list --installed", "pip list", "pip3 list",
// Container / Cloud Discovery (highly suspicious)
"cat /proc/1/cgroup", "ls /.dockerenv",
"curl 169.254.169.254", "wget 169.254.169.254",
"curl metadata.google", "wget metadata.google",
// LOTL Tool Detection
"which gcc", "which python", "which perl", "which ruby",
"which nc", "which ncat", "which socat",
"which wget", "which curl", "which nmap"
]);
// --- MAIN QUERY ---
DeviceProcessEvents
| where TimeGenerated > ago(timeframe)
| where ProcessCommandLine has_any (suspiciousPatterns)
// ---- FP FILTER 1: Exclude known service accounts ----
| where AccountName !in (excludedAccounts)
// ---- FP FILTER 2: Exclude known automation parent processes ----
| where InitiatingProcessFileName !in (excludedParentImages)
// ---- FP FILTER 3: Exclude known automation command lines ----
| where InitiatingProcessCommandLine !has "ansible"
and InitiatingProcessCommandLine !has "puppet"
and InitiatingProcessCommandLine !has "chef"
and InitiatingProcessCommandLine !has "salt-call"
and InitiatingProcessCommandLine !has "cfengine"
// ---- Categorization with risk weighting ----
| extend NormalizedCommand = case(
// --- High Risk Categories (Weight 3) ---
ProcessCommandLine has "sudo -l" or ProcessCommandLine has "find / -perm"
or ProcessCommandLine has "find / -suid" or ProcessCommandLine has "find / -sgid"
or ProcessCommandLine has "find / -writable" or ProcessCommandLine has "getcap -r",
"Privilege_Escalation_Enum",
ProcessCommandLine has "id_rsa" or ProcessCommandLine has "id_dsa"
or ProcessCommandLine has "id_ecdsa" or ProcessCommandLine has "id_ed25519"
or ProcessCommandLine has "find / -name *.pem" or ProcessCommandLine has "find / -name *.key"
or ProcessCommandLine has "find / -name *.pfx" or ProcessCommandLine has ".ssh/config"
or ProcessCommandLine has ".ssh/authorized_keys"
or ProcessCommandLine has "cat /etc/shadow",
"Credential_Hunting",
ProcessCommandLine has "cat /proc/1/cgroup" or ProcessCommandLine has "ls /.dockerenv"
or ProcessCommandLine has "169.254.169.254" or ProcessCommandLine has "metadata.google",
"Cloud_Container_Discovery",
// --- Medium Risk Categories (Weight 2) ---
ProcessCommandLine has "nmap " or ProcessCommandLine has "masscan ",
"Active_Network_Scanning",
ProcessCommandLine has "crontab -l" or ProcessCommandLine has "cat /etc/crontab"
or ProcessCommandLine has "ls /etc/cron"
or ProcessCommandLine has "systemctl list-unit-files" or ProcessCommandLine has "service --status-all"
or ProcessCommandLine has "ls /etc/init.d" or ProcessCommandLine has "cat /etc/rc.local",
"Persistence_Enum",
ProcessCommandLine has "find / -name wp-config" or ProcessCommandLine has "find / -name config.php"
or ProcessCommandLine has "find / -name .env" or ProcessCommandLine has "find / -name database.yml"
or ProcessCommandLine has "find / -name web.config",
"Config_File_Hunting",
ProcessCommandLine has ".bash_history" or ProcessCommandLine has ".mysql_history"
or ProcessCommandLine has ".psql_history",
"History_Exfil",
ProcessCommandLine has "which gcc" or ProcessCommandLine has "which python"
or ProcessCommandLine has "which perl" or ProcessCommandLine has "which nc"
or ProcessCommandLine has "which ncat" or ProcessCommandLine has "which socat"
or ProcessCommandLine has "which wget" or ProcessCommandLine has "which curl"
or ProcessCommandLine has "which nmap",
"LOTL_Tool_Discovery",
// --- Low Risk Categories (Weight 1) ---
ProcessCommandLine has "whoami" or ProcessCommandLine has "getent passwd"
or ProcessCommandLine has "cat /etc/passwd" or ProcessCommandLine has "cat /etc/group"
or ProcessCommandLine has "lastlog",
"User_Discovery",
ProcessCommandLine has "uname" or ProcessCommandLine has "cat /etc/os-release"
or ProcessCommandLine has "hostnamectl" or ProcessCommandLine has "lsb_release"
or ProcessCommandLine has "dmidecode" or ProcessCommandLine has "cat /proc/version",
"System_Info_Discovery",
ProcessCommandLine has "ps aux" or ProcessCommandLine has "ps -ef"
or ProcessCommandLine has "pstree" or ProcessCommandLine has "lsof -i",
"Process_Discovery",
ProcessCommandLine has "netstat" or ProcessCommandLine has "ss -tulpn" or ProcessCommandLine has "ss -antp"
or ProcessCommandLine has "arp -a" or ProcessCommandLine has "ip addr"
or ProcessCommandLine has "ip route" or ProcessCommandLine has "ifconfig"
or ProcessCommandLine has "cat /etc/hosts" or ProcessCommandLine has "cat /etc/resolv.conf",
"Network_Discovery",
ProcessCommandLine has "printenv" or ProcessCommandLine has "cat /etc/environment"
or ProcessCommandLine has "cat /proc/net",
"Environment_Discovery",
ProcessCommandLine has "dpkg -l" or ProcessCommandLine has "rpm -qa"
or ProcessCommandLine has "apt list --installed" or ProcessCommandLine has "pip list",
"Software_Discovery",
"other"
)
| where NormalizedCommand != "other"
// --- Aggregation per device/user/time window ---
| summarize
UniqueCategoryCount = dcount(NormalizedCommand),
DetectedCategories = make_set(NormalizedCommand),
DetailedCommands = make_set(ProcessCommandLine, 25),
CommandCount = count(),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated),
ReportId = take_any(ReportId)
by DeviceId, DeviceName, AccountName, bin(TimeGenerated, timeframe)
| where UniqueCategoryCount >= threshold
// --- Risk Scoring: High-risk categories carry more weight ---
| extend RiskScore =
iif(set_has_element(DetectedCategories, "Credential_Hunting"), 3, 0)
+ iif(set_has_element(DetectedCategories, "Privilege_Escalation_Enum"), 3, 0)
+ iif(set_has_element(DetectedCategories, "Cloud_Container_Discovery"), 3, 0)
+ iif(set_has_element(DetectedCategories, "Active_Network_Scanning"), 2, 0)
+ iif(set_has_element(DetectedCategories, "Persistence_Enum"), 2, 0)
+ iif(set_has_element(DetectedCategories, "Config_File_Hunting"), 2, 0)
+ iif(set_has_element(DetectedCategories, "History_Exfil"), 2, 0)
+ iif(set_has_element(DetectedCategories, "LOTL_Tool_Discovery"), 2, 0)
+ iif(set_has_element(DetectedCategories, "User_Discovery"), 1, 0)
+ iif(set_has_element(DetectedCategories, "System_Info_Discovery"), 1, 0)
+ iif(set_has_element(DetectedCategories, "Process_Discovery"), 1, 0)
+ iif(set_has_element(DetectedCategories, "Network_Discovery"), 1, 0)
+ iif(set_has_element(DetectedCategories, "Environment_Discovery"), 1, 0)
+ iif(set_has_element(DetectedCategories, "Software_Discovery"), 1, 0)
// --- Burst Detection: Timespan of activity ---
| extend ActivityDurationMinutes = datetime_diff('minute', LastSeen, FirstSeen)
// --- Severity Classification ---
| extend Severity = case(
RiskScore >= 12 and ActivityDurationMinutes <= 30, "Critical",
RiskScore >= 8, "High",
RiskScore >= 5 and UniqueCategoryCount >= 7, "Medium",
"Low"
)
// --- Only output relevant alerts ---
| where Severity in ("Critical", "High", "Medium")
// --- Final Projection ---
| project
Timestamp=TimeGenerated,
DeviceId,
DeviceName,
AccountName,
Severity,
RiskScore,
UniqueCategoryCount,
CommandCount,
ActivityDurationMinutes,
DetectedCategories,
DetailedCommands,
ReportId
| order by RiskScore desc, UniqueCategoryCount desc
```
This query is designed to detect suspicious post-exploitation activities on Linux systems by analyzing clusters of commands that are typically used for system discovery and enumeration. Here's a simplified breakdown of what the query does:
Timeframe and Threshold: It looks at command activities within a 4-hour window and requires at least 6 unique suspicious activities to trigger an alert.
Allowlists: It excludes known service accounts and processes that are commonly used for legitimate administrative tasks, such as monitoring tools and automation scripts, to reduce false positives.
Suspicious Patterns: The query identifies specific command patterns that are indicative of malicious activities, such as credential hunting, privilege escalation, network scanning, and system information discovery.
Risk Scoring: Each detected activity is categorized and assigned a risk score based on its potential threat level. High-risk activities like credential hunting and privilege escalation are weighted more heavily.
Burst Detection: It evaluates the speed of command execution to identify rapid bursts of activity, which can indicate an active attack.
Severity Classification: Based on the risk score and the number of unique activities, the query assigns a severity level (Critical, High, Medium, or Low) to each detected incident.
Output: Only incidents with a severity of Medium or higher are reported, providing details such as the device, account involved, risk score, and the specific commands executed.
Overall, this query helps security operations center (SOC) analysts detect and prioritize potential security incidents by focusing on behavioral patterns rather than isolated commands, making it a more reliable tool for identifying active threats on Linux systems.

Benjamin Zulliger
Released: March 9, 2026
Tables
Keywords
Operators