Command and Control (TA0011)(external, opens in a new tab or window)
text code block:FROM logs-endpoint.events.network-*, logs-windows.sysmon_operational-* METADATA _index | WHERE host.os.type == "windows" AND event.category == "network" AND event.action in ("lookup_requested", "DNSEvent (DNS query)") AND dns.question.name IS NOT NULL // Exclude browser processes | WHERE NOT process.name IN ( "chrome.exe", "msedge.exe", "MicrosoftEdge.exe", "MicrosoftEdgeCP.exe", "firefox.exe", "iexplore.exe", "safari.exe", "brave.exe", "opera.exe", "vivaldi.exe", "msedgewebview2.exe" ) // Extract the parent domain (last two labels, e.g. example.com) | GROK dns.question.name """(?:[^.]+\.)+(?<parent_domain>[^.]+\.[^.]+)$""" | EVAL parent_domain = COALESCE(parent_domain, dns.question.name) // Known RMM parent domains, add or remove entries here as your environment changes. | WHERE parent_domain IN ( "teamviewer.com", "logmein.com", "logmeinrescue.com", "logmeininc.com", "internapcdn.net", "anydesk.com", "screenconnect.com", "connectwise.com", "splashtop.com", "zohoassist.com", "dwservice.net", "gotoassist.com", "getgo.com", "logmeinrescue.com", "rustdesk.com", "remoteutilities.com", "atera.com", "ammyy.com", "n-able.com", "kaseya.net", "bomgar.com", "beyondtrustcloud.com", "parsec.app", "parsecusercontent.com", "tailscale.com", "twingate.com", "jumpcloud.com", "vnc.com", "remotepc.com", "netsupportsoftware.com", "getscreen.me", "beanywhere.com", "swi-rc.com", "swi-tc.com", "qetqo.com", "tmate.io", "playanext.com", "supremocontrol.com", "itarian.com", "datto.com", "auvik.com", "syncromsp.com", "pulseway.com", "immy.bot", "immybot.com", "level.io", "ninjarmm.com", "ninjaone.com", "centrastage.net", "datto.net", "liongard.com", "naverisk.com", "panorama9.com", "superops.ai", "superops.com", "tacticalrmm.com", "meshcentral.com", "remotly.com", "fixme.it", "islonline.com", "zoho.eu", "goverlan.com", "iperius.net", "iperiusremote.com", "remotix.com", "mikogo.com", "r-hud.net", "pcvisit.de", "netviewer.com", "helpwire.app", "remotetopc.com", "rport.io", "action1.com", "tiflux.com", "gotoresolve.com" ) // Aggregate by parent domain and get 1st time seen timestamp as well as unique count of agents | STATS event_count = COUNT(*), Esql.first_time_seen = MIN(@timestamp), Esql.count_distinct_host_id = COUNT_DISTINCT(host.id), Esql.process_executable_values = VALUES(process.executable), Esql.dns_question_name_values = VALUES(dns.question.name), Esql.host_name_values = VALUES(host.name) BY parent_domain // Calculate the time difference between first time seen and rule execution time | eval Esql.recent = DATE_DIFF("minute", Esql.first_time_seen, now()) // First time seen is within 6m of the rule execution time and first seen in the last 5 days as per the rule from schedule and limited to 1 unique host | where Esql.recent <= 6 and Esql.count_distinct_host_id == 1 // populate fields for rule exception | eval host.name = MV_FIRST(Esql.host_name_values), process.executable = MV_FIRST(Esql.process_executable_values), dns.question.name = MV_FIRST(Esql.dns_question_name_values) | keep host.name, process.executable, dns.question.name, Esql.*
Install detection rules in Elastic Security
Detect First Time Seen DNS Query to RMM Domain in the Elastic Security detection engine by installing this rule into your Elastic Stack.
To setup this rule, check out the installation guide for Prebuilt Security Detection Rules(external, opens in a new tab or window).