MVP Jörgen Nilsson did a great post the other day over at https://4sysops.com/archives/monitoring-laps-with-configuration-manager/ where he showcased how one could monitor LAPS with the help of CI's in ConfigMgr to make sure it's installed and running properly. Continuing on the LAPS theme and ways ConfigMgr can help us improve security and maintain control I would like to talk a little about how we can remove non authorized members of the local administrator group with the help of Configuration Items/Baselines in ConfigMgr.

For those who are unfamiliar with LAPS (Local administrator password solution) you can learn more here:

https://technet.microsoft.com/en-us/mt227395.aspx

The issue

In theory a user could request for the LAPS password and have administrator rights during the time until the next evaluation cycle where the password gets reset, but during that time its possible for the user to add any user to the local administrator group so even when the LAPS password resets their own user or another user could have been added to the local administrator group.

This issue is not just related to LAPS but can of course happen regardless that an unwanted member gets added to the local administrator group.

A solution

One way to solve this issue is to make a Configuration Item in Configuration Manager that with the help of powershell checks which user accounts are located in the Local administrator group on the local machine and in the same powershell script you define which accounts should be there and then you use a remediation script to delete any user account that's not predefined to be there and thus you make sure only the accounts that should have local administrator access has it.

Discovery Script

function Get-GroupBySid () { param( [parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [Alias("Name")] [string]$ComputerName, [string]$GroupNameSid = "S-1-5-32-544" ) $objSID = New-Object System.Security.Principal.SecurityIdentifier($GroupNameSid) $objgroup = $objSID.Translate( [System.Security.Principal.NTAccount]) $objgroupname = ($objgroup.Value).Split("\")[1] return ,$objgroupname } $Admingroup = Get-GroupBySid -ComputerName localhost $members = net localgroup $Admingroup | where {$_ -and $_ -notmatch "command completed successfully"} | select -skip 4 $Adminaccounts = $null $Adminaccounts = @() foreach ($member in $members) { switch ($member) { "Administrator" {} "COMPANY\Administrator" {} "LocalAdmin" {} "SD010" {} default {$adminaccounts += $member} } } if ($Adminaccounts -ne $null) { $Compliance = "No" } Else { $Compliance = "Yes" } $Compliance

Remediation Script

function Get-GroupBySid () { param( [parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [Alias("Name")] [string]$ComputerName, [string]$GroupNameSid = "S-1-5-32-544" ) $objSID = New-Object System.Security.Principal.SecurityIdentifier($GroupNameSid) $objgroup = $objSID.Translate( [System.Security.Principal.NTAccount]) $objgroupname = ($objgroup.Value).Split("\")[1] return ,$objgroupname } $Admingroup = Get-GroupBySid -ComputerName localhost $members = net localgroup $Admingroup | where {$_ -and $_ -notmatch "command completed successfully"} | select -skip 4 $Adminaccounts = $null $Adminaccounts = @() foreach ($member in $members) { switch ($member) { "Administrator" {} "COMPANY\Administrator" {} "LocalAdmin" {} "SD010" {} default {$adminaccounts += $member} } } foreach ($Adminaccount in $Adminaccounts) { net localgroup administrators $Adminaccount /delete New-EventLog -Source "RemoveAdmin" -LogName "Application" -ErrorAction SilentlyContinue Write-EventLog -LogName "Application" -Source "RemoveAdmin" -Message “Removing $Adminaccount from the local Administrator group on machine $ENV:COMPUTERNAME” -EventId 10001 -EntryType information }

The Setup

First off all we need to create a new Configuration Item and give it an awesome name

Next up is to set the "Setting type" to "Script" and "Data type" to "String"

Insert the Discovery Script in to the Edit script windows that appears and remember to make sure the "Script language" is set to Powershell.

both the discovery and remediation script needs to contain the correct user that are allowed to be present in the local administrator group.

The discovery script will check that only the users specified in the script are there and if there's any exception it will kick off the remediation script and remove users that's not defined in the remediation script so make sure both scripts have the exact same users.

Next up is to create the compliance rule we need to choose "Rule type" as "value" and "The setting must comply with the following rule" set to "Equals" and "the following rule to" to be "Yes".

Meaning that if the discovery script returns "Yes" its all good and the remediation script doesn't need to run. The last important step is to check the box "Run the specified remediation script when this setting is noncompliant"

Finish up the wizard and then create a Configuration Baseline that you include this Configuration Item to and deploy it.

And when deploying the Configuration Baseline it's important to remember to check the boxes for remediation and that you have a evaluation schedule that's frequent enough.

Over at a client you can see that we have 5 members of the local administrator group which is 1 member more than specified in the CI and CB we created

As soon as the evaluation of the Configuration baseline has kicked off and initiated the script the user COMPANY\SD011 got removed from the local administrator group

and with that it the script also created an event in event viewer that an member have been removed from the group ( If you are using SCOM in your environment you can have this monitored)

This was just an example on how one can go about removing unwanted members from the local admin group and there are many ways one can expand on this.

Feel free to leave any comments and questions below,

You can also find me over at www.timmyit.com and don't forget to follow me on twitter https://twitter.com/TimmyITdotcom

Until next time, Cheers !

//Timmy Andersson