Detect Permission Groups Discovery in Elastic Security
Adversaries may attempt to discover group and permission settings to understand which user accounts and groups are available, group memberships, and which users and groups have elevated permissions. This information informs targeting decisions and enables privilege escalation, lateral movement, and persistence planning. Common enumeration methods include native Windows commands (net group, net localgroup), PowerShell cmdlets (Get-ADGroup, Get-LocalGroup), LDAP queries, BloodHound/SharpHound collection, Linux identity commands (id, groups, getent group), and cloud-provider APIs. Threat actors including APT41, TA505, Volt Typhoon, and Scattered Spider have used these techniques in real-world intrusions.
MITRE ATT&CK
- Tactic
- Discovery
- Technique
- T1069 Permission Groups Discovery
- Canonical reference
- https://attack.mitre.org/techniques/T1069/
Elastic Detection Query
process where event.type == "start" and (
(
process.name in~ ("net.exe", "net1.exe")
and process.args : ("group", "localgroup")
) or (
process.name in~ ("powershell.exe", "pwsh.exe")
and process.command_line : ("*Get-ADGroup*", "*Get-ADGroupMember*", "*Get-LocalGroup*", "*Get-LocalGroupMember*", "*Get-ADPrincipalGroupMembership*")
) or (
process.name in~ ("dsquery.exe", "dsget.exe")
and process.command_line : "*group*"
) or (
process.name : "whoami.exe"
and process.args : ("/groups", "/all", "/priv")
) or (
process.name : "gpresult.exe"
) or (
process.command_line : ("*SharpHound*", "*BloodHound*", "*-CollectionMethod*", "*--CollectionMethods*")
) or (
process.name in~ ("id", "groups", "getent")
and process.parent.name in ("bash", "sh", "zsh", "dash", "python", "python3", "perl", "ruby")
)
) Detects permission group discovery activity (MITRE T1069) by monitoring process execution for Windows group enumeration commands (net group, dsquery, whoami /groups), PowerShell AD/local group cmdlets, BloodHound/SharpHound collectors, and Linux identity commands (id, groups, getent group). Covers both domain and local group enumeration patterns used by APT41, TA505, Volt Typhoon, and Scattered Spider.
Data Sources
Required Tables
False Positives & Tuning
- IT administrators running routine AD health checks or group membership audits using Get-ADGroup or net group commands during normal operations
- Helpdesk staff using gpresult or whoami /groups to troubleshoot user permissions and Group Policy application issues
- Legitimate security tools and SIEM agents enumerating local groups during asset inventory or compliance scanning
- DevOps pipelines or configuration management tools (Ansible, Chef, Puppet) querying group membership to validate provisioning state
- BloodHound or SharpHound legitimately run by red team or internal penetration testing teams with prior authorization
Other platforms for T1069
Testing Methodology
Validate this detection against 5 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1 Local Group Enumeration via net.exe
Expected signal: Sysmon Event ID 1: Two Process Create events for net.exe (or net1.exe, which net.exe spawns internally). CommandLine values: 'net localgroup' and 'net localgroup Administrators'. Security Event ID 4688 if command line auditing is enabled. Parent process will be cmd.exe or the shell used to execute the commands.
- Test 2 Domain Group Enumeration via net.exe
Expected signal: Sysmon Event ID 1: Process Create for net.exe with CommandLine 'net group /domain' and 'net group "Domain Admins" /domain'. Network connection to domain controller on port 389 (LDAP) or 445 (SMB SAMR protocol). On the domain controller: Security Event ID 4661/4662 may fire for SAM group object access.
- Test 3 PowerShell Active Directory Group Enumeration
Expected signal: Sysmon Event ID 1: Process Create for powershell.exe with CommandLine containing 'Get-ADGroup' and 'Get-ADGroupMember'. PowerShell ScriptBlock Log Event ID 4104 capturing the full script content. LDAP network traffic to domain controller on port 389/636.
- Test 4 whoami Group Membership Query
Expected signal: Sysmon Event ID 1: Two Process Create events for whoami.exe. CommandLine values: 'whoami /groups' and 'whoami /all'. No network traffic (local token query). Output includes SID values, group names, and enabled privileges — this data is often captured via screen scraping in interactive sessions.
- Test 5 Linux Group Discovery via id and getent
Expected signal: Linux auditd: syscall execve events for /usr/bin/id, /usr/bin/groups, /usr/bin/getent with respective arguments. Syslog entries if exec auditing is enabled. On systems with osquery or EDR agents: process creation events for each command with full argument lists.
References (9)
- https://attack.mitre.org/techniques/T1069/
- https://attack.mitre.org/techniques/T1069/001/
- https://attack.mitre.org/techniques/T1069/002/
- https://attack.mitre.org/techniques/T1069/003/
- https://www.crowdstrike.com/blog/hidden-administrative-accounts-bloodhound-to-the-rescue/
- https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1069.001/T1069.001.md
- https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1069.002/T1069.002.md
- https://github.com/BloodHoundAD/BloodHound
- https://www.mandiant.com/resources/blog/apt41-initiates-global-intrusion-campaign-using-multiple-exploits
Response Playbook
Triage
- Identify the user account that triggered the alert — is it a standard user, privileged admin, service account, or machine account? Standard users running domain group enumeration is highly suspicious.
- Review the parent process — was net.exe or dsquery.exe launched by cmd.exe from a user session, or from an unexpected parent like powershell.exe, wscript.exe, mshta.exe, or a service (svchost.exe)? LOLBin parents indicate post-exploitation.
- Check whether this is isolated or part of a sequence — look ±5 minutes for other discovery commands (whoami, ipconfig, systeminfo, net user, net share, nltest /domain_trusts). A cluster of discovery commands within a short window is a strong indicator of active intrusion.
- For BloodHound/SharpHound detections: check the process hash against VirusTotal and internal allowlists. Confirm with the security team whether an authorized assessment is scheduled. BloodHound binaries from temp directories or user profiles are highly suspicious.
- For domain group queries (net group /domain, Get-ADGroup, dsquery group): check if the account normally authenticates to domain controllers. Look for abnormal logon times or source IPs in adjacent authentication logs.
- Check for lateral movement indicators in the same timeframe — new logon events (4624 Type 3 or Type 10) on other hosts from the same source user or machine within the hour before/after the group discovery.
Containment
- If BloodHound/SharpHound is confirmed malicious: immediately isolate the endpoint via EDR network isolation, disable the executing account in Active Directory, and rotate credentials for any accounts whose group memberships were harvested.
- If discovery commands were executed by a compromised service account: disable the service account, audit all hosts where that account has been used recently (Security Event ID 4624 filtering on that account name), and reset the password.
- If the discovery is part of an active intrusion sequence: escalate to IR and consider broader network segmentation. Group enumeration typically precedes targeted lateral movement to privileged hosts.
- Block the source host from communicating with domain controllers via firewall rule until investigation is complete, if isolation of the endpoint is not feasible.
- If cloud group enumeration is involved (AWS IAM, Azure AD, GCP IAM): revoke the API credentials or OAuth tokens used for enumeration and audit CloudTrail/Azure Activity logs for subsequent access attempts.
Evidence Collection
- Windows Security Event ID 4688 (Process Creation with command line logging enabled) — captures the full command line of net.exe, dsquery.exe, whoami.exe invocations.
- Sysmon Event ID 1 (Process Create) — provides parent/child process tree, hashes, and full command line regardless of Security audit policy.
- Active Directory event logs on domain controllers: Event ID 4661 (object handle requested) and Event ID 4662 (operation performed on object) for LDAP queries against group objects.
- Network traffic captures: BloodHound/SharpHound generates high-volume LDAP/LDAPS traffic to domain controllers on ports 389/636. Capture pcap during the incident window.
- PowerShell ScriptBlock Logging (Event ID 4104) — if AD cmdlets were used via PowerShell, this captures full script content including piped commands and output handling.
- Prefetch files for net.exe, whoami.exe, dsquery.exe — C:\Windows\Prefetch\*.pf provides execution timestamps and DLL load evidence.
- BloodHound output files — search for .json files matching BloodHound schema (computers.json, users.json, groups.json, acls.json, domains.json) in temp directories, user profiles, and removable media.
Escalation Criteria
- !BloodHound or SharpHound binary executed — this indicates systematic, automated AD enumeration consistent with pre-ransomware or APT tradecraft.
- !Group discovery commands executed under a service account or SYSTEM context with no associated change ticket or maintenance window.
- !Discovery activity followed within 15 minutes by net use, PsExec, WMI, or RDP connections to other hosts — indicates active lateral movement using group data.
- !Multiple hosts showing the same group discovery commands within a short window (possible worm propagation or scripted campaign).
- !Domain admin groups or tier-0 asset groups specifically enumerated (e.g., 'Domain Admins', 'Enterprise Admins', 'Schema Admins', 'Protected Users') — adversary is targeting the highest-privilege accounts.
- !Discovery commands originating from a host that has no legitimate administrative role (user workstation querying domain group membership via LDAP directly rather than via net.exe).
Investigation Guide
Related Techniques
Forensic Artifacts
- >
Registry: HKLM\SYSTEM\CurrentControlSet\Services\NetLogon\Parameters — domain membership details queried during group enumeration. - >
File System: BloodHound output files (*.json matching AD schema) in %TEMP%, %USERPROFILE%, or mapped drives — contain harvested group membership graphs. - >
File System: C:\Windows\Prefetch\NET.EXE-*.pf, WHOAMI.EXE-*.pf, DSQUERY.EXE-*.pf — execution timestamps and run counts. - >
File System: PowerShell history at %APPDATA%\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt — may contain Get-ADGroup or Get-LocalGroup commands run interactively. - >
Event Log: Microsoft-Windows-PowerShell/Operational Event ID 4104 — full script block content for PowerShell AD cmdlet usage. - >
Event Log: Security Event ID 4661/4662 on domain controllers — LDAP/SAM access to group objects, records SAM group enumeration by remote hosts. - >
Network: LDAP queries on port 389/636 to domain controllers from non-admin hosts — BloodHound generates hundreds of LDAP queries in short bursts (visible in DC network captures or firewall logs). - >
Memory: If SharpHound is injected rather than run as a standalone binary, process memory of the injected host may contain BloodHound collection data structures.
Tuning Guidance
Start by building a baseline of legitimate group discovery in your environment. Key allowlist candidates: (1) IT helpdesk accounts running net localgroup Administrators on support calls — allowlist specific account+host combinations, not the command pattern itself; (2) AD provisioning scripts running as service accounts — allowlist the specific service account name + initiating process (e.g., task scheduler or specific automation tool); (3) Security scanning tools — allowlist by parent process hash rather than command line. Avoid suppressing any BloodHound/SharpHound indicators regardless of context — always require a ticket. For domain group discovery specifically, consider raising severity when the initiating account is a non-admin user, when the parent process is an Office application or browser (indicating phishing-delivered access), or when the host has no legitimate AD administration role. In high-AD-activity environments, layer the detection by requiring the discovery commands to be followed within 10 minutes by a network logon (Event ID 4624 Type 3) to another host from the same account — this correlation dramatically improves precision.
Hunting Queries
Hunt for accounts or hosts executing three or more net group/localgroup commands within the past 7 days. High command counts from a single account or device indicate scripted enumeration rather than one-off administrative lookups — consistent with APT41 and TA505 tooling patterns.
DeviceProcessEvents
| where Timestamp > ago(7d)
| where (FileName =~ "net.exe" or FileName =~ "net1.exe")
and ProcessCommandLine has_any ("group", "localgroup")
| summarize
CommandCount = count(),
UniqueCommands = dcount(ProcessCommandLine),
Commands = make_set(ProcessCommandLine, 20),
FirstSeen = min(Timestamp),
LastSeen = max(Timestamp)
by AccountName, DeviceName, InitiatingProcessFileName
| where CommandCount >= 3
| sort by CommandCount desc index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
(Image="*\\net.exe" OR Image="*\\net1.exe")
(CommandLine="*group*" OR CommandLine="*localgroup*")
| stats
count as CommandCount,
dc(CommandLine) as UniqueCommands,
values(CommandLine) as Commands,
earliest(_time) as FirstSeen,
latest(_time) as LastSeen
by User, host, ParentImage
| where CommandCount >= 3
| sort - CommandCount Hunt for burst PowerShell AD group enumeration — more than 5 cmdlet executions per hour by a single account, or the same account enumerating groups across more than 2 hosts. This pattern distinguishes automated BloodHound-style collection from legitimate one-time admin queries and is consistent with pre-ransomware reconnaissance tradecraft.
DeviceProcessEvents
| where Timestamp > ago(7d)
| where FileName =~ "powershell.exe" or FileName =~ "pwsh.exe"
| where ProcessCommandLine has_any (
"Get-ADGroup", "Get-ADGroupMember", "Get-LocalGroup",
"Get-LocalGroupMember", "Get-ADPrincipalGroupMembership",
"net group", "net localgroup"
)
| summarize
Count = count(),
Devices = dcount(DeviceName),
Commands = make_set(ProcessCommandLine, 10)
by AccountName, bin(Timestamp, 1h)
| where Count > 5 or Devices > 2
| sort by Count desc index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
(Image="*\\powershell.exe" OR Image="*\\pwsh.exe")
(CommandLine="*Get-ADGroup*" OR CommandLine="*Get-ADGroupMember*" OR CommandLine="*Get-LocalGroup*" OR CommandLine="*Get-LocalGroupMember*")
| bin _time span=1h
| stats
count as Count,
dc(host) as Devices,
values(CommandLine) as Commands
by User, _time
| where Count > 5 OR Devices > 2
| sort - Count Hunt for discovery trifectas — accounts executing 5+ distinct discovery commands using 3+ different tools within a 30-minute window. This holistic view catches the broader reconnaissance phase where group discovery is part of a systematic environment survey, regardless of which individual commands appear in the main alert. Consistent with APT41 and Volt Typhoon living-off-the-land discovery phases.
let DiscoveryCommands = DeviceProcessEvents
| where Timestamp > ago(24h)
| where ProcessCommandLine has_any (
"net group", "net localgroup", "net user",
"whoami", "ipconfig", "systeminfo", "hostname",
"tasklist", "netstat", "arp ", "route print",
"dsquery", "nltest", "Get-ADGroup", "Get-ADUser"
)
| project Timestamp, DeviceName, AccountName, ProcessCommandLine, FileName;
DiscoveryCommands
| summarize
TotalCommands = count(),
UniqueTools = dcount(FileName),
CommandList = make_set(ProcessCommandLine, 20),
FirstSeen = min(Timestamp),
LastSeen = max(Timestamp),
SpanMinutes = datetime_diff('minute', max(Timestamp), min(Timestamp))
by AccountName, DeviceName
| where TotalCommands >= 5 and UniqueTools >= 3 and SpanMinutes <= 30
| sort by TotalCommands desc index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
(
(Image="*\\net.exe" AND (CommandLine="*group*" OR CommandLine="*user*" OR CommandLine="*share*"))
OR (Image="*\\whoami.exe")
OR (Image="*\\ipconfig.exe")
OR (Image="*\\systeminfo.exe")
OR (Image="*\\hostname.exe")
OR (Image="*\\tasklist.exe")
OR (Image="*\\netstat.exe")
OR (Image="*\\dsquery.exe")
OR (Image="*\\nltest.exe")
)
| bin _time span=30m
| stats
count as TotalCommands,
dc(Image) as UniqueTools,
values(CommandLine) as CommandList
by User, host, _time
| where TotalCommands >= 5 AND UniqueTools >= 3
| sort - TotalCommands Atomic Red Team Tests
Enumerates local groups on the current system using the built-in net.exe utility, then queries membership of the local Administrators group. This is one of the most common first-stage discovery commands observed in post-exploitation frameworks and manual attacker activity. The double-invocation (list all groups, then query a specific high-value group) mirrors real adversary behavior.
Command
net localgroup
net localgroup Administrators Expected Telemetry
Sysmon Event ID 1: Two Process Create events for net.exe (or net1.exe, which net.exe spawns internally). CommandLine values: 'net localgroup' and 'net localgroup Administrators'. Security Event ID 4688 if command line auditing is enabled. Parent process will be cmd.exe or the shell used to execute the commands.
Expected Detection
KQL: FileName matches net.exe/net1.exe AND ProcessCommandLine has 'localgroup'. IsLocalGroupQuery=true. SPL: match on net.exe with 'localgroup' in CommandLine. Both queries will generate two separate events.
Enumerates domain groups and specifically queries the membership of the Domain Admins group using net.exe with the /domain flag. This technique is used by APT41, TA505, and Volt Typhoon operators to identify privileged accounts for targeting. Requires domain-joined machine and network connectivity to a domain controller.
Command
net group /domain
net group "Domain Admins" /domain Expected Telemetry
Sysmon Event ID 1: Process Create for net.exe with CommandLine 'net group /domain' and 'net group "Domain Admins" /domain'. Network connection to domain controller on port 389 (LDAP) or 445 (SMB SAMR protocol). On the domain controller: Security Event ID 4661/4662 may fire for SAM group object access.
Expected Detection
KQL: IsDomainGroupQuery=true, ProcessCommandLine has '/domain'. SPL: CommandLine matches 'group' and '/domain'. Both are elevated-priority events due to domain targeting.
Uses the ActiveDirectory PowerShell module to enumerate all AD groups and retrieve membership of the Domain Admins group. This is a more capable and scriptable alternative to net.exe used by sophisticated actors and BloodHound-equivalent tools. Requires the RSAT ActiveDirectory module (available on domain-joined Windows 10/11 and Server).
Command
powershell.exe -NoProfile -Command "Import-Module ActiveDirectory; Get-ADGroup -Filter * | Select-Object Name, GroupScope, GroupCategory | Format-Table; Get-ADGroupMember -Identity 'Domain Admins' | Select-Object Name, SamAccountName, objectClass" Expected Telemetry
Sysmon Event ID 1: Process Create for powershell.exe with CommandLine containing 'Get-ADGroup' and 'Get-ADGroupMember'. PowerShell ScriptBlock Log Event ID 4104 capturing the full script content. LDAP network traffic to domain controller on port 389/636.
Expected Detection
KQL: FileName matches powershell.exe AND ProcessCommandLine has 'Get-ADGroup' AND 'Get-ADGroupMember'. IsDomainGroupQuery=true. SPL: match on powershell.exe with Get-ADGroup and Get-ADGroupMember in CommandLine.
Uses the built-in whoami.exe utility with the /groups and /all flags to display all group memberships and privileges for the current user token. This is commonly executed as an immediate post-exploitation step to understand what access level has been obtained. The /all flag additionally reveals privileges (SeDebugPrivilege, SeImpersonatePrivilege, etc.) that inform further exploitation steps.
Command
whoami /groups
whoami /all Expected Telemetry
Sysmon Event ID 1: Two Process Create events for whoami.exe. CommandLine values: 'whoami /groups' and 'whoami /all'. No network traffic (local token query). Output includes SID values, group names, and enabled privileges — this data is often captured via screen scraping in interactive sessions.
Expected Detection
KQL: FileName matches whoami.exe AND ProcessCommandLine has_any('/groups', '/all'). IsLocalGroupQuery=true. SPL: Image matches whoami.exe and CommandLine matches /groups or /all.
Enumerates group memberships on a Linux system using the id, groups, and getent commands. The id command shows current user's primary and supplementary groups; getent group dumps the entire /etc/group database including service accounts and system groups. Used by threat actors including Volt Typhoon during Linux-based infrastructure compromises.
Command
id
groups
getent group
getent group sudo
cat /etc/group | grep -v '^#' Expected Telemetry
Linux auditd: syscall execve events for /usr/bin/id, /usr/bin/groups, /usr/bin/getent with respective arguments. Syslog entries if exec auditing is enabled. On systems with osquery or EDR agents: process creation events for each command with full argument lists.
Expected Detection
Linux-focused detections using auditd or syslog sourcetypes. KQL (if Linux hosts forward to Sentinel via MMA/AMA): Syslog table entries matching 'getent group' or 'id ' commands. SPL: sourcetype=linux_secure or syslog filtering on these command names with group-related arguments.