/build/static/layout/Breadcrumb_cap_w.png

Audit Local Administrators Group with SCCM

Overview

Provide a full step by step guide on how to audit members of the local Administrators group (or any other local groups at the same time) via ConfigMgr. This implementation will use a Configuration Item, deployed via a Configuration Baseline to a Collection. The heavy lifting is done with a PowerShell script.

Many thanks to the internet for providing the solution. My implementation is a merge of two ideas, and making it scalable.

To view compatibility, please go to the end of the document.


Script Credits


Guide

Prepare a computer with the WMI classes.

1. Get a copy of the script from here.
https://gist.github.com/rileyz/40ec2e8ca9c15c85ce2de70bd1f5fdea

2. Get a copy of WMI Explorer from here, you'll need this later to peer into WMI.
https://github.com/vinaypamnani/wmie2
 

On a target device with the CCM Agent installed, run the Inventory-LocalSecurityGroup.ps1 script with elevated privileges. It should run with no errors, and output data to the console via the verbose stream if enabled.

You want to make sure the the Inventory-LocalSecurityGroup.ps1 is gather the data you require. For example if you need to audit the local 'Users' group, or output the data to file, then enable and test the functions now. Warning: if you enable verbose in the script, don't forget to disable it when your done. 

Save a copy of the your modified Inventory-LocalSecurityGroup.ps1, you will need this later, to add to the Configuration Item.


Check that the information has been added to WMI by using WMI Explorer. If you see data in the Instances panel ( in the red box), then you are good to go.

 

SCCM Configuration Item & Configuration Baseline Implementation

1. Extend the CCM Agent Hardware Inventory by opening the SCCM Console and navigating to "Administration > Overview > Client Settings".  I would recommend you extend the Hardware Inventory on the "Default Client Settings" but leave it unchecked, and then enabling them on another Client Setting to enable testing.

Extend Hardware Inventory on "Default Client Settings" with the details below.

Default Settings
Click Hardware Inventory and then Set Classes.
z+SjgNGfcQERgAAAABJRU5ErkJggg==

Hardware Inventory Classes
Click Add.
Bx6O3hZT2O0wAAAAAElFTkSuQmCC

Add Hardware Inventory Class
Connect to the target device where we ran the Inventory-LocalSecurityGroup.ps1 script. Once connected, find and check LocalSecurityGroup Class Name.  Click Edit and double check the Class qualifiers.
wMz10lCSdfChQAAAABJRU5ErkJggg==

Class Qualifiers
Ensure the Property PrimaryKey should be checked, like the image below. Normally the Domain, LocalSecurity, PrimaryKey and SID will be checked by also default.

Once checked, click OK to the dialogs to get back to the SCCM console and then enable the inventory class on the desired Custom Device Setting for testing.

If this is not the case then you will need to export the MOF file, edit the keys so at least the PrimaryKey is set as the Key and then import the updated MOF.  This is to ensure there is a unique identifier in the database for the line item, otherwise you will have missing data in SCCM.

Mick's solution worked in SCCM 2016, but something has change in the newer versions of SCCM. As noted on his blogs comments section, the reporting is not correct.9WXGZ3L78y+eJvx35GTH67P9bjPzyFfG6OUJ+8vmvXOivjH39DhUlCDAYDAaDFQqFwv8PJsFc8NmUUr8AAAAASUVORK5CYII=

If editing the MOF, the edited MOF section should look like the example below once modified.
Warning: you can break inventory if you do this wrong, so keep a backup of the MOF.

[ SMS_Report (TRUE), SMS_Group_Name ("LocalSecurityGroupInventory"), SMS_Class_ID ("MICROSOFT|LOCALSECURITYGROUPINVENTORY|1.0"), Namespace ("root\\\\cimv2") ] class LocalSecurityGroupInventory : SMS_Class_Template { [ SMS_Report (TRUE), key ] String Domain; [ SMS_Report (TRUE), key ] String LocalSecurityGroup; [ SMS_Report (TRUE), key ] String PrimaryKey; [ SMS_Report (TRUE), key ] String SID; [ SMS_Report (TRUE) ] String User; };


2. Creating the Configuration Item in SCCM by opening the SCCM Console and navigating to "Assets and  Compliance > Overview > Compliance Settings > Configuration Items".

Create a new "Configuration Item" with the details below.

General
Give the Configuration Item a name like "Inventory Local Administrators into WMI", and select the Windows Desktops and Servers (custom) radio button.H3i8dFWjPveGAAAAAElFTkSuQmCC


Supported Platforms
Ensure the "Select all" check box is checked, this will ensure future Windows versions will be selected as well.
qkGyngnAAAAAElFTkSuQmCC


Settings
Click New to add our setting.
xrWtg13T1r9dlUCAXmmw1RARERHRvQQC9EqDrYaIiIiI7iUQoFcabDVEREREdC+BAL3SYKshIiIiontzgeDEiRMEAqy7BlsNEREREd2rM0BzczOBAP3QYKshIiIiontzgeDkyZMEAqy7BlsNEREREd2rM8D27dul4dSpUwQCrLsGWw0RERER3aszwI4dO6Th9OnTBAKsuwZbDRERERHdqzPAzp07peHMmTMEAqy7BlsNEREREd2rM8CuXbuk4ezZswQCrLsGWw0RERER3ZsLBOfOnSMQYN012GqIiIiI6F6dAXbv3i0NX331FYEA667BVkNERERE9+oMsHfvXmm4cOFCMIGIiIiIiNny4MGD8v8CmszDE1jYVKMAAAAASUVORK5CYII=

A new dialog will open. On the General tab, give the setting a name - in our case "Compliance Setting". Change the Setting type to Script, and the Data type to Integer. In the Discovery script section, click Edit Script and add the PowerShell script Inventory-LocalSecurityGroup.ps1.
+F6OIZCT2AAAAAElFTkSuQmCC

In the Compliance Rules tab, add the rule which detects this setting as compliant. In our case, we are just looking for a Boolean value return of true. Click New and name the rule "WMI Class Detected", set the rule type as Value, and the value returned by the specified script equals "0". Once that is complete, click OK to confirm the Setting and Rule we just created. Then OK again to get back to the main wizard.
IpoxidA8dAAAAABJRU5ErkJggg==


Settings
We should be back at the main wizard. Click Next.
Fv2lovWWIAAAAASUVORK5CYII=


Compliance Rules
You will see the Compliance Rule we just created before. Click Next.
eX5NoKudplAAAAABJRU5ErkJggg==


Summary
Click Next.
w+c+U5jVw70zgAAAABJRU5ErkJggg==


Completion
Configuration Item has now been created. Click Close.
wDQo7EFFAOtaQAAAABJRU5ErkJggg==


3. Creating the Configuration Baseline in SCCM by opening the SCCM Console and navigating to "Assets and  Compliance > Overview > Compliance Settings > Configuration Baselines".

Create a new "Configuration Baselines" with the details below.

Create Configuration Baseline
Give the Configuration baseline a name, in our case "Local Administrators Group Membership Audit". Now to add the Configuration Item Click Add > Configuration Item.
WdyQRAAAAAElFTkSuQmCC


A dialogue should open like the below, add our Configuration Item we create before from the available list of items. Click OK after the item is added, this will close the dialog  below and take you back the previous dialog above, Click OK again to close the wizard to bring you back to the SCCM console.
FxcMOAAAAAElFTkSuQmCC


 

SCCM Configuration Baselines Deployment

1. Deploy the Configuration Baseline in SCCM by opening the SCCM Console and navigating to "Assets and  Compliance > Overview > Compliance Settings > Configuration Baselines".

Deploy the Configuration Baseline with the details below.

In the SCCM console, find the Configuration Baseline you created before, right click the item and select Deploy.
Uo4nDXnHPAAAAAABJRU5ErkJggg==

 

Select the Configuration Baseline from the left options list, and Add the item to the right list. Once that is added, select the Collection to target. The schedule can also be adjusted to how often you would like the evaluation to be run. Click OK to deploy the Configuration Baseline - this is no confirmation dialog, it will deployed at this point.weh8fVUIkT6oQAAAABJRU5ErkJggg==


2. Monitoring once it has been deployed. You can monitor the deployment via "Monitoring > Overview > Deployments" and searching for your Configuration Baseline. Your compliant and non-compliant devices can be found here, or you can create a report.

Just to note, non-compliant devices are Local Security Groups which have orphaned SIDs. The orphaned SIDs cause the Get-LocalGroupMember cmdlet to error, a ADSI workaround was implemented to gather the members, the drawback was the SID could not be gathered correctly from cross domain members of the Local Security Group where Foreign Security Principals with the same username exists in the current domain due to the SIDHistory. Ie it would return the Foreign Security Principal SID from the current domain, rather than original cross forest domain. This was our edge case situation, for most people this should not be an issue as you will normally be in a single domain.


System Center Configuration Manager - Resource Explorer

Check Configuration Baselines is working and reporting. Go to your SCCM Collection and view the computer objects in the collection. Right click and start Resource Explorer. If everything is working correctly, you should see the inventory data like below, for your computer object. Having this data in the inventory means you can also report on this data.f8BlFK44nNMiQ0AAAAASUVORK5CYII=


SCCM Reporting with Reporting Services

Work in progress, coming soon!
 
But for now you can use Mick's query solution. In the SCCM Console and navigate to "Monitoring > Overview > Queries".  Then Create Query, Edit Query Statement, then Show Query Language.  Now paste in the WQL statement below, and OK to the dialogues to get back to the SCCM console. All done, view your report!

select 
	SMS_R_System.Name, SMS_G_System_LOCALSECURITYGROUPINVENTORY.Domain, 
	SMS_G_System_LOCALSECURITYGROUPINVENTORY.User,
	SMS_G_System_LOCALSECURITYGROUPINVENTORY.SID
from  
	SMS_R_System inner 
join 
	SMS_G_System_LOCALSECURITYGROUPINVENTORY 
on 
	SMS_G_System_LOCALSECURITYGROUPINVENTORY.ResourceID = SMS_R_System.ResourceId 
order by 
	SMS_R_System.Name, SMS_G_System_LOCALSECURITYGROUPINVENTORY.Domain, 
        SMS_G_System_LOCALSECURITYGROUPINVENTORY.User


Compatibility

SCCM

  • Tested on SCCM 1906 (25/03/2020).

Windows

  • Windows 10 1903
  • Windows Server 2016
  • Windows Server 2012 R2
  • Windows Server 2008 R2


Edit Log

25/03/2020: Initial release.
25/03/2020: Article re-formatting, copy/paste from OneNote was not ideal 
09/04/2020: Updated the query, so it pulls the SID information too.


Comments

  • Thanks, exactly what I was looking for. I am curious about the Reports ;) - Mela 2 years ago
  • We translate it ;)

    select
    vSMS_R_System.Name0, v_GS_LOCALSECURITYGROUPINVENTORY.Domain0,
    v_GS_LOCALSECURITYGROUPINVENTORY.User0,
    v_GS_LOCALSECURITYGROUPINVENTORY.SID0
    from
    vSMS_R_System inner
    join
    v_GS_LOCALSECURITYGROUPINVENTORY
    on
    v_GS_LOCALSECURITYGROUPINVENTORY.ResourceID = vSMS_R_System.ItemKey
    order by
    vSMS_R_System.Name0, v_GS_LOCALSECURITYGROUPINVENTORY.Domain0,
    v_GS_LOCALSECURITYGROUPINVENTORY.User0 - Mela 2 years ago
  • Many thanks for your script. However when using the 'Legacy method' in your script to get the users you just put the "SID" as unknown.

    If you replace your code with this, it will also resolve the SID when falling back to the legacy method.

    if ($Error.Count -ne 0) {
    Write-Verbose 'Using legacy method for backwards compatibility.'

    $Group = [ADSI]"WinNT://localhost/$LocalSecuirtyGroup"
    $Members = @($group.psbase.Invoke("Members"))

    $members | ForEach-Object {
    $name = $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)
    $path = $_.GetType().InvokeMember("ADsPath", 'GetProperty', $null, $_, $null)

    #substract the proper domain name or set it as BUILTIN
    $Domain = $path -replace "WinNT://","" -replace "/$name",""


    #find the SID of the user or group
    $user = New-Object System.Security.Principal.NTAccount($name)
    $sid = $user.Translate([System.Security.Principal.SecurityIdentifier])



    $LocalInventory += $i++ | select @{Label='PrimaryKey'; Expression={$i}},
    @{Label='SID'; Expression={$sid.Value}},
    @{Label='LocalSecurityGroup'; Expression={$LocalSecuirtyGroup}},
    @{Label='Domain'; Expression={Switch -Exact ($domain) {
    "$env:COMPUTERNAME" {'BUILTIN'}
    'WinNT:' {'Unknown'}
    default {$domain}}}},
    @{Label="User"; Expression={$name}}


    }

    } - Houdini 2 years ago
This post is locked
 
This website uses cookies. By continuing to use this site and/or clicking the "Accept" button you are providing consent Quest Software and its affiliates do NOT sell the Personal Data you provide to us either when you register on our websites or when you do business with us. For more information about our Privacy Policy and our data protection efforts, please visit GDPR-HQ