The problem and thought behind it
We are currently looking at ways to keep a tighter hold over client workstations and the administrative rights a user has over it. One thing we are starting with is who is an administrator on a machine.
When a person owns their PC, they are the sole administrator so can do whatever they want as it is theirs to do with. In the corporate environment, people expect to have administrative control on devices, even though it’s not necessary for their role. A user may have been given admin privileges over their corporate computer by the internal IT as a quick fix to an issue, as they are a VIP user in the company or maybe it was meant to be removed by never did.
It maybe that the company wants managers to have administrative control over their team’s workstations for simple tasks (software install, driver updates ect). This is a problem that is seen a lot when internal administrators make changes to a device to quickly solve an issue, but not the long term fix.
These rights are handed out gradually as they are wanted and with very little thought on the security implications or reporting.
This is being reduced with technology like PIM or LAPS but unfortunately, users still want to have rights they don’t need – frustrating every MSP technician!
The concept and the outcome
I have created created a RMM component to run a script, to control this. The job takes note of all users under the local administrator group and write the output to a UDF under the target device in RMM. The output is a list of users that have administrative rights over the workstation.
This process will then give the client visibility of devices and the administrators, which can then be adjusted if it’s not needed.
Local administrators need to be controlled because if an end user account gets breached and the account has administrator privileges over other devices, it will significantly easier access, adjust and impact the workstation. It may also be that the end user begin to use the workstation for personal uses and want to install software that’s not controlled by an MDMs such as Intune.
This only gives a list of who currently has access to the device and audits the output.
The purpose of the MSP is to support the end user and not to make assumptions and changes to devices, without consulting, agreeing and planning with the approved technical contacts. When changes are made with the best intentions, the end user can see it as the IT getting too involved and disruptive. The script created only gives a list, which the account manager can pass to the user and have them made the choice.
How it works
The first step of the process, the script needs the machine name, users that you want excluded such as your approved administrator account, and the members of the administrators group. The below example is adding the domain account tomw.admin along with the two local administrator accounts to excludedUsers variable.
This is a adjustable list that can be changed as the client requires it.
# Get the local computer name
$computerName = $env:COMPUTERNAME
# Try to get the domain name; fallback to computer name if not domain-joined
try {
$domainName = ([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().Name)
} catch {
$domainName = $computerName
}
# Define users to exclude (both static and dynamic)
$excludedUsers = @(
"$domainName\tomw.admin",
"$computerName\administrator",
"$computerName\NTXAdmin"
)
# Get the local Administrators group
$adminGroup = [ADSI]"WinNT://./Administrators,group"
# Get the members of the Administrators group
$members = @($adminGroup.psbase.Invoke("Members") | ForEach-Object {
$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)
})
The next step filters out the Windows built in users or orphaned accounts that start with S-1-12-1- and the users listed in the excludedUsers variable listed above. This means that only active users are listed.
# Convert SIDs to display names
$displayNames = @()
foreach ($member in $members) {
try {
$sid = New-Object System.Security.Principal.SecurityIdentifier($member)
$account = $sid.Translate([System.Security.Principal.NTAccount])
$displayNames += $account.Value
} catch {
# If the member is not a SID, use the original name
$displayNames += $member
}
}
# Filter out display names that contain 'S-1-12-1-' and any in the exclusion list
$filteredDisplayNames = $displayNames | Where-Object {
$_ -notmatch 'S-1-12-1-' -and ($excludedUsers -notcontains $_)
}
Now that the information has been gathered and formatted correctly, the file step is to get the info and add it to a variable on the device, using RMM. This then writes it onto the RMM portal against the machine.
# Write the members of the Administrators group to the specified UDF
$UDFSelection = $env:UDFSelection
$UDFOutput = $filteredDisplayNames -join ", "
# Write to RMM
REG ADD HKEY_LOCAL_MACHINE\SOFTWARE\CentraStage /v Custom11 /t REG_SZ /d $UDFOutput /f
# Confirm output
Write-Output "Members of the Administrators group have been written to $env:UDFSelection"
How it looks
The process presents a simple list of all users in the local administrators group, that can then be presented to the client and for them to decide on. Obviously, the account manager will express the concerns and dangers but at the end of the day, it’s up to the end user.


Conclusion
This component gives the RMM users an over view of who’s got local administrator rights on a machine. Controlling these rights whilst not impacting at a company level, it takes one machine to get breached and the attackers are in. Keeping these rights under lockdown reduces the blast radius and other devices that they could impact.
There’s also a simple Powershell script that can be ran to list the end users that aren’t wanted, loop through the machine and remove them from the local administrators.
# Define the list of users to remove
$UsersToRemove = @(
"DOMAIN\username1",
"COMPUTERNAME\username2"
)
# Get the local Administrators group
try {
$adminGroup = [ADSI]"WinNT://./Administrators,group"
} catch {
Write-Error "Failed to access the Administrators group."
exit 1
}
foreach ($user in $UsersToRemove) {
try {
# Convert to WinNT format (replace backslash with slash)
$userPath = "WinNT://" + $user.Replace('\', '/')
$adminGroup.Remove($userPath)
Write-Output "Removed $user from the Administrators group."
} catch {
Write-Warning "Failed to remove $user. It may not exist or is not a member of the group."
}
}
This could be built into RMM and used on an ad-hoc basis, as the requirements of the business changes.