Every Windows service configured to run as a domain user account leaves that account's password on the host, so one compromised server can hand an attacker an identity that works on every other server where the same account runs. Directory queries tell you which service accounts exist, but not where they are actually used. This guide works from the host side: it shows how to enumerate the logon account of every service across a Windows estate, how to separate domain accounts from built-in and managed identities, how to confirm the results from logon events, and how to change a service's account without an outage. It is for Windows server administrators, identity teams and detection engineers. For the background on service identity choices, see the Windows Services and Service Account Security Guide.
Key takeaways
- StartName is the field that matters: the
Win32_Serviceclass exposes the account each service runs as inStartName, inDomainName\Usernameor UPN form, so one read-only CIM query per host gives you the raw data. - Exclude what is safe, keep what is not: LocalSystem,
NT AUTHORITY\LocalService,NT AUTHORITY\NetworkServiceandNT SERVICE\virtual accounts have no domain password to steal; group managed service accounts end in$and have a Windows-managed password. Everything else with a domain prefix is a finding. - The password lives on the host: Microsoft states the Service Control Manager does not maintain service passwords, and Windows keeps them as LSA secrets, which attackers dump with ATT&CK T1003.004. A domain account on 200 servers is 200 places to steal it.
- Logon events confirm reality: event 4624 with logon type 5 records the Service Control Manager starting a service under an account, and 4697 records the account configured at install. Use them to catch hosts your scan missed.
- Change the account, not just the record: the fix is a gMSA, a virtual account or a scoped account per service, set in a change window with the previous configuration recorded so you can roll back with one command.
When you need this
- Before rotating a service account password: you must know every host and service using it, or the rotation stops services you did not know about. Microsoft notes that if the password expires, the logon fails and the service fails to start. See Rotating a Windows or Linux Service Account Password.
- Before converting to gMSA: the host list from this guide is the input to How to convert AD service accounts to gMSA, because the gMSA must be allowed for every host that runs the service.
- After a privileged account review: once How to find service accounts with Domain Admin rights has found a privileged service account, this guide tells you which servers hold its password and therefore which hosts are effectively Tier 0.
- Incident response: if a server is compromised, every domain account running a service on it must be treated as exposed. The list from this guide is the reset list.
- Inventory and audit: CIS Controls v8.1 Safeguard 5.5 asks for an inventory of service accounts; the host view adds where each one runs. The Service Account Inventory Template has a layout for the results.
Before you start
- Access: reading service configuration remotely needs administrative rights on each target host. Use a dedicated, audited administrative account from a privileged access workstation, not a domain admin account on every server. See the Privileged Access Workstations Guide.
- Transport:
Get-CimInstance -ComputerNamecreates a temporary session over WS-Management (WinRM). Microsoft recommends a CIM session (New-CimSession) when you run several operations against the same computer. Confirm WinRM is reachable on the server estate first; for hosts without WinRM, use your endpoint management or EDR inventory instead. - Scope: member servers, domain controllers, and workstations where line-of-business agents run. Include servers in other domains of the forest and in resource forests.
- A results table: host, service name, display name,
StartName,StartMode,State,PathName, collection time, classification and owner. - Read-only first: every discovery step below only reads configuration. Changes come at the end, under change control.
Step-by-step
1. Know how a service records its account
| Where | What it shows | Notes |
|---|---|---|
Win32_Service.StartName (CIM/WMI) | Account the service runs as: DOMAIN\user, user@domain, .\user for a local account, or a built-in name | For kernel and file system drivers, StartName holds a driver object name such as \FileSystem\Rdr, not an account; filter drivers out |
Registry value ObjectName under HKLM\SYSTEM\CurrentControlSet\Services\<service> | The same logon account, as stored by the Service Control Manager | Useful for offline images and for tools that read the registry rather than WMI |
QueryServiceConfig (Win32 API, used by sc.exe qc) | User name, never the password | Microsoft documents that the API returns the user name but not the password |
| Security event 4697 | Service Account configured when the service was installed | Microsoft notes later account changes are not logged in this event |
| Security event 4624, logon type 5 | The Service Control Manager started a service under this account | Shows the account actually used at start, on hosts with logon auditing |
2. Classify the values you will see
StartName value | Identity type | Domain password on host? | Classification |
|---|---|---|---|
LocalSystem | Built-in, acts as the computer account on the network | No | Not in scope here; review custom services running as LocalSystem separately |
NT AUTHORITY\LocalService, NT AUTHORITY\NetworkService | Built-in, low privilege | No | Expected |
NT SERVICE\<name> | Virtual account, per service | No | Expected; preferred for single-host services |
DOMAIN\name$ | Group managed (or standalone managed) service account | Windows-managed password, retrieved from a domain controller | Expected; check which hosts may retrieve it |
.\name or HOSTNAME\name | Local user account | Local password only | Finding if the same local name and password repeat across hosts |
DOMAIN\name or name@domain without a trailing $ | Domain user account | Yes, stored on the host | Finding: the subject of this guide |
3. Query a single host (read-only)
- On one test server, run
Get-CimInstance -ClassName Win32_Service -Property Name,DisplayName,StartName,StartMode,State,PathName,ServiceType. The-Propertyparameter limits what is returned, which matters when you scale out. - Drop drivers by keeping only
ServiceTypevaluesOwn ProcessandShare Process(and the interactive variants if present). - Drop the built-in identities from step 2 by name, and drop any
StartNameending in$into a separate managed account list. - What remains with a domain prefix or UPN suffix is your domain account list for that host. Compare it with the Services console (the Log On As column) on the same host to prove the filter is right before you scale out.
4. Scale out across the estate
- Build the host list from Active Directory computer objects that are enabled and have logged on recently, split into rings (for example 50 servers first).
- Create CIM sessions in batches with
New-CimSession -ComputerNameand pass them with-CimSession, which Microsoft recommends for repeated operations against the same computer. Record hosts that fail to connect: they are a coverage gap, not a clean result. - Collect the same properties as step 3, add the host name and timestamp, and write to your results table.
- Where WinRM is blocked, take the same fields from configuration management, EDR or an agent that reads the
ObjectNameregistry value. Do not open remote management just for this survey. - Repeat on domain controllers separately. Any domain user account running a service on a domain controller has a password stored on a Tier 0 system and must be treated as Tier 0.
Small estates (tens of servers) can do this in an afternoon from one workstation. Large estates should prefer the inventory the endpoint platform already collects and use direct CIM queries only to fill gaps, because thousands of interactive admin connections are themselves noisy and create exposure.
5. Confirm from logon events
- Logon type 5: in your SIEM, search event 4624 with Logon Type 5 and a domain in the Account Domain field that is not
NT AUTHORITYorNT SERVICE. Group by account and host. Hosts that appear here but not in the scan are coverage gaps. - Managed accounts: Microsoft notes that logons by managed service accounts and gMSAs show
Virtual Account = Yesin 4624, which helps you separate them. - Privilege mismatch: Microsoft recommends monitoring for a mismatch between logon type and account, for example logon type 5 by a member of a domain administrative group. Join the account list with the results of the Domain Admin review.
- New services: event 4697 (subcategory Audit Security System Extension) logs the Service Account for each new service. Microsoft recommends reporting every 4697 where the Service Account is not localSystem, localService or networkService. Event 7045 in the System log gives a similar signal without extra audit policy.
Getting these events into one place needs collection from member servers, not only domain controllers. See the Windows Event Forwarding Guide and the Active Directory Security Monitoring and Event IDs Guide.
6. Enrich and rank the findings
Pivot the results by account. For each domain account record the number of hosts and services, whether any host is a domain controller or other Tier 0 system, the account's group memberships, servicePrincipalName (Kerberoasting exposure, ATT&CK T1558.003), pwdLastSet and the password never expires flag. Then rank:
| Priority | Pattern | Why |
|---|---|---|
| 1 | Privileged account (Domain Admins or equivalent) running a service on member servers | Dumping one server's LSA secrets yields domain control |
| 2 | One account on many hosts | Lateral movement from any one host to all others (ATT&CK T1078.002) |
| 3 | Account with an SPN and an old human-set password | Offline cracking through Kerberoasting |
| 4 | Account on a domain controller or identity system | Password stored on a Tier 0 host |
| 5 | Personal user account running a service | Service breaks when the person leaves; nobody owns it |
| 6 | Single-host service using a domain account it does not need | Replace with a virtual account |
Assign an owner to each account from the application that uses it. If nobody claims an account, that is a finding in its own right; the How to Run an Access Review for Service Accounts guide covers the attestation step.
7. Choose the replacement identity
| Situation | Use | Trade-off |
|---|---|---|
| Service needs no network identity, or the computer account is enough | Virtual account (NT SERVICE\name) or NetworkService | Network access uses the computer account, so permissions are granted to the computer |
| Service needs a domain identity on one or more hosts | gMSA | Windows manages the password; the application must support a service logon without a typed password; Windows Server 2012 and later |
| Product does not support gMSA | A dedicated domain account per service and tier, long random password, vaulted and rotated, logon restricted to its hosts | Rotation is still a manual or PAM-driven process |
| Account is not used (service disabled or host retired) | Remove the service configuration, then disable the account | Check for scheduled tasks and app pools using the same account first |
Scheduled tasks and IIS application pools can also store domain credentials on the host. They are outside this guide's queries, but the same account often appears in all three, so check them before you disable anything.
8. Change the logon account (destructive, change-controlled)
- Record the current configuration for rollback: service name,
StartName,StartModeand the service's dependencies. - Prepare the new identity. For a gMSA, the host must be allowed to retrieve its password; Microsoft documents that member hosts obtain the current and preceding password values from a domain controller.
- Grant the new identity only what the application needs: file and registry ACLs, database logins, SPNs moved from the old account, and the Log on as a service right (
SeServiceLogonRight) if your GPO restricts it. - Change the service account in a maintenance window, using the Services console, your configuration tooling, or
sc.exe config <service> obj= <account>. Microsoft notespassword=is required for any account other than LocalSystem, and that a space must follow each equals sign. For a gMSA, the account name ends with$and no password is entered. - Restart the service and check event 4624 type 5 for the new account and the application's own health checks.
- After a soak period, remove the old account's rights on that host. Once no host uses it, disable it, wait one review cycle, then delete it.
Verify it worked
The targets below are NHI Mgmt Group recommendations, not vendor or regulatory requirements.
| Metric | Source | Target |
|---|---|---|
| Hosts scanned out of hosts in scope | Scan results versus AD computer list | Above 98%, gaps named |
| Services running as domain user accounts | Step 3 and 4 queries | Falling each month; each remaining one with owner and reason |
| Domain accounts used on more than one host | Pivot by account | Zero outside gMSAs |
| Privileged accounts running services on member servers | Join with privileged group review | Zero |
| Logon type 5 accounts not in the inventory | Event 4624 in SIEM | Zero |
| New services installed with a domain user account | Event 4697 or 7045 | Each one tied to a change ticket |
Rollback and common errors
- Rollback: set the service back to the recorded account and password, restart, and check the 4624 type 5 event. Keep the old account enabled until the soak period ends so rollback is possible.
- Filtering drivers as findings: driver
StartNamevalues are object names, not accounts. Filter on service type before classifying. - Trusting 4697 alone: it records the account at install time only. A service later switched to a domain account does not generate a new 4697, so the scan and type 5 logons are the real picture.
- Treating unreachable hosts as clean: failed connections are missing data. Report coverage with every result.
- Forgetting the password was exposed: changing a service off a shared domain account does not undo what the stored password allowed. Reset the old account's password once services have moved, or disable it.
- Missing other credential stores: the same account in a scheduled task or app pool keeps working after you move the service, then fails when you disable the account.
Where identity fits
A domain account used by a service is a non-human identity with the same lifecycle problems as any other: no natural owner, a password that rarely changes, and permissions that grow. The host scan is the usage evidence that identity governance usually lacks. Feed it into your service account inventory and access reviews so the directory record shows where each account runs. The Service Account Security Guide covers the governance model.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| NIST CSF 2.0 | PR.AA-01, PR.AA-05, DE.CM-03 | Credentials for services managed; least privilege; account usage monitored |
| NIST SP 800-53 Rev 5 | AC-2, AC-6, IA-5, CM-8 | Account management, least privilege, authenticator management, component inventory |
| CIS Controls v8.1 | Safeguard 5.5; Controls 5 and 6 | Inventory of service accounts; account and access control management |
| ISO/IEC 27001:2022 Annex A | A.5.16, A.8.2 | Identity management; privileged access rights |
| MITRE ATT&CK v20 | T1003.004 LSA Secrets; T1078.002 Domain Accounts; T1558.003 Kerberoasting; T1543.003 Windows Service; T1007 System Service Discovery | Theft of stored service passwords, reuse of domain accounts, ticket cracking, malicious services, and the same discovery an attacker runs |
Practitioner checklist
- Test the
Win32_Servicequery and filter on one host against the Services console. - Scan every in-scope host in rings and report coverage alongside findings.
- Classify each
StartName: built-in, virtual, managed ($), local, or domain user. - Confirm with 4624 logon type 5 and alert on 4697 or 7045 with non-built-in accounts.
- Pivot by account, record hosts, privileges, SPNs and password age, and rank by risk.
- Assign an owner to each account and check scheduled tasks and app pools for the same account.
- Move services to gMSA or virtual accounts in change windows with the old configuration recorded.
- Reset or disable the old account after the soak period and repeat the scan monthly.
Standards and references
- Microsoft Learn: Win32_Service class
- Microsoft Learn: Service User Accounts
- Microsoft Learn: Get-CimInstance
- Microsoft Learn: Event 4697, A service was installed in the system
- Microsoft Learn: Event 4624, An account was successfully logged on
- Microsoft Learn: Log on as a service
- Microsoft Learn: sc.exe config
- Microsoft Learn: Group Managed Service Accounts overview
Related NHI Mgmt Group resources: Group Managed Service Accounts (gMSA) Guide, How to find and retire Active Directory service accounts with SPNs, Credential Dumping Guide, Lateral Movement Guide.