🏢Active DirectoryNetworkGPOAttack PathsMonitoring

NetSessionEnum, Remote SAM Hardening, BloodHound Reconnaissance, Active Directory: Blinding the Attack Graph

Remote SAM stays open to Everyone on every domain controller, and stale SrvsvcSessionInfo ACLs survive in-place upgrades — the defaults behind BloodHound's HasSession and AdminTo edges.

Younes AZABARBy Younes AZABAR13 min read
NetSessionEnum, Remote SAM Hardening, BloodHound Reconnaissance, Active Directory: Blinding the Attack Graph

What Is NetSessionEnum, Remote SAM Hardening, BloodHound Reconnaissance, Active Directory Attack-Graph Exposure?

NetSessionEnum, remote SAM hardening, BloodHound reconnaissance, Active Directory attack graphs: these four topics all reduce to the same three settings, and none of them carries a CVE number — which is exactly why almost nobody hardens them.

BloodHound's two most valuable edge types, HasSession and AdminTo, are not built from an exploit. They come from two ordinary Windows RPC calls: NetSessionEnum (who is currently logged on here?) and a SAMR query against the local SAM database (who is a local administrator here?). Whether a low-privileged domain account may make them is decided entirely by two defaults that changed at different times — and that still leave a large opening today. NetSessionEnum was open to Authenticated Users up to Windows 10 1703 and Windows Server 2016, and remote SAM was unrestricted before Windows 10 1607 and Windows Server 2016; on current builds both are restricted on member servers and workstations, but remote SAM is still open to Everyone on every domain controller, by documented design. An attacker with one low-privileged foothold walks the estate asking both questions wherever they are still answered, and SharpHound turns the answers into a graph that points straight at Domain Admin.

The three settings below are the levers that remove those two questions from the graph: the SrvsvcSessionInfo security descriptor that gates NetSessionEnum, the RestrictRemoteSam policy that gates the SAM/SAMR query, and whether SMBv1 — the protocol whose era predates both hardening defaults — is still installed anywhere in the estate.

How It Works

Session and local-admin enumeration are two of several machine-identity weaknesses that feed BloodHound's attack graph — see also the broader computer objects attack surface in Active Directory for the delegation and DCSync side of the same problem.

NetSessionEnum and the HasSession edge

NetSessionEnum is a legacy Server service API (\\host\srvsvc over the IPC$ administrative share) that lists the network sessions currently connected to a machine — effectively "which accounts are logged on or have a mapped drive to me right now." SharpHound calls it during the default Session collection method, resolves the returned IPs/hostnames back to computer objects, and draws a HasSession edge from that computer to every account it finds. A HasSession edge is a promise of opportunity, not a guarantee: if the attacker can reach that computer with admin rights (or another path to it), a real, currently-connected user's credentials or token may be sitting in memory to steal.

Who is allowed to call NetSessionEnum is controlled by a security descriptor stored in the registry value SrvsvcSessionInfo, under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\DefaultSecurity. Compass Security tested this specific ACL build by build and published the matrix: Windows 10 1607 (14393) and 1703 (15063) and Windows Server 2016 (14393) grant Authenticated Users the right to call it, while Windows 10 1709 (16299) and later, Windows Server 2019 (17763) and Windows Server 2022 (20348) do not. On those newer builds the descriptor grants Administrators, Server Operators and Power Users remotely, plus the Interactive, Service and Batch logon sessions locally — which is, almost exactly, the ACL the NetCease hardening script was written to apply. Compass also notes that cumulative updates did not change the behaviour within a given release, and that there is no clear public Microsoft documentation of the change, so the only way to know which behaviour a given host has is to read the value, not infer it from the OS version on the asset list.

Remote SAM access and the AdminTo edge

SharpHound's LocalAdmin collection method (also used by the RDP, DCOM, and PSRemote methods) enumerates a computer's local groups over the SAMR named pipe (\\host\samr, also over IPC$) to find who is a member of local Administrators — the source of the AdminTo edge. The SAMRPC protocol lets a low-privileged caller enumerate users, groups, and group membership from the local SAM and from Active Directory, which is exactly the reconnaissance step attackers used long before BloodHound existed to find where a privileged account has standing local-admin rights.

This is gated by the Network access: Restrict clients allowed to make remote calls to SAM policy (registry value RestrictRemoteSam, HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\RestrictRemoteSam, REG_SZ). Microsoft's own documentation is explicit about the default here, and the default is uneven by design:

RoleDefault SDDLEffective behavior
Non-domain-controller (Windows 10 1607+ / Server 2016+)O:SYG:SYD:(A;;RC;;;BA)Only the local Administrators group can remotely query SAM
Windows Server 2016 (or later) domain controller (reading Active Directory)"" (blank)Everyone has read access, to preserve legacy application compatibility
Any earlier OS versionNo access check performedFully open by default

That middle row is the nuance that matters: the "secure by default since 2016" story only applies to member servers and workstations. Domain controllers — the machines whose local-admin data an attacker most wants — ship with SAMR reads open to Everyone, on every supported Windows Server version, for compatibility reasons Microsoft states explicitly rather than as an oversight.

Where SMBv1 fits

SMBv1 is not the transport that carries NetSessionEnum or SAMR calls — those RPCs ride over named pipes on IPC$ regardless of SMB dialect. What SMBv1 tells you is history. Microsoft has not installed SMBv1 by default since Windows 10 and Windows Server, version 1709, and Windows Server 2019 and later ship without it after a clean installation. A host still answering SMBv1 therefore falls into one of three buckets, and the third is the one most estates forget: it predates the cutoff, someone reinstalled it deliberately, or it was upgraded in place. Microsoft is explicit that in-place upgrades do not automatically remove SMBv1, and that on Windows 10 Enterprise, Education and Pro for Workstations "an administrator must decide to uninstall SMBv1 in these managed environments" — no 15-day auto-removal applies there. So SMBv1 does not prove the host is old; it proves the host was never re-baselined. That is the same condition under which a pre-1709 SrvsvcSessionInfo descriptor survives, which is what makes it a useful inventory shortcut — "go read this host's session and SAM ACLs by hand" — rather than a separate attack primitive.

This session/local-admin reconnaissance surface sits next to other recon paths already covered on this blog: SMB signing left disabled, which enables NTLM relay, NTLM relay attack chains against Active Directory more broadly, and anonymous LDAP access via a permissive dsHeuristics value, which covers directory-side enumeration. This article does not restate any of that — it is specifically the session-enumeration and local-admin-enumeration surface that feeds HasSession and AdminTo.

The Attack Chain

Step 1 — Any domain foothold

The attacker needs nothing more than one valid domain credential (or an unattended session token) — no exploit, and no local admin rights on the domain controllers they are about to enumerate.

Step 2 — Default SharpHound collection

# -c All runs every collection method, Session and LocalAdmin included
.\SharpHound.exe -c All -d corp.local

For every live host, SharpHound calls NetSessionEnum over \\host\srvsvc for sessions and a SAMR local-group query over \\host\samr for local admins. The two calls do not fail or succeed together. The SAMR query succeeds against every domain controller regardless of Windows version, because of the blank default above; the session call succeeds on any host whose SrvsvcSessionInfo descriptor is still the pre-1709 one, or was loosened afterwards. A single low-privileged account is enough for both.

Step 3 — BloodHound builds the path

BloodHound Community Edition correlates the returned HasSession and AdminTo edges with existing group membership to compute a shortest path such as: compromised low-privileged account → has a session on Host-X → a Domain Admin account is also logged onto Host-X → attacker takes over Host-X → dumps LSASS or steals the Domain Admin's token.

Step 4 — Credential theft on the target host

If the attacker also has (or can obtain) local admin on the session-bearing host — frequently true, since AdminTo enumeration from the same low-privileged sweep already reveals which hosts have permissive local-admin membership — the session becomes a credential-theft opportunity via LSASS access or token impersonation.

Detection

Neither NetSessionEnum nor a SAMR read produces a dedicated "someone enumerated me" Windows event by default, and both rely on the same advanced audit policy configuration most domains leave at its incomplete out-of-the-box state. The following events give the closest coverage:

Event IDSourceWhat it showsRequires
16965Directory-Service-SAM (System log)A remote call to SAM was denied — includes the caller's SID and network addressNothing: it also fires under the hard-coded default descriptor, with no registry value set
16968Directory-Service-SAM (System log)Audit-only mode: shows what would have been denied, without breaking anythingRestrictRemoteSamAuditOnlyMode = 1
5145Microsoft-Windows-Security-Auditing (Detailed File Share)Access check against an IPC$ named pipe — Share Name = \\*\IPC$, Relative Target Name = srvsvc, samr, or lsarpc"Audit Detailed File Share" advanced audit subcategory enabled

Do not build volume-based detection on 16965 alone. Microsoft throttles it: by default the event is written only the first time access is denied after boot, and every later denial inside a 15-minute window is merely counted and reported in bulk by event 16969 ("N remote calls to the SAM database have been denied in the past X-seconds throttling window"). The window is set by RestrictRemoteSamEventThrottlingWindow (REG_DWORD, seconds, under HKLM\System\CurrentControlSet\Control\Lsa); set it to 0 to disable throttling and log every denial. Audit-only mode is not throttled, which is another reason to run it first.

A practical hunt: filter Event ID 5145 for Share Name = \\*\IPC$ and Relative Target Name in srvsvc, samr, lsarpc, then flag any non-domain-controller source account that touches more than a handful of distinct destination hosts in a short window — a single workstation account calling srvsvc/samr against dozens of hosts in minutes is SharpHound's default collection behavior, not normal user activity. Event 5145 comes from the Audit Detailed File Share subcategory, which is off by default and high-volume, so scope it deliberately.

Remediation

  1. Inventory before you restrict. Turn on RestrictRemoteSamAuditOnlyMode (REG_DWORD, value 1, under HKLM\SYSTEM\CurrentControlSet\Control\Lsa) and review event 16968 for a few days to identify legitimate remote-SAM callers before configuring the policy live.
  2. Explicitly configure RestrictRemoteSam on domain controllers. The default there is "Everyone" for compatibility — it does not become secure just because the box is running the latest Windows Server. Define an SDDL that allows only the accounts and groups that actually need remote SAM reads (SAMRi10, from the same Microsoft researchers as NetCease, creates a dedicated "Remote SAM Users" group and writes the SDDL for you instead of hand-editing the string). Restarts are not required: Microsoft states the setting takes effect when it is saved locally or applied by Group Policy.
  3. Harden NetSessionEnum with a SrvsvcSessionInfo ACL change — on the builds that still need it. The NetCease script removes Authenticated Users from the SrvsvcSessionInfo security descriptor and adds the Interactive, Service and Batch logon SIDs, leaving Administrators, Power Users and Server Operators in place. Its own documentation is explicit that you "need to restart the 'Server' service for changes to take effect" (Restart-Service -Name LanmanServer -Force). Note what this means on a modern estate: Windows 10 1709+ and Windows Server 2019+ already ship that ACL, so NetCease is close to a no-op there — its value is on the pre-1709 and Server 2016 hosts, and on any host whose descriptor was loosened after the fact. Test in an audit/staging group first — the same admin tools that break under RestrictRemoteSam can break here too.
  4. Do not assume the OS version tells you the current state. Query SrvsvcSessionInfo and RestrictRemoteSam directly instead of trusting "we're on Server 2019/2022 so we're fine":
    Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name RestrictRemoteSam -ErrorAction SilentlyContinue
    
  5. Confirm SMBv1 is actually gone, not just assumed gone.
    # Requires elevation; disabling triggers a restart unless -NoRestart is used
    Get-WindowsOptionalFeature -Online -FeatureName SMB1Protocol
    # If State is Enabled:
    Disable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol -NoRestart
    
    # Microsoft's non-elevated alternative, better suited to sweeping an estate:
    Get-SmbServerConfiguration | Format-List EnableSMB1Protocol
    
    Treat any host that still answers SMBv1 as a flag to manually verify its SrvsvcSessionInfo and RestrictRemoteSam state — not because SMBv1 proves the host is old, but because it proves the host was never re-baselined, which is the same condition that preserves a stale session or SAM descriptor. This complements the broader Active Directory hardening priorities list, which covers where this fits against other fixes.
  6. Re-run SharpHound after hardening and diff the edge count. A drop in HasSession and AdminTo edges against the same domain, with the same collection methods, is the only proof the change actually reduced the attack graph rather than just the compliance checklist.

How EtcSec Detects This

EtcSec's Active Directory audit covers all three settings at the level where they are governed centrally: Group Policy. NET_SESSION_HARDENING_MISSING fires when no policy configures SrvsvcSessionInfo session hardening at all — the NetCease-equivalent setting is simply absent from the domain's policy set. SAM_REMOTE_ACCESS_OPEN fires when RestrictRemoteSam is either unset or carries an SDDL with no DACL in it, which is the state that leaves the domain-controller default in place. SMB_V1_ENABLED fires when policy leaves SMBv1 enabled.

Read those three findings for what they are: they tell you whether the domain has a policy closing these gaps, not whether every individual machine complies with it. That distinction is the whole point of this article. A clean GPO baseline still leaves you the per-host work described above — reading SrvsvcSessionInfo and RestrictRemoteSam on the hosts themselves, and re-running SharpHound to diff the edge count — because an in-place upgrade, a local policy write or a third-party hardening script can diverge from the policy without changing it.

Explore the identity security pages that support this topic