Event Trigger - phbits/WebsiteFailedLogins GitHub Wiki
Taking action on an alert using Event Triggers is used when alerts are written to the Windows Event Log. This can useful for stand-alone systems or environments leveraging Windows Event Collection (WEC).
[Alert]
Method = WinEvent
[Alert]
Method = WinEvent,Smtp
Setting this up is a two-part process that will be explained further below. Note that this process will need to be completed twice. Once for FailedLoginsPerIPEventId
and again for TotalFailedLoginsEventId
.
- Setup Event Trigger
- Create Action Script
The following PowerShell snippet will create an Event Trigger. The same can be achieved by using the command-line utility SCHTASKS
or via the User Interface (UI) taskschd.msc
.
Information needed to complete this script include:
- Name of script this trigger should call.
- User account this trigger should runas. This account will also be used to run the script mentioned above.
- Working directory.
- WinEvent settings from WebsiteFailedLogins configuration file.
# ExecutionPolicy set to Unrestricted should only be used for testing.
# Specify the name of the script by replacing Application-EventID10.ps1
# update working directory to reflect your environment
$Action = New-ScheduledTaskAction -Execute 'C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe' `
-Argument -NoLogo -NoProfile -NonInteractive -WindowStyle Hidden `
-File .\Application-EventID10.ps1 -RecordID $(eventRecordID) `
-ExecutionPolicy Unrestricted' `
-WorkingDirectory 'C:\WebsiteFailedLogins\'
# Specify the user account to run this task and the script it calls.
$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
$cimTriggerClass = Get-CimClass -ClassName MSFT_TaskEventTrigger `
-Namespace Root/Microsoft/Windows/TaskScheduler:MSFT_TaskEventTrigger
$Trigger = New-CimInstance -CimClass $cimTriggerClass -ClientOnly
# update the following XPath query with values used in the WebsiteFailedLogins configuration file
$Trigger.Subscription = "<QueryList><Query Id=`"0`" Path=`"Application`"><Select Path=`"Application`">*[System[Provider[@Name='WebsiteFailedLogins'] and (EventID=10)]]</Select></Query></QueryList>"
$Trigger.ExecutionTimeLimit = 'PT5M'
$Trigger.Enabled = $TRUE
# Setting ValueQueries enables RecordID to 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'
# Update as desired: TaskName, Description, TaskPath
Register-ScheduledTask -TaskName 'ApplicationEventID10-W3SVC1' `
-Description 'Run script on Application Event 10' `
-TaskPath '\WebsiteFailedLogins\' `
-Action $Action `
-Trigger $Trigger `
-Settings $Settings `
-Principal $Principal
param([int]$RecordID)
# If writing to an Event Log other than Application
# update the following $xmlQuery
$xmlQuery = @"
<QueryList>
<Query Id="0" Path="Application">
<Select Path="Application">*
[System[(EventRecordID=$($RecordID))]]
</Select>
</Query>
</QueryList>
"@
$alertEvent = Get-WinEvent -FilterXml $xmlQuery
# uncomment if DataType = xml
# $alertData = [System.Management.Automation.PSSerializer]::Deserialize($alertEvent.Message)
# uncomment if DataType = json
# $alertData = $alertEvent.Message | ConvertFrom-Json
<#
# following is how to access the data.
# UrlPath only available when Authentication=Forms
$alertData.ClientIP # 10.0.0.11
$alertData.FailedLogins # 20
$alertData.Sitename # W3SVC1
$alertData.IISLogPath # C:\inetpub\logs\LogFiles\W3SVC\
$alertData.Authentication # Forms
$alertData.HttpResponse # 401
$alertData.UrlPath # /login.aspx
$alertData.Start # 2021-01-26T18:17:51Z
# End must be used with quotes due to "~"
$alertData.'End~' # 2021-01-26T18:22:51Z
#>
# do something with $alertData here