TIPS & TRICKS TIPS & TRICKS

Monitoring Local Administrators on Windows Hosts

It is always gratifying when one of my readers comes to me with a problem. I love challenges. This one had to do with one of my old posts surrounding Local Administrators remotely. Of course, the way to do this is via WMI. However, it doesn’t quite work the same way locally. This is because the WMI call to Win32_Group.GetRelated() returns other stuff as well. So the question posed was “how do I get the list of Local Administrators locally.” More specifically, I want to monitor the local Administrators group.

I look at this two ways. Firstly, I want to get a regular list of names in the Administrators group and secondly, I want to monitor for changes to the Administrators group during the day. Let’s start with the first one. My favorite tool for this is, of course, PowerShell. After a bit of back and forth, I came up with a script that works on both Windows Server 2012 and Windows Server 2008R2 – there is a little bit of syntax change in the Where-Object between PowerShell 2 (used on Windows Server 2008R2) and PowerShell 3 (used on Windows Server 2012 and above).

(Get-WMIObject Win32_Group | Where-Object { $_.Name –eq ‘Administrators’ }).GetRelated() | Where-Object { $_.__CLASS –eq “Win32_UserAccount” –or $_.__CLASS –eq “Win32_Group” } | Select-Object __CLASS,Caption,SID

The script-block form of Where-Object has always been available and hence is suitable here. My original script has just Where-Object Name -eq ‘Administrators’ which doesn’t work in PowerShell 2. After we have the GetRelated() information, we can search for the information we are really after – the users (which has a __CLASS of Win32_UserAccount) and the groups (which has a __CLASS of Win32_Group). Finally, we select the information we are interested in. As you are probably aware if you are a constant reader of the blog, we use SA-ModularInput-PowerShell to run our PowerShell for us. This module requires us to Select-Object the fields prior to finishing. We can now put this script into our inputs.conf file:

script = (Get-WMIObject Win32_Group | Where-Object { $_.Name –eq ‘Administrators’ }).GetRelated() | Where-Object { $_.__CLASS –eq “Win32_UserAccount” –or $_.__CLASS –eq “Win32_Group” } | Select-Object __CLASS,Caption,SID
schedule = 0 30 2 ? * *
sourcetype = PowerShell:LocalAdmins
source = PowerShell
disabled = false

[powershell2://LocalAdmins]
script = (Get-WMIObject Win32_Group | Where-Object { $_.Name –eq ‘Administrators’ }).GetRelated() | Where-Object { $_.__CLASS –eq “Win32_UserAccount” –or $_.__CLASS –eq “Win32_Group” } | Select-Object __CLASS,Caption,SID
schedule = 0 30 2 ? * *
sourcetype = PowerShell:LocalAdmins
source = PowerShell
disabled = false

Notice that I have two versions – one is PowerShell 2 and the other is PowerShell 3. On Windows Server 2012 and above, only PowerShell 3 is available – you have to install PowerShell 2 separately. Thus the second one doesn’t get run. On Windows Server 2008 R2 the reverse is true – you don’t get PowerShell 3 – only PowerShell 2 is installed by default. If you have standardized on PowerShell 3 already (and you really should have done so by now), only enter the first stanza. There isn’t a Common Information Model for group membership inventory, but I tend to assume there will be in the future. In keeping with the CIM, let’s define our field extractions properly and ensure there are tags. This would fall under the Inventory Data Model and be a “Group” type. Our membership can be either a Group or a UserAccount and will have a domain and a username and a security ID. Start with props.conf:

[PowerShell:LocalAdmins]
REPORT-cim = localadmins-type, localadmins-userdom, localadmins-sid

Then define the extractions in transforms.conf:

[localadmins-type]
REGEX=(?ms)__CLASS=Win32_(?<member_type>.*?)\n

[localadmins-userdmon]
REGEX=(?ms)Caption=(?<member_domain>[^\\]+)\\(?<member_name>.*?)\n

[localadmins-sid]
REGEX=(?ms)SID=(?<member_sid>.*?)\n

Finally, our tags.conf looks like this:

[sourcetype=PowerShell:LocalAdmins]
inventory = enabled
group = enabled

Now that we have our list of local administrators, how do we get the changes? The changes are recorded in the Security Windows Event Log. This is kept in the Splunk_TA_windows and I highly recommend that this is distributed with common inputs enabled – one of which is the WinEventLog://Security input. Don’t want everything? You can limit the event codes you need with a whitelist and blacklist. The relevant event codes are:

  • NT5 (Windows Server 2003 and before): 635-639
  • NT6 (Windows Server 2008 and beyond): 4731-4735

The Splunk App for Windows Infrastructure contains specific field extractions for these events, allowing you to easily incorporate them into your own dashboards. Now you can truly monitor the local Administrators group on all your servers.

Splunk
Posted by Splunk

Join the Discussion