Breach Horizon
guides

Service account hygiene: the 4 mistakes that turn one compromised key into full domain takeover

Laurens VanhaekeJun 8, 20268 min readReviewed by Laurens Vanhaecke

Most ransomware groups don't brute-force their way to a domain controller. They walk in through a service account that hasn't had its password changed since the previous IT admin left three years ago. Service account hygiene isn't a compliance checkbox — it's the difference between a contained incident and a full rebuild.

Why service accounts are the #1 lateral-movement vector

Service accounts are structurally attractive to attackers for one reason: they're designed to authenticate without human interaction, which means the usual trip-wires don't fire. No MFA prompt. No user noticing an unexpected login. No one questioning why the backup agent is authenticating at 2 a.m. on a Saturday.

In Active Directory environments — which still describes the majority of SMB and mid-market networks — service accounts typically hold persistent, high-privilege credentials that are valid 24/7. When CrowdStrike and Microsoft both publish their annual threat reports, lateral movement through compromised service or machine identities consistently sits at the top of the initial-access-to-privilege-escalation chain. The 2023 Scattered Spider campaign against MGM and Caesars didn't rely on zero-days. It relied on over-privileged identities and absent monitoring.

For MSPs managing 50-client portfolios, the blast radius compounds. One client's compromised service account credential, if that account has been copy-pasted into another client's environment — which happens more than anyone admits — becomes a cross-tenant incident. The remediation cost isn't one rebuild, it's ten.

The four mistakes below cover the vast majority of real-world service account exposure I've seen across client environments. None of them require advanced tooling to fix. They require discipline.

Mistake 1: Human-set passwords that never rotate

The most common service account configuration I encounter is a password set by a human, documented in a password manager or a sticky note, and never changed because "rotating it will break something." That fear is understandable. It's also wrong, and it's been wrong since Windows Server 2008 R2 introduced Managed Service Accounts (MSAs) and since 2012 when Group Managed Service Accounts (gMSAs) expanded the capability domain-wide.

gMSAs solve the rotation problem entirely. The Key Distribution Service handles password generation and rotation automatically — 240-character random passwords, rotating on a schedule you define, with no application restart required for supported services. SQL Server, IIS application pools, scheduled tasks, Windows services — all of them support gMSAs. If your service account is running a supported workload and you're still using a human-set password, you've accepted a risk you didn't need to accept.

For workloads that can't use gMSAs — legacy apps, third-party services that authenticate with static credentials — service account password rotation needs to be automated through your RMM. NinjaOne and ConnectWise both support scripted credential rotation tied to their secret vaults. The rotation interval should be 90 days maximum; 30 days for anything with domain-level permissions. "Breaking something" is a one-time migration cost. A compromised static credential is a potential $500K incident.

One concrete check: pull every service account from Active Directory, filter for PasswordLastSet older than 180 days, and cross-reference against PasswordNeverExpires = True. That combination is a red flag in every environment I've audited. In most environments I audit, it describes 30-40% of service accounts.

Mistake 2: Domain Admin membership 'for now'

"For now" is the most expensive phrase in IT. A service account gets Domain Admin because the application vendor said it was required, or because it was easier than scoping exact permissions, or because someone was under pressure during a deployment and would "clean it up later." Later never comes.

Domain Admin membership on a service account means a single credential compromise equals full domain takeover. Every DC. Every GPO. Every user account. Every file share. The attacker doesn't need to escalate privileges — you handed them the keys before they even asked.

The fix is least-privilege scoping, and it requires actually reading what permissions the application needs. Most enterprise applications that claim to need Domain Admin don't. They need specific delegation — write access to a particular OU, read access to group membership, the ability to register SPNs. Microsoft's documentation for products like Exchange, SCCM (now Intune co-management), and SharePoint all specify minimum required permissions. Vendor documentation that says "Domain Admin required" without justification should be challenged. If the vendor can't explain why, escalate to their support team and document the response.

For applications that genuinely need elevated AD access, create a custom role with exactly the delegated rights required. Use dsacls or the AD Delegation of Control Wizard to scope it. Audit it quarterly. If you're managing client environments through a platform like Microsoft 365 Business Premium + Entra ID, the same principle applies to service principals and app registrations — scope to minimum Graph API permissions, not Directory.ReadWrite.All by default.

The practical test: open Active Directory Users and Computers, navigate to the Domain Admins group, and look at every non-human member. Any service account in that list that has been there longer than a deployment window is a liability you're carrying for free.

Mistake 3: Same account across dev/prod

Environment parity is convenient for developers and catastrophic for security teams. When the same service account credential runs in both development and production environments, you've effectively made your production blast radius as large as your least-secured environment — and dev environments are almost always less secured.

Dev environments typically have looser firewall rules, more permissive GPOs, developer workstations with local admin, and less monitoring. An attacker who compromises a dev environment through a phishing email, an exposed RDP port, or an unpatched vulnerability now has a valid credential that works in production. They don't need to find a separate foothold. They already have one.

The fix is environment segregation at the identity layer. Production service accounts should be provisioned separately from dev and staging. They should have different passwords (or separate gMSA configurations), different naming conventions (svc-prod-backupagent vs. svc-dev-backupagent), and different audit policies. Cross-environment reuse should be a policy violation, not just a recommendation.

This also applies to MSP-managed environments. If you're using a shared monitoring credential across all client tenants — a pattern I've seen in NinjaOne and ConnectWise deployments — a compromise of that credential in one client's environment is a compromise of your monitoring visibility everywhere. Tenant isolation at the credential layer isn't optional. Cloudflare's Zero Trust platform and similar ZTNA solutions let you scope service account–equivalent access per tenant without credential sharing, which is the architecture you should be building toward.

A Kerberoasting attack specifically targets this mistake. If a service account with a weak or reused password has an SPN registered, any domain-authenticated user can request a Kerberos service ticket and attempt offline cracking. Tools like Rubeus or Impacket's GetUserSPNs make this trivially easy. Unique, complex, regularly rotated passwords per environment make Kerberoasting computationally impractical.

Mistake 4: No monitoring for service-account interactive logins

Service accounts should never log in interactively. They authenticate as services — event ID 4624 with logon type 5 (service) or type 4 (batch). If you see a service account generating logon type 2 (interactive) or type 10 (remote interactive/RDP), something is wrong. Either an admin is using a service account as a shortcut, or an attacker is using a compromised service account credential to move laterally.

Most environments have zero alerting on this. Windows Security logs generate the events. Nobody reads them.

The fix has two parts. First, enforce the restriction: configure the "Deny log on locally" and "Deny log on through Remote Desktop Services" user rights assignments in Group Policy for all service accounts. This turns the misconfiguration from a silent risk into an auditable failure. Second, alert on it: ship Security event logs to your SIEM or log aggregator and build a detection rule on event ID 4624 where the account name matches your service account naming convention and logon type is 2, 7, 10, or 11.

If you're using Microsoft Sentinel, the query is four lines of KQL. If you're using a SIEM built into your RMM, the logic is the same. CrowdStrike Falcon Identity Protection surfaces this natively for enrolled endpoints. There's no excuse for not having this detection in 2026.

The broader principle: service accounts need their own monitoring tier. They don't behave like users, so user-behavior baselines don't apply cleanly. What you're looking for is deviation from the account's established authentication pattern — new source IPs, new destination hosts, new logon types, authentication outside business hours for accounts that have never authenticated outside business hours. Establish the baseline, alert on deviation, investigate every alert.

The 90-day cleanup project that fixes 80% of risk

You don't need a six-month initiative. You need a structured 90-day sprint with clear ownership.

Days 1-30: Inventory and classify. Pull every service account from AD. Document the owning application, the responsible team, the last password change, group memberships, and whether it has an SPN. Flag every account with Domain Admin membership, PasswordNeverExpires, or PasswordLastSet older than 180 days. This inventory doesn't exist in most environments. Building it is the highest-value action you can take in month one.

Days 31-60: Migrate and restrict. Convert every eligible service account to a gMSA. For accounts that can't convert, implement scripted rotation through your RMM vault. Strip Domain Admin membership from every service account that doesn't have a documented, reviewed business justification. Apply "Deny interactive logon" GPO settings to all service accounts.

Days 61-90: Monitor and validate. Deploy detection rules for interactive service account logins. Run a Kerberoasting simulation using a read-only domain account and verify your SIEM catches the ticket requests. Validate that gMSA rotation is firing on schedule by checking the msDS-ManagedPasswordLastChangeTimestamp attribute. Document what you've done — not for compliance, but because the next incident response engagement will demand it.

If you want to validate what's visible from outside your environment before you start that sprint — exposed credential endpoints, misconfigured DNS, public-facing services running under over-privileged accounts — run the free Exposure Report and use the findings to prioritize your internal remediation order. External exposure doesn't cause service account compromise directly, but it tells you which attack paths are most likely to land an attacker in a position where they can use a weak service account credential.

For more on how we approach layered identity risk across client environments, read our methodology.


Service account hygiene is unsexy. It doesn't generate a vendor case study or a conference talk. It generates environments where attackers who get a foothold find dead ends instead of highways. That's the outcome worth building toward.

Run the free Exposure Report and validate public-surface findings.

See what attackers see — before they do.

Run the free passive scan, get a prioritized fix plan, and close the gaps yourself or have us do it for you.