Published: May 03, 2012
For the most part, Windows Server services run under generic system based accounts, such as LocalSystem or NT AUTHORITY\LocalService. But occasionally, a service needs to be run under a “real” user account, either domain or machine-based. Too often I’ve seen these running under an administrator account. In any event, you should know where these types of service accounts are being used.
The first thing you might want to do is find out what accounts are currently being used. PowerShell is the easiest tool. We can use WMI to query all instances of the Win32_Service class and look at the StartName property. One approach might be to use Group-Object.
PS C:\> get-wmiobject win32_service -comp jdhit-dc01 | Group Startname -NoElement | Sort Count Count Name ----- ---- 1 administrator@jdhitsol... 1 JDHITSOLUTIONS\Adminis... 10 NT AUTHORITY\NetworkSe... 14 NT AUTHORITY\LocalService 79 LocalSystem
This gives me a nice distribution breakdown, but I can see there are a few services using a user account. If I know in advance what account to search for, I could run a PowerShell command like this:
PS C:\> get-wmiobject win32_service -comp jdhit-dc01 -filter "Startname Like '%Administrator%'" | select name,startname name startname ---- --------- MSSQL$MICROSOFT##SSEE [email protected] RSEEService JDHITSOLUTIONS\Administrator
A better approach would be to filter out all the system accounts. This is a little tricky with WMI filtering, but here’s something that should do the trick.
PS C:\> get-wmiobject win32_service -comp jdhit-dc01 -filter "Startname Like '[^NT Authority|LocalSystem]%' OR Startname Like '%@%'" | select name,startname name startname ---- --------- MSSQL$MICROSOFT##SSEE [email protected] RSEEService JDHITSOLUTIONS\Administrator
In my testing, I’ve found I need the compound filter to pick up accounts using the UPN format. But now, given a list of computernames, I could build a report like this.
PS S:\> get-wmiobject win32_service -comp (get-content computers.txt) -filter "Startname Like '[^NT Authority|LocalSystem]%' OR Startname Like '%@%'" | select systemname,name,startname | export-csv svcaccounts.csv –NoTypeInformation
This will create a simple CSV file which I can open in Excel.
If you prefer your WMI in a CLI flavor, you can also use WMIC from a a CMD prompt.
C:\>wmic service where 'startname like "[^NT Authority|LocalSystem]%"' Get Name, Displayname,StartName DisplayName Name StartName SQL Server (SQLExpress) MSSQL$SQLEXPRESS .\sql Veeam Backup Service Veeam Backup and Replication Service .\Jeff Veeam Backup Catalog Service Veeam Backup Catalog Data Service .\Jeff
WMIC can be a bit tricky, so if you are interested in using it, you might want to check out my articles on the subject. [Command Line WMI Part 1; Command Line WMI Part 2; Command Line WMI Part 3]
Now, if PowerShell isn’t an option for you and you find WMIC awkward, you could turn to the command line tool SC.EXE to retrieve the same information. If you suspect a service, it is pretty easy to check.
C:\>sc qc mssql$sqlexpress [SC] QueryServiceConfig SUCCESS SERVICE_NAME: mssql$sqlexpress TYPE : 10 WIN32_OWN_PROCESS START_TYPE : 2 AUTO_START (DELAYED) ERROR_CONTROL : 1 NORMAL BINARY_PATH_NAME : "c:\Program Files\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\Binn\sqlservr.exe" -sSQLEXPRESS LOAD_ORDER_GROUP : P@ssw0rd TAG : 0 DISPLAY_NAME : SQL Server (SQLExpress) DEPENDENCIES : SERVICE_START_NAME : .\sql
Scripting this to check all services is a bit more tedious, and after more time than I would have wanted, I came up with a batch file you could use. Don’t expect a speedy result like PowerShell, as the script has to get a list of all services and then get the configuration for each service and check the service start name.
@echo off ::GetServiceAccount.bat ::Jeffery Hicks :: http://jdhitsolutions.com/blog :: http://twitter.com/jeffhicks ::USAGE GetServiceAccount [computername] ::You must run this with an account that has admin rights on any remote computer if %1$==$ ( set zcomp=%Computername% ) else ( set zcomp=%1 ) echo Finding non system service accounts on %zcomp% rem get a list of service names sc \\%zcomp% query type= service state= all | findstr /i "Service_Name" > %temp%\~zlist.qqq for /f "tokens=2* delims=: " %%i in (%temp%\~zlist.qqq) Do if %%j$==$ (Call :Check %zcomp% %%i) else ( Call :Check %zcomp% "%%i %%j") goto :Exit :Check rem echo %2 rem create a temp file sc \\%1 qc %2 | findstr /i "Name" > %temp%\~foo.qqq rem define a counter set zcount=0 rem test for service account name findstr /i "service_start_name" %temp%\~foo.qqq | findstr /i /r "\<LocalSystem" > NUL if errorlevel 1 set /a zcount+=1 findstr /i "service_start_name" %temp%\~foo.qqq | findstr /i /r "\ NUL if errorlevel 1 set /a zcount+=1 rem If neither type of entry was found then display the temp file if %zcount% equ 2 type %temp%\~foo.qqq :Exit set zcomp= set zcount= rem delete temp file if it still exists if Exist %temp%\~foo.qqq del %temp%\~foo.qqq if Exist %temp%\~zlist.qqq del %temp%\~zlist.qqq
But it works:
C:\>c:\scripts\GetServiceAccount.bat JDHIT-DC01 Finding non system service accounts on JDHIT-DC01 SERVICE_NAME: MSSQL$MICROSOFT##SSEE BINARY_PATH_NAME : C:\WINDOWS\SYSMSI\SSEE\MSSQL.2005\MSSQL\Binn\sqlser vr.exe -sMICROSOFT##SSEE DISPLAY_NAME : Windows Internal Database (MICROSOFT##SSEE) SERVICE_START_NAME : [email protected] SERVICE_NAME: RSEEService BINARY_PATH_NAME : "C:\Program Files\SAPIEN Technologies, Inc\RSEE Ser vice\rexecService.exe" DISPLAY_NAME : Remote Script Execution SERVICE_START_NAME : JDHITSOLUTIONS\Administrator C:\>
Personally, I’ll stick to PowerShell but I wanted to leave you with some options. In any event, now you should be able to identify what accounts your services are running under, and identify potential problems before they become major headaches. If you want to try the batch file, you can download it here.