In a perfect (admin) world all our people work happily with user level privileges and nobody ever need admin rights nowhere at anytime. This may work well in Windows environments where all devices are managed through active directory and there are interesting tools out there to help you manage these challenges.
Today I want to share a small script that might help you find out where non-standard admin rights are set in your (Windows-)network.
The solution requires at least two and a third optional step:
1. a
VBScript that is run periodically as a KACE SMA script
2. a custom inventory rule (CIR) to read the script results into your inventory
3. (optional) setup a report that gives you an overview of all non-standard machines
1. The Script
The script lists all members of the target machines’ local admin group. Since some accounts like the well-known “Administrator” should not necessarily be reported you may (and should) provide excludes for that list.The script run results are saved to the file "c:\windows\localadmins.txt". If you don’t like that path feel free to adjust it, you can replace this inside the script.
So first you need to copy and paste the following script code into a text editor (I prefer Notepad++) of your choice and save it, for example as “LocalAdministrators.vbs”:
'http://www.tech-archive.net/Archive/Scripting/microsoft.public.scripting.vbscript/2005-07/msg00832.html
Set objWshNetwork = CreateObject("WScript.Network")
strComputer = objWshNetwork.ComputerName
dim filesys
Set filesys = CreateObject("Scripting.FileSystemObject")
'recreate output-file
If filesys.FileExists("c:\windows\localadmins.txt") Then
filesys.DeleteFile "c:\windows\localadmins.txt"
End If
filesys.CreateTextFile("c:\windows\localadmins.txt"), True
' List of well know SID's is available here:
'
' Well-known security identifiers in Windows operating systems
' http://support.microsoft.com/?id=243330
strGroupSID = "S-1-5-32-544" ' Well Known SID of the Administrators group
'------------------------------------------------------------------------------
'EXCLUDE THESE ENTRYS FROM OUTPUT
'------------------------------------------------------------------------------
'For output of everything use this:
'excludes = Array()
'For excluding multiple entrys use this:
excludes = Array("Administrator","Domain-Admins")
'For excluding a single entry use this:
'excludes = Array("Administrator")
'------------------------------------------------------------------------------
' Obtain the group name based on well know SID
strGroupName = GetGroupName(strComputer, strGroupSID)
' Connect to the group
Set objGroup = GetObject("WinNT://" & strComputer & "/" & strGroupName & ",group")
' Display all member names in the group
Set filetxt = filesys.OpenTextFile("c:\windows\localadmins.txt", 8, True)
For Each objMember in objGroup.Members
output = True
If UBound(excludes) <> -1 Then
For i = LBound(excludes) To UBound(excludes)
If UCase(excludes(i)) = UCase(objMember.Name) Then output = False
Next
End If
If output = True Then
WScript.Echo objMember.Name
filetxt.WriteLine(objMember.Name)
End If
Next
filetxt.Close
Function GetGroupName(sComputer, sGroupSID)
Dim oGroupAccounts, oGroupAccount
Set oGroupAccounts = GetObject( _
"winmgmts://" & sComputer & "/root/cimv2") _
.ExecQuery("Select Name from Win32_Group" _
& " WHERE Domain = '" & sComputer & "' AND SID = '" & sGroupSID & "'")
If oGroupAccounts.Count = 0 Then
' need to use Domain = 'BUILTIN' at least for Win2k SP2
Set oGroupAccounts = GetObject( _
"winmgmts://" & sComputer & "/root/cimv2") _
.ExecQuery("Select Name from Win32_Group" _
& " WHERE Domain = 'BUILTIN' AND SID = '" & sGroupSID & "'")
End If
For Each oGroupAccount In oGroupAccounts
GetGroupName = oGroupAccount.Name
Next
End Function
Before
importing the script into your KACE SMA now define your excludes.
Find this line in the Script:
EXCLUDE THESE ENTRYS FROM OUTPUT
See the documentation there: The excludes are defined as a comma separated list of strings of all the strings you want to drop from output. You’ll find other examples for a single exclusion or no exclusions as well.
Save the script again!
Now go to the Scripting section of your KACE SMA and create a new script. Be sure to:
- Provide a nifty name for the script :)
- Script type is “Online KScript”
- DON’T FORGET TO TICK “ENABLE” AT YOUR SCRIPT AFTER TESTING! (don’t know how often I forgot that...)
- Select a bunch of machines, labels or even all devices for deployment
- Select at least one Windows OS as target “Operating Systems”
- Run as “Local System”
- Choose an appropriate schedule (I took every 24 hours)
- Enable “Allow run without a logged-in user”
- Preferably enable “Run on next connection if offline”
- Upload
your previously created script file (“LocalAdministrators.vbs”) as dependency
Inside the script you just need one single task with one single step in the “On Success”-section:
- Step type is “Launch a program...”
- “Directory”
is:
$(KACE_SYS_DIR) - “File”
is:
cscript.exe - Enable “Wait for completion”
- Disable “Visible”
- Parameters:
(include the quotation marks!)
//nologo "$(KACE_DEPENDENCY_DIR)\LocalAdministrators.vbs"
…so it should look like this in the end:
That’s
all for the script. Now save everything and test run it on a couple of
machines. You should see an appropriate output in the script run’s log file and,
of course, in the output file of the script on the local machine ("c:\windows\localadmins.txt"
if you did not change it).
2. The Custom Inventory Rule (CIR)
To attach
the generated info to the machines inventory you need to create a custom
inventory rule that allows the KACE SMA to upload the content to its database.
Here is how:
Go to your “Inventory”
and inside the “Software” section, hit the “Choose Action” button and then
click “New”.
Now fill
the “Name” field. You can enter anything meaningful you like, e.g. “Local Administrators”.
In “Supported Operating Systems” you have to select at least the Windows OS you
chose at the KScript before!
I suggest you pick all Windows Client OS in both cases.
Don’t worry, neither the script nor the custom inventory rule will eat up
performance or memory on your systems.
Most important: fill the text box “Custom Inventory Rule:” with this one:
ShellCommandTextReturn(cmd /c type C:\Windows\localadmins.txt)
All other fields are not necessary to fill for making this custom inventory rule work. Just save it now and you’re done.
After setting up this custom inventory rule you should see output like this in a machines inventory under “Software” in the “Custom Inventory Fields” section:
NOTE THAT THE KSCRIPT MUST HAVE RUN SUCCESSFULLY FIRST ON THE MACHINE(S) AND THE MACHINE(S) NEED TO DO AN INVENTORY BEFORE YOU’LL SEE DATA HERE! (Of course, you can force inventory if you want to)
3. Optional: the Report
You can define a report that will show you all non-standard systems with more local admins than you expect. This probably won’t work if you did not define any exclusions in the script above anyway.
To create that report go to the “Reporting”
section of your SMA, hit “Choose action:” and click on “New (Wizard)”.
Enter a useful name in the “Title” field and assign a fitting category.
I suggest to disable “Show Line Numbers” unless explicitly needed.
Leave “Device” selected as “Topic:” and click the “Next”-button.
In the “Fields to Display”-dialogue I just selected a few fields beside the special information we want so see, in my case that’s “System Name” and “Last Inventory” of the “Device Identity Information”-group.
Now scroll down to the “Custom Fields”-group and expand it. Select your custom inventory field you created in step 2 and continue by clicking the “Next”-button again.
Give the columns
the order you desire, I started with “System Name” (that’s nice because KACE
SMA will provide a link to that machines’ inventory!)
Continue with “Next” again.
Order the results as you want and proceed with “Next”.
Now in the “Filters” section, hit “Specify rules
to filter the records”, remove the unnecessary “Agent connection time” field
with the trash bin icon and add your custom inventory again by clicking the +
icon.
Define the operator as “is NOT NULL”, now it should look like this:
Finish and
test drive your new report!
If everything went right and your machines ran the script and at least one
inventory cycle (already mentioned in step 2) you should now get some results -
unless you don’t have any non-standard admins floating around!
One last hint: you can use the “Report Schedules” of KACE SMA to periodically investigate your network. For example, let KACE SMA email you the results of your new report as Excel sheet attached once a week.
Now happy admin-hunting :) and leave a comment
if you have any questions or suggestions about this!
https://www.itninja.com/blog/view/create-a-cir-to-get-a-clean-list-of-your-local-admins-and-then-filter-out-the-it-approved-admins-also-presented-at-dell-world-user-forum-2014-lessions-from-the-field - SMal.tmcc 5 years ago
The reason to take this slightly different approach was caused by a scenario in which the local administrators group had different localized names in a (global company) network.
I'm currently trying to add a way to exclude objects by optionally using the (well-known) SIDs instead of static strings for the same reason.
But no luck until now... - chrpetri 5 years ago
One thing I would do different is not use c:\windows for the file placement, you really do not want to create random files in the system directories.
You should use %ALLUSERSAPPDATA%\Quest\KACE\user for file placement. The rights are set correctly on this path when the client installs to do this. Putting files here makes it easier to recognize that they were created for Kace usage and not by malware gathering info. - SMal.tmcc 5 years ago
I solve the same problems with Powershell - czerp 5 years ago
So why don't you post a powershell solution blog for this if you solve the problems that way. Be glad to read it and rate it. - SMal.tmcc 5 years ago
ShellCommandTextReturn(Powershell.exe "$Computer = $env:computername; $LocalGroupName = "Administrators"; $group = [ADSI]"WinNT://$Computer/$LocalGroupName"; $members = @($group.Invoke("Members")); $members | foreach {$_[0].GetType().InvokeMember("ADSPath", 'GetProperty', $null, $_, $null)}") - czerp 5 years ago
Am I correct in assuming that the Custom Inventory Rule (CIR) that czerp posted is enough to get the data without the VB scripting? From there I just need to generate a report to pull the data from the CIR?
Thanks in advance for any responses. - Mike_Rainey 1 year ago