The post by @Leo is correct however you may run into performance issues if combing through many events. The ideal approach is to construct a filter specific for what you're looking for. Since the SID for the local administrators group is well-known (S-1-5-32-544
), the following XML filter can be used. One can copy/paste this into Event Viewer (Filter Current Log > XML) or use it with PowerShell.
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">
*[System[(EventID=4732)]]
and
*[EventData[Data[@Name='TargetSid'] and Data='S-1-5-32-544']]
</Select>
</Query>
</QueryList>
To use with PowerShell, set the XML filter to a variable and then run Get-WinEvent
.
$xmlFilter = @"
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">
*[System[(EventID=4732)]]
and
*[EventData[Data[@Name='TargetSid'] and Data='S-1-5-32-544']]
</Select>
</Query>
</QueryList>
"@
Get-WinEvent -FilterXml $xmlFilter
Alerting
If you'd like to run some custom action after the occurrence of an event like this, setting up alerts via Scheduled Tasks
is possible as I recently posted on my blog - Microsoft Event Log Alerting. Doing so requires two parts:
- Setup Scheduled Task
- Setup PowerShell Script
Scheduled Task
The following PowerShell commands will setup the Scheduled Task to only trigger when a member is added to BuiltIn\Administrators
. Note that many of these configuration settings are not available via the GUI.
# NOTE - ExecutionPolicy set to Unrestricted should only be used for testing.
$Action = New-ScheduledTaskAction -NoLogo `
-Execute "C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe" `
-NoProfile `
-NonInteractive `
-WindowStyle Hidden `
-File .\Security_4732.ps1 -RecordID $(eventRecordID) `
-ExecutionPolicy Unrestricted' `
-WorkingDirectory "C:\AlertScripts\"
$Principal = New-ScheduledTaskPrincipal -UserId "NT AUTHORITY\SYSTEM" `
-LogonType ServiceAccount
$Settings = New-ScheduledTaskSettingsSet -DisallowDemandStart `
-Compatibility Win8 `
-Hidden `
-WakeToRun `
-RunOnlyIfNetworkAvailable `
-AllowStartIfOnBatteries
$Settings.RunOnlyIfIdle = $FALSE
$Settings.ExecutionTimeLimit = "PT5M"
$Settings.StartWhenAvailable = $TRUE
$Settings.StopIfGoingOnBatteries = $FALSE
$Settings.DisallowStartOnRemoteAppSession = $FALSE
$Settings.DisallowStartIfOnBatteries = $FALSE
# Create Trigger via Security Event ID 4732 & Local Admin Group
$cimTriggerClass = Get-CimClass -ClassName MSFT_TaskEventTrigger `
-Namespace Root/Microsoft/Windows/TaskScheduler:MSFT_TaskEventTrigger
$Trigger = New-CimInstance -CimClass $cimTriggerClass -ClientOnly
$Trigger.Subscription = @"
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">
*[System[(EventID=4732)]]
and
*[EventData[Data[@Name='TargetSid'] and Data='S-1-5-32-544']]
</Select>
</Query>
</QueryList>
"@
$Trigger.ExecutionTimeLimit = 'PT5M'
$Trigger.Enabled = $TRUE
# Set ValueQueries so the RecordID can be passed to the script
$Trigger.ValueQueries = [CimInstance[]]$(Get-CimClass -ClassName MSFT_TaskNamedValue `
-Namespace Root/Microsoft/Windows/TaskScheduler:MSFT_TaskNamedValue)
$Trigger.ValueQueries[0].Name = "eventRecordID"
$Trigger.ValueQueries[0].Value = "Event/System/EventRecordID"
Register-ScheduledTask -TaskName "Security_4732" `
-Description "Run script when user is added to local administrators group." `
-TaskPath "\AlertScripts\" `
-Action $Action `
-Trigger $Trigger `
-Settings $Settings `
-Principal $Principal
PowerShell Script
With the Scheduled Task setup, save the following PowerShell code to C:\AlertScripts\Security_4732.ps1
. Be sure to customize this for use with your own email. Though really it can be customized however you'd like. Just be sure to only allowed signed scripts when deploying into production which will also require updating the Scheduled Task.
param([int]$RecordID)
$xmlQuery = @"
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">*
[System[(EventRecordID=$($RecordID))]]
</Select>
</Query>
</QueryList>
"@
$triggeredEvent = Get-WinEvent -FilterXml $xmlQuery
Send-MailMessage -To "alert@my-domain.local" -From "$($env:COMPUTERNAME)@my-domain.local" `
-SmtpServer "smtp.my-domain.local" `
-Subject "User Added to Local Administrators Group" `
-Body "RecordID: $($RecordID)`r`n$($triggeredEvent.Message)" `
-Priority High
Testing
There have been issues when trying to copy/paste XML queries. Be sure to test thoroughly as I've had seemingly correct queries not even work in Event Viewer. It wasn't until I manually retyped them that they worked again.
Documentation
Microsoft has done a much better job documenting events by providing detailed explanations. The page for this particular event can be found here:
4732(S): A member was added to a security-enabled local group.
Here you'll find the account listed under Subject: is responsible for making this request.