Finding Services Using non-System accounts
Originally published March 23, 2006
I went into a new customer recently and found that they had about a gazillion standalone servers, all of which had the same administrator password, and they used the Administrator account to run some services.
While there often seem to be good reasons for doing this (pass through authentication, only requiring a single account having elevated privileges, etc.) it almost always turns out to be a bad idea. It makes it difficult to change passwords when employees turn over, and you can have service failures when you change passwords.
And, lest you forget, there are other things that could possibly depend on these passwords too: COM objects and websites, to mention two other possibilities.
So, I wrote a script that, based upon a simple input file containing a list of computers, goes out and checks for all services running on each computer that are using a non-default account. For the purposes of my script, I considered these accounts to be default accounts: "NT AUTHORITY\LocalService", "LocalSystem", ".\ASPNET", "NT AUTHORITY\NETWORK SERVICE", "NT AUTHORITY\NetworkService". In your environment, those will probably work, but I make no guarantees for that. :-)
This script also specifically identifies the total number of services running under the administrator account. Those are things you really probably want to change!
The input file is easy to generate from adfind/dsquery/dns - whatever way you can use to produce a list of servers in your environment, one server per line. If you need to have comment lines, then begin a line with the crosshatch character (”#”).
Sample summary output:
Processing complete
Total computers processed: 33
Total Administrator services: 27
Total special services: 62
Total errors: 0
Total comment lines: 0
Of course, as always, this script is provided “AS IS” and conveys no warranties.
Option Explicit
' check-services.vbs
Const ForReading = 1
Dim objFS, objFileIn, iCount, iError, iComment, iAdminCount, iTot
Dim strRemoteComputer
Sub e (str)
WScript.Echo str
End Sub
Function ErrorReport (str)
If Err.Number Then
iError = iError + 1
ErrorReport = True
e "Error 0x" & CStr (Hex (Err.Number)) & " occurred " & str
If Err.Description <> "" Then
e "Error description: " & Err.Description & "."
End If
Err.Clear
Else
ErrorReport = False
End If
End Function
Sub Startup
If Wscript.Arguments.Count <> 1 Then
e "Usage: Check-Services.vbs listofcomputers.txt"
e " "
e "'listofcomputers.txt' contains a list of the computers"
e "that will be checked for services that do not contain"
e "default accounts."
e " "
wscript.quit 1
End If
On Error Resume Next
Set objFS = CreateObject ("Scripting.FileSystemObject")
If ErrorReport ("while creating Scripting.FileSystemObject") Then
wscript.quit 1
End If
Set objFileIn = objFS.OpenTextFile (wscript.arguments (0), ForReading)
If ErrorReport ("while opening " & wscript.arguments (0)) Then
Set objFS = Nothing
wscript.quit 1
End If
iTot = 0
iCount = 0
iError = 0
iComment = 0
iAdminCount = 0
End Sub
Sub Shutdown
objFileIn.Close
Set objFileIn = Nothing
Set objFS = Nothing
End Sub
' Constants we need for WBEM calls
Const wbemFlagReturnImmediately = &H10
Const wbemFlagForwardOnly = &H20
Dim arrExclude
arrExclude = Array ("NT AUTHORITY\LocalService", _
"LocalSystem", _
".\ASPNET", _
"NT AUTHORITY\NETWORK SERVICE", _
"NT AUTHORITY\NetworkService")
Function CheckExclusions (ByVal strVal)
Dim i
For i = LBound (arrExclude) To UBound (arrExclude)
If LCase (strVal) = LCase (arrExclude (i)) Then
CheckExclusions = True
Exit Function
End If
Next
CheckExclusions = False
End Function
Sub CheckServicesOnComputer (ByVal strComputer)
Dim objWMIService
Dim colItems, objItem
Dim iExcluded, iIncluded
iExcluded = 0
iIncluded = 0
WScript.Echo ""
WScript.Echo "Checking computer " & strComputer
On Error Resume Next
Set objWMIService = GetObject ("winmgmts:\\" & strComputer & "\root\CIMV2")
If ErrorReport ("opening CIMv2") Then Exit Sub
Set colItems = objWMIService.ExecQuery ("SELECT name,startname,caption FROM Win32_Service", "WQL", _
wbemFlagReturnImmediately + wbemFlagForwardOnly)
If ErrorReport ("on ExecQuery") Then Exit Sub
On Error Goto 0
' if we get any items returned, it's installed
For Each objItem In colItems
If CheckExclusions (objItem.StartName) Then
iExcluded = iExcluded + 1
Else
iIncluded = iIncluded + 1
If Right (LCase (objItem.StartName), Len ("\Administrator")) = "\administrator" Then iAdminCount = iAdminCount + 1
'wscript.echo "name = " & objItem.Name & " startname = " & objItem.StartName & " caption = " & objItem.Caption
e " startname = " & objItem.StartName & " caption = " & objItem.Caption
End If
Next
Set colItems = Nothing
Set objWMIService = Nothing
Wscript.echo "Included items = " & iIncluded & " excluded items = " & iExcluded & " for computer " & strComputer
iTot = iTot + iIncluded
End Sub
' Main
Call Startup
Do Until objFileIn.AtEndOfStream
strRemoteComputer = objFileIn.ReadLine
If ErrorReport ("while reading input line") Then
Exit Do
End If
' If the first character is a "#", then the line is a comment
If Left (strRemoteComputer, 1) <> "#" Then
Call CheckServicesOnComputer (strRemoteComputer)
iCount = iCount + 1
Else
iComment = iComment + 1
End If
Loop
Call Shutdown
e " "
e "Processing complete"
e "Total computers processed: " & iCount
e "Total Administrator services: " & iAdminCount
e "Total special services: " & iTot
e "Total errors: " & iError
e "Total comment lines: " & iComment