SQL Server runs as a Tier Zero account
A SQL Server instance runs as a Domain Admin or other Tier Zero account, so whoever administers the database can act as that account.
- Category
- Attack Path
- Severity
- At least High.
- Typical owner
- the database team, with the owner of the service account
- Data needed
- MSSQLHound's OpenGraph output, read with its built-in mapping pack*. That pack is untrusted until you trust it (
trust = ["mssqlhound"]under[opengraph]in pathwarden.toml, or on the app's Mappings page); until then its data is context only. See the OpenGraph guide.
On this page
In plain language
Every SQL Server instance runs as a Windows account. Database administrators can make the server run operating system commands, and those commands run as that account. Older installations were often set up to run as a Domain Admin "so the backups work".
That turns everyone who administers the instance (its sysadmin logins, logins that can impersonate them, administrators of the server it runs on) into a Domain Admin. Database teams are rarely treated as Tier Zero, so this path is easy to miss. Running the service as a gMSA or the default virtual account, with only the rights it needs, closes it.
What Pathwarden flags
A SQL Server instance's service runs as a Tier Zero account (often an old
installation that runs as a Domain Admin). Whoever controls the instance (a
sysadmin login, a login with CONTROL SERVER or IMPERSONATE ANY LOGIN, an
administrator of its computer) runs code as that account (xp_cmdshell, SQL
Agent jobs, CLR) and can use its identity on the network. So the instance,
and everyone who administers it, controls Tier Zero.
The finding lists the accounts and logins outside Tier Zero that control the instance.
The evidence comes from MSSQLHound (an OpenGraph file, see
docs/opengraph.md): its service account record, and the logins, roles
and permissions that lead to the instance, with Pathwarden's corrections
(DENY through roles, the public role, disabled logins).
How attackers use it
SQL Server is everywhere, its sysadmins are rarely treated as Tier Zero, and
xp_cmdshell is one sp_configure away for a sysadmin. A service account
in Domain Admins turns "DBA on a reporting server" into "Domain Admin"
(T1505.001, SQL Stored Procedures; T1078.002, Domain Accounts). The service
account's password is also Kerberoastable through its MSSQLSvc SPN
(PW-006).
Find it with Pathwarden
Data needed: MSSQLHound's OpenGraph output, read with its built-in mapping pack*. That pack is untrusted until you trust it (trust = ["mssqlhound"] under [opengraph] in pathwarden.toml, or on the app's Mappings page); until then its data is context only. See the OpenGraph guide.
In the web UI or the HTML report, open the Findings tab and expand PW-034: each finding shows who can use it (its exposure), the attack path drawn out, the affected objects, and the fix. The remediation path tells you whether a single plan step closes it. On the command line:
# every finding of this rule, with its path and fix
pathwarden findings -i .\collect --rule PW-034
# the step-by-step guide on this page, offline
pathwarden guide PW-034
# after the fix: collect again, then check it is gone
pathwarden retest -i .\collect-after --rule PW-034Exit codes make retest easy to script: 0 Fixed, 1 Still open, 3 Can't tell. See findings lifecycle and retest.
Before you change anything
- Confirm the service account in SQL Server Configuration Manager or with
SELECT servicename, service_account FROM sys.dm_server_services. - Find out why it runs as that account: usually a linked server, a backup share or an old installer default. List what the instance reaches with it (backup paths, linked servers, SSIS packages, Agent jobs).
- Plan a service restart window.
How to fix it
Option A: Run the service as a gMSA or a virtual account (recommended)
- Change the service account with SQL Server Configuration Manager (not
services.msc), to a group managed service account or the default virtual accountNT SERVICE\MSSQLSERVER. - Grant the new account only what the instance needs (the backup share, the remote resources), then remove the old account from Tier Zero groups and rotate its password.
- Move the
MSSQLSvcSPNs to the new account (Configuration Manager does it for virtual accounts and gMSAs).
Option B: Treat the instance as Tier Zero
If it must keep the account, the instance is Tier Zero: remove sysadmin, CONTROL SERVER and IMPERSONATE ANY LOGIN from every login outside Tier Zero, limit the local administrators of its computer to Tier Zero admins, and add the computer under Additional Tier Zero in Settings.
T-SQL and PowerShell
-- Who controls the instance
SELECT r.name AS role, m.name AS member, m.is_disabled
FROM sys.server_role_members rm
JOIN sys.server_principals r ON r.principal_id = rm.role_principal_id
JOIN sys.server_principals m ON m.principal_id = rm.member_principal_id
WHERE r.name IN ('sysadmin', 'securityadmin');
SELECT pr.name, pe.permission_name, pe.state_desc
FROM sys.server_permissions pe JOIN sys.server_principals pr ON pr.principal_id = pe.grantee_principal_id
WHERE pe.permission_name IN ('CONTROL SERVER', 'IMPERSONATE ANY LOGIN');
-- Remove a login from sysadmin
ALTER SERVER ROLE sysadmin DROP MEMBER [<Login>];# Create a gMSA for the instance
New-ADServiceAccount -Name "<gMSA>" -DNSHostName "<gMSA>.<Domain>" -PrincipalsAllowedToRetrieveManagedPassword "<SqlComputer>$"
Install-ADServiceAccount -Identity "<gMSA>" # on the SQL Server computerVerify the fix
Collect again with MSSQLHound and its coverage file, then analyze the new collection. The finding is fixed when the instance no longer runs as a Tier Zero account (or the account left Tier Zero). Without a coverage file it stays open as "can't tell".
Roll back
Set the previous service account again in SQL Server Configuration Manager and restart the service. Do not restore a Tier Zero account's old password.
References
- Microsoft: Configure Windows service accounts and permissions (SQL Server)learn.microsoft.com
- Microsoft: Group Managed Service Accounts overviewlearn.microsoft.com
- MSSQLHound (SpecterOps)github.com
- SpecterOps: Adding MSSQL to BloodHound with OpenGraphspecterops.io
- Microsoft: xp_cmdshell (Transact-SQL)learn.microsoft.com
- MITRE ATT&CK T1505.001: Server Software Component: SQL Stored Proceduresattack.mitre.org
- MITRE ATT&CK T1078.002: Valid Accounts: Domain Accountsattack.mitre.org
Very new and undergoing testing. These features haven't received a lot of testing yet. Try them out and let us know what's working.