30 November 2015

Local Administrator Report

The firm I work at does not give users local administrator access for several reasons. We did an audit of our systems and found out several users had local administrator privileges that should not have. In order to keep track of all systems all of the time, I wrote the following two PowerShell scripts to report systems in which a user is part of the administrators group.

This is a two step process, using SCCM Application deployment. The first step is to use a custom detection method written in PowerShell. The detection script queries the local administrator group of the system it is being executed on. It excludes members in the $MemberExclusions and systems in the $SystemExclusions arrays. I hard coded the exclusions in the detection script so that I can go right in there and directly add users and systems as needed. When you add a system to the application detection method, you also need to add the system to the exclusions.txt file. If there are no users in the administrators group, then the application detection script will return an "installed" status back to SCCM. If there are additional users in the group, besides the excluded, then the script will return a "not installed" message back to SCCM.

The only portion of the LocalAdministratorsDetection.ps1 file you need to modify are lines 19, 26, and 27. 

When a "not installed" message is returned back, which is an exit code 0, SCCM will now execute the LocalAdministrators.ps1 script to "install" the application. I wanted to have emails generated when this script executes, so I had to find a way to execute the script with a domain account, instead of the normal system account. This was achieved by placing a copy of psexec.exe in the same folder as the localadministrators.ps1 file exists. Now the way to set this up is to create a normal application deployment in SCCM 2012. As you setup the deployment types, under the Programs tab, you will need to use the following command line:

psexec.exe \\%COMPUTERNAME% -u <domain>\<domain account> -p <password> -h cmd.exe /c "echo . | powershell.exe -executionpolicy bypass -file \\<Directory>\LocalAdministrators.ps1"

The only parts of the psexec.exe command line you need to customize for your environment will be those highlighted in bold. This command line executes the powershell script using the specified domain account. The %COMPUTERNAME% grabs the computer name of the system it is being executed on.

The LocalAdministrators.ps1 script will now get a list of all users in the administrators group that are not excluded in the exclusions.txt file, which also exists in the same directory as the .ps1 file. You will need to create a file called EmailAddresses.txt, which will have a list of email addresses that you want to be emailed a report. You also need to create an exclusions.txt file. This will have a list of systems to exclude from the query. The only parts of the localadministrators.ps1 file you need to customize are Lines 27, 28, 77, and 83. At the end of the script, it will send out an email to all addresses in the EmailAddresses.txt file. Finally, it renames the file LocalAdministrators.log to LocalAdministrators_Emailed.log. When the application detection is rerun, it will see the _Emailed in the filename and return a success if there are extra users in the local administrator group. If there are no extra users in the group and that file exists, then the application detection method will delete the .log file. 

You can download the LocalAdministrators.ps1 script from here.
You can download the LocalAdministratorsDetection.ps1 script from here.

1:  <#       
2:       .NOTES  
3:       ===========================================================================  
4:        Created with:      SAPIEN Technologies, Inc., PowerShell Studio 2015 v4.2.98  
5:        Created on:       11/23/2015 1:14 PM  
6:        Created by:       Mick Pletcher  
7:        Organization:         
8:        Filename:        LocalAdministrators.ps1  
9:       ===========================================================================  
10:       .DESCRIPTION  
11:            This script will open query the local administrators group. It generates  
12:            a log file if there are users in the local administrators group that are  
13:            not in the exclusions group. A .log file is written to the local HDD. The  
14:            script then returns a error code 0 back to SCCM, which will initiate a   
15:            software deployment. At that point, the secondary script will email  
16:            the .log file to the appropriate users. That script then deletes the  
17:            .log file which will then create a successful   
18:  #>  
20:  #Declare Global Variables  
21:  Set-Variable -Name Body -Force  
22:  Set-Variable -Name EmailAddress -Force  
23:  Set-Variable -Name EmailAddresses -Force  
24:  Set-Variable -Name Exclusions -Force  
25:  Set-Variable -Name LocalAdmin -Force  
26:  Set-Variable -Name LocalAdmins -Force  
27:  Set-Variable -Name LogFile -Value $env:windir"\Logs\LocalAdministrators.log" -Force  
28:  Set-Variable -Name LogFileEmailed -Value $env:windir"\Logs\LocalAdministrators_Emailed.log" -Force  
29:  Set-Variable -Name Member -Force  
30:  Set-Variable -Name Members -Force  
31:  Set-Variable -Name Output -Force  
32:  Set-Variable -Name Prof -Force  
33:  Set-Variable -Name Profiles -Force  
34:  Set-Variable -Name RelativePath -Force  
36:  cls  
37:  $RelativePath = (split-path $SCRIPT:MyInvocation.MyCommand.Path -parent) + "\"  
38:  $Body = "Local Administrator(s)" + [char]13 + "---------------------------" + [char]13  
39:  $EmailAddresses = @()  
40:  $EmailAddresses = Get-Content -Path $RelativePath"EmailAddresses.txt"  
41:  $LocalAdmins = @()  
42:  $Members = net localgroup administrators | where { $_ -AND $_ -notmatch "command completed successfully" } | select -skip 4  
43:  $Profiles = Get-ChildItem -Path $env:SystemDrive"\users" -Force  
44:  $Exclusions = Get-Content -Path $RelativePath"Exclusions.txt"  
45:  Foreach ($Member in $Members) {  
46:       $Member = $Member.Split("\")  
47:       If ($Member.Count -gt 1) {  
48:            [string]$Member = $Member[1]  
49:            If ($Member -notin $Exclusions) {  
50:                 Foreach ($Prof in $Profiles) {  
51:                      If ($Member -eq $Prof) {  
52:                           $LocalAdmins += $Member  
53:                      }  
54:                 }  
55:            }  
56:       }  
57:       Remove-Variable -Name Member  
58:  }  
59:  if ((Test-Path $LogFileEmailed) -eq $true) {  
60:       Remove-Item -Path $LogFileEmailed -Force  
61:  }  
62:  if ((Test-Path $LogFile) -eq $true) {  
63:       Remove-Item -Path $LogFile -Force  
64:  }  
65:  if ($LocalAdmins.Count -gt 0) {  
66:       if ((Test-Path $LogFile) -eq $false) {  
67:            New-Item -Path $LogFile -ItemType file -Force  
68:       }  
69:       foreach ($LocalAdmin in $LocalAdmins) {  
70:            Add-Content -Path $LogFile -Value $LocalAdmin -Force  
71:            $Body = $Body + $LocalAdmin + [char]13  
72:       }  
73:  }  
74:  If ($LocalAdmins.count -eq 1) {  
75:       $Output = $LocalAdmin + [char]32 + "is a local administrator on" + [char]32 + $env:COMPUTERNAME  
76:       foreach ($EmailAddress in $EmailAddresses) {  
77:            Send-MailMessage -To $EmailAddress -From "IT@acme.com" -Subject "Local Administrator Report" -Body $Output -SmtpServer "smtp.acme.com"  
78:       }  
79:       Rename-Item -Path $LogFile -NewName $LogFileEmailed -Force  
80:  } else {  
81:       $Output = "The attached file lists all local administrators on" + [char]32 + $env:COMPUTERNAME  
82:       foreach ($EmailAddress in $EmailAddresses) {  
83:            Send-MailMessage -To $EmailAddress -From "IT@acme.com" -Subject "Local Administrator Report" -Body $Output -Attachments $LogFile -SmtpServer "smtp.acme.com"  
84:       }  
85:       Rename-Item -Path $LogFile -NewName $LogFileEmailed -Force  
86:  }  
87:  $LocalAdmins = $null  
89:  #Cleanup Global Variables  
90:  Remove-Variable -Name Body -Force  
91:  Remove-Variable -Name EmailAddress -Force  
92:  Remove-Variable -Name EmailAddresses -Force  
93:  Remove-Variable -Name Exclusions -Force  
94:  Remove-Variable -Name LocalAdmin -Force  
95:  Remove-Variable -Name LocalAdmins -Force  
96:  Remove-Variable -Name LogFile -Force  
97:  Remove-Variable -Name LogFileEmailed -Force  
98:  Remove-Variable -Name Members -Force  
99:  Remove-Variable -Name Output -Force  
100:  Remove-Variable -Name Prof -Force  
101:  Remove-Variable -Name Profiles -Force  

1:  <#       
2:       .NOTES  
3:       ===========================================================================  
4:        Created with:      SAPIEN Technologies, Inc., PowerShell Studio 2015 v4.2.98  
5:        Created on:       11/23/2015 1:14 PM  
6:        Created by:       Mick Pletcher  
7:        Organization:         
8:        Filename:        LocalAdministratorsDetectionMethod.ps1  
9:       ===========================================================================  
10:       .DESCRIPTION  
11:            This script will query the local administrators group. It will return a  
12:            success to SCCM if there are no members in the local administrators   
13:            group or if a system is in the SystemExclusions array or a user is   
14:            in the MemberExclusions variable.   
15:  #>  
17:  #Declare Global Variables  
18:  Set-Variable -Name LocalAdmins -Force  
19:  Set-Variable -Name LogFile -Value $env:windir"\Logs\LocalAdministrators_Emailed.log" -Force  
20:  Set-Variable -Name Member -Force  
21:  Set-Variable -Name MemberExclusions -Force  
22:  Set-Variable -Name Members -Force  
23:  Set-Variable -Name SystemExclusions -Force  
25:  cls  
26:  $MemberExclusions = @("Domain Admins","Workstation Admins")  
27:  $SystemExclusions = @("SYSTEM01")  
28:  $LocalAdmins = @()  
29:  $Members = net localgroup administrators | where { $_ -AND $_ -notmatch "command completed successfully" } | select -skip 4  
30:  $Profiles = Get-ChildItem -Path $env:SystemDrive"\users" -Force  
31:  Foreach ($Member in $Members) {  
32:       $Member = $Member.Split("\")  
33:       If ($Member.Count -gt 1) {  
34:            [string]$Member = $Member[1]  
35:            If ($Member -notin $MemberExclusions) {  
36:                 $LocalAdmins += $Member  
37:            }  
38:       }  
39:       Remove-Variable -Name Member  
40:  }  
41:  if (($LocalAdmins.Count -eq 0) -and ((Test-Path -Path $LogFile) -eq $true)) {  
42:       Remove-Item -Path $LogFile -Force  
43:  }  
44:  if (($LocalAdmins.Count -gt 0) -and ($env:COMPUTERNAME -notin $SystemExclusions) -and ((Test-Path -Path $LogFile) -eq $false )) {  
45:       Start-Sleep -Seconds 5  
46:       exit 0  
47:  } else {  
48:       Write-Host "No Local Administrators"  
49:       Start-Sleep -Seconds 5  
50:       exit 0  
51:  }  
52:  $LocalAdmins = $null  
54:  #Cleanup Global Variables  
55:  Remove-Variable -Name LocalAdmins -Force  
56:  Remove-Variable -Name LogFile -Force  
57:  Remove-Variable -Name Member -Force  
58:  Remove-Variable -Name MemberExclusions -Force  
59:  Remove-Variable -Name Members -Force  
60:  Remove-Variable -Name SystemExclusions -Force  


Post a Comment