#Region Header
#======================================================================================
#
File Name : Audit-And-Purge-LocalAdmins.ps1
#
Original Author : Kenneth C. Mazie (kcmjr AT kcmjr.com)
#
:
#
Description : Used to audit and manage the local administrators group on domain
computers.
#
:
#
Notes : Original version rewritten for more reliable operation and better
reporting.
#
: Make sure to update all variables before running. Output is only to the
console.
#
:
#
Arguments : 4 pipeline command argument options exist:
#
: -Report <mode> Mode must be "brief"
"verbose", or "none". Defaults to "brief"
#
: -Debug If included enables test
mode. Defaults to $false if left off.
#
: -Add If included will
add any user ID in the "ValidAdmins"
#
:
array to local admin group on domain systems.
#
: -Remove If included will remove any user
ID in the "BadUserNames"
#
:
hash table from the local admins group on domain systems.
#
: Any combination of options can be included at once.
#
:
#
Warnings : Be carefull not to delete important accounts (like your own)!!
#
:
#
Legal : Public Domain. Modify and redistribute freely. No rights reserved.
#
: SCRIPT PROVIDED "AS IS" WITHOUT WARRANTIES OR GUARANTEES OF
#
: ANY KIND. USE AT YOUR OWN RISK. NO TECHNICAL SUPPORT PROVIDED.
#
:
#
Credits : Code snippets and/or ideas came from many sources including but
#
: not limited to the following:
#
:
#
Last Update by : Kenneth C. Mazie
#
Version History : v1.0 - 02-19-14 - Original
#
Change History : v1.1 - 04-03-14 - Misc edits
#
: v2.0 - 05-15-14 - MAJOR rewrite. Altered all process flows.
Altered
#
: input file format.
#
:
#=======================================================================================
#EndRegion
Param (
[switch]$Debug,
[switch]$Add,
[switch]$Remove,
$Report = "brief"
)
Clear-Host
$ErrorActionPreference = "silentlycontinue"
$Domain = "mydomain"
$TestPC = "test-machine"
Try{if (!(Get-Module -Name ActiveDirectory)){Import-Module ActiveDirectory}}
Catch{[void][System.Windows.Forms.MessageBox]::Show("The Active Directory
PowerShell module was not found and is required. Exiting" , "Error");Break}
function ListAdministrators
{$members = $Group.psbase.invoke("Members") | %{$_.GetType().InvokeMember("Name",'GetProperty',$null,$_,$null)}
#$members
return $members}
$ValidAdmins = @{ #--[ Hash table of valid
local admins ]--
1="enterprise
admins";
2="domain admins";
3="administrator";
4="user1"
}
$NewAdmins = @() #--[ Array of new admins to
add ]--
$NewAdmins += "testuser"
$BadUserNames = @{ #--[ Hash table of users to
remove from local admins group ]--
1="testuser";
2="bob";
3="jim";
4="dan"
}
Write-Host "Processing domain
membership..." -ForegroundColor Yellow
If ($Debug){$Computers = @($TestPC)}Else{$Computers = Get-ADComputer -Filter {OperatingSystem -Like "*Windows*"} -Property * | select name}
$Count = $Computers.count
foreach ($Computer in $Computers){
$List = "";$Target = "";$Group = ""
If ($Debug){$Computer = $Computer}Else{$Computer = $Computer.name}
Write-Host "`nTarget =
$Computer ("($Count-1)" remaining )" -ForegroundColor Cyan
if ($Computer -like "*ESX*"){ #--[ One off bypass ]--
Write-Host "BYPASSING "$Computer -ForegroundColor Magenta
}Else{
#--[
Check if computer is accessible, if not go to next computer in list ]--
if (Test-Connection -ComputerName $Computer -Count 1 -ErrorAction SilentlyContinue){
$Target = [ADSI]("WinNT://" + $Computer + ",computer")
$Group = $Target.psbase.children.find("administrators") #--[ Select the local
admins group ]--
$List = ListAdministrators #--[ Get the members of the
administrators group via ADSI ]--
#--[ Alternately get list of users in local admin group with WMI
]--
# $List =
Get-WmiObject -computername $computer -Class win32_GROUPUSER -ErrorAction
SilentlyContinue | WHERE {$_.groupcomponent -match 'administrators' } | foreach
{[wmi]$_.partcomponent }
ForEach ($User in $List){
$User = $User.TrimStart().ToLower()
If ($Report -ne ""){
If ($Report -eq "brief"){} #Write-Host " "$User -ForegroundColor Gray
} #--[ Just report changes, or
optionally all entries ]--
If ($Report -eq "verbose"){
#--[
Report results against valid user list ]--
If ($ValidAdmins.ContainsValue($User)){
Write-Host "
AUTHORIZED admin ""$User"" detected..." -ForegroundColor Green
}Else{
If ($User.substring(0,8) -eq "S-1-5-21"){ #--[ Name is an orphaned
SID ]--
Write-Host "
ORPHANED SID Please Remove Manually... $User" -ForegroundColor Yellow
}Else{
If ($Remove){
Write-Host "
UNAUTHORIZED admin ""$User"" detected..." -ForegroundColor Red
}Else{
Write-Host " UNEXPECTED admin
""$User"" detected..." -ForegroundColor White
}
}
}
}
}
#--[
Remove the user ]----------------------------------------------
If ($Remove){
If ($BadUserNames.ContainsValue($User)){
Write-Host "
--- Attempting to remove ""$User""..." -ForegroundColor Red
$Group.Remove("WinNT://" + $Target + "/" + $User)
$VerifyList = ListAdministrators
If ($VerifyList -contains $User){
Write-Host "
--- Verification failed. Retrying as
""$Domain\$User""..." -ForegroundColor Red
$Group.Remove("WinNT://" + $Target + "/" + $Domain + "/" + $User)
}
$VerifyList = ListAdministrators
If ($VerifyList -contains $User){
Write-Host "
--- Re-Verification failed. Please remove ""$User""
manually ---" -ForegroundColor Red
}Else{
Write-Host " --- Verified removal of
""$User"" ---" -ForegroundColor Green
}
$Change = $true
}
}
}
#--[ Add
the user
]-------------------------------------------------
If ($Add){
ForEach ($Admin in $NewAdmins){
#
$Exists = 0
$AddList = ListAdministrators
If ($AddList -contains $Admin.ToLower()){#$Exist = 1}
#
If ($Exists -eq 0){
Write-Host " NEW
ADMIN ""$Admin"" " -ForegroundColor Gray -NoNewline
Write-Host "EXISTS... Not
Adding" -ForegroundColor Red
}Else{
Write-Host " ADDING
----> $Admin" -ForegroundColor Green
$Group.Add("WinNT://" + $Target.name + "/" + $Admin)
$Change = $true
}
}
}
}Else{
#-------------------------------------------------------------------
Write-Host " System is not reachable online..." -ForegroundColor Red
}
If ($Change){Write-Host " Redetecting admins..." -ForegroundColor Magenta; ListAdministrators; $Change=$false}
}
$Count --
}
Write-host "`nCompleted...
" -ForegroundColor Yellow
-----------------------------------------------------------------------------------
---------------------
Below is the original version -------------------------
-----------------------------------------------------------------------------------
#Region Header
<#======================================================================================
File Name : AuditLocalAdmins.ps1
Original Author : Kenneth C. Mazie (kcmjr AT kcmjr.com)
:
Description : Will examine all systems in specified domain to determine
membership
: in the local admins group.
:
Notes : Add users to ignore to the local admins filter array, otherwise
: all members will be listed. Requires Get-QADComputer from the
: Quest (now Dell) Active Directory commandlets available free at
:
http://www.quest.com/powershell/activeroles-server.aspx
:
Warnings : None
:
Legal : Public Domain. Modify and redistribute freely. No rights reserved.
: SCRIPT PROVIDED "AS IS" WITHOUT WARRANTIES OR GUARANTEES OF
: ANY KIND. USE AT YOUR OWN RISK. NO TECHNICAL SUPPORT PROVIDED.
:
Credits : None
:
Last Update by : Kenneth C. Mazie
Version History : v1.0 - 07-14-14 - Original
Change History : v1.1 - 00-00-00 -
:
=======================================================================================#>
#EndRegion
Clear-Host
$ErrorActionPreference = "silentlycontinue"
$domain = "mydomain.com"
#--[
Local admins to filter out ]--
$Administrators = @{
1="admin1";
2="admin2"
}
$Computers = Get-QADComputer | select name
$Count = $Computers.count
foreach ($Computer in $Computers){
$Computer = $Computer.name
Write-Host "`nTarget = $Computer
($Count)" -ForegroundColor Cyan
if ($Computer -eq "computer1"){ # --[ A one-off bypass
]--
Write-Host "BYPASSING "$Computer -ForegroundColor Magenta
}Else{
#--[
Check if computer is accessible, if not go to next computer in list ]--
if (Test-Connection -ComputerName $Computer -Count 1 -ErrorAction SilentlyContinue){
#--[ Get
list of users in local admin group with WMI ]--
$list = Get-WmiObject -computername $computer -Class win32_GROUPUSER -ErrorAction SilentlyContinue | WHERE {$_.groupcomponent -match 'administrators' } | foreach {[wmi]$_.partcomponent }
#--[ For
each user filter out domain admins and administrator ]--
foreach ($user in $list){
If ($Administrators.ContainsValue($user.name.tolower())){}Else{
Write-Host "
"$user.name
}
}
}Else{
Write-Host "
System is not reachable online..." -ForegroundColor Red
}
$Count --
}
}
Write-host Completed...