From f28dc90b3ef6c670a5dac6e8cd40182057f08309 Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Fri, 14 Aug 2020 12:13:07 -0400 Subject: [PATCH] Set event.outcome based on raw keyword value (#20564) Set the event.outcome value if the event contains the "audit failure" or "audit success" keywords. The `Keywords` value in the XML is a hex value where each bit can represent a keyword. So this checks if the audit success or audit failure bits are set then adds `event.outcome` as either "success" or "failure". I removed similar logic from the Security module since it is now redundant. That logic was based on string matching of the keyword name (rather than number) so it had problems when the OS language was not English. Fixes #20079 (cherry picked from commit 16ea8e2f7ced5ff1f323141ad1f8ec91037d71b8) --- CHANGELOG.next.asciidoc | 2 + winlogbeat/eventlog/eventlog.go | 12 ++++++ winlogbeat/sys/event.go | 4 +- winlogbeat/sys/event_test.go | 4 +- .../security/config/winlogbeat-security.js | 40 ------------------- 5 files changed, 18 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index 16d54c8a10d..9f59430b131 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -372,6 +372,7 @@ field. You can revert this change by configuring tags for the module and omittin *Winlogbeat* - Fix invalid IP addresses in DNS query results from Sysmon data. {issue}18432[18432] {pull}18436{18436} +- Fix `event.outcome` in the security module for non-English languages. {issue}20079[20079] {pull}20564[20564] *Functionbeat* @@ -742,6 +743,7 @@ field. You can revert this change by configuring tags for the module and omittin - Set process.command_line and process.parent.command_line from Sysmon Event ID 1. {pull}17327[17327] - Add support for event IDs 4673,4674,4697,4698,4699,4700,4701,4702,4768,4769,4770,4771,4776,4778,4779,4964 to the Security module {pull}17517[17517] - Add registry and code signature information and ECS categorization fields for sysmon module {pull}18058[18058] +- Add `event.outcome` to events based on the audit success and audit failure keywords. {pull}20564[20564] *Elastic Log Driver* - Add support for `docker logs` command {pull}19531[19531] diff --git a/winlogbeat/eventlog/eventlog.go b/winlogbeat/eventlog/eventlog.go index 468483a71d7..9302417be2e 100644 --- a/winlogbeat/eventlog/eventlog.go +++ b/winlogbeat/eventlog/eventlog.go @@ -55,6 +55,12 @@ var ( readErrors = expvar.NewMap("read_errors") ) +// Keyword Constants +const ( + keywordAuditFailure = 0x10000000000000 + keywordAuditSuccess = 0x20000000000000 +) + // EventLog is an interface to a Windows Event Log. type EventLog interface { // Open the event log. state points to the last successfully read event @@ -138,6 +144,12 @@ func (e Record) ToEvent() beat.Event { m.Put("event.created", time.Now()) + if e.KeywordsRaw&keywordAuditFailure > 0 { + m.Put("event.outcome", "failure") + } else if e.KeywordsRaw&keywordAuditSuccess > 0 { + m.Put("event.outcome", "success") + } + addOptional(m, "log.file.path", e.File) addOptional(m, "log.level", strings.ToLower(e.Level)) addOptional(m, "message", sys.RemoveWindowsLineEndings(e.Message)) diff --git a/winlogbeat/sys/event.go b/winlogbeat/sys/event.go index d88617d8925..b6674d41f40 100644 --- a/winlogbeat/sys/event.go +++ b/winlogbeat/sys/event.go @@ -235,10 +235,10 @@ func (v *HexInt64) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { return err } - num, err := strconv.ParseInt(s, 0, 64) + num, err := strconv.ParseUint(s, 0, 64) if err != nil { // Ignore invalid version values. - return nil + return err } *v = HexInt64(num) diff --git a/winlogbeat/sys/event_test.go b/winlogbeat/sys/event_test.go index 8d0f6ee04f8..d4a4d2a564d 100644 --- a/winlogbeat/sys/event_test.go +++ b/winlogbeat/sys/event_test.go @@ -37,7 +37,7 @@ const allXML = ` 4 9 0 - 0x4000000000000004 + 0x8020000000000000 100 @@ -94,7 +94,7 @@ func TestXML(t *testing.T) { EventIdentifier: EventIdentifier{ID: 91}, LevelRaw: 4, TaskRaw: 9, - KeywordsRaw: 0x4000000000000004, + KeywordsRaw: 0x8020000000000000, TimeCreated: TimeCreated{allXMLTimeCreated}, RecordID: 100, Correlation: Correlation{"{A066CCF1-8AB3-459B-B62F-F79F957A5036}", "{85FC0930-9C49-42DA-804B-A7368104BD1B}"}, diff --git a/x-pack/winlogbeat/module/security/config/winlogbeat-security.js b/x-pack/winlogbeat/module/security/config/winlogbeat-security.js index f223b8f0b8d..9a117a42f6f 100644 --- a/x-pack/winlogbeat/module/security/config/winlogbeat-security.js +++ b/x-pack/winlogbeat/module/security/config/winlogbeat-security.js @@ -21,13 +21,6 @@ var security = (function () { "11": "CachedInteractive", }; - // ECS Allowed Event Outcome - // https://www.elastic.co/guide/en/ecs/current/ecs-allowed-values-event-outcome.html - var eventOutcomes = { - "Audit Success": "success", - "Audit Failure": "failure", - }; - // User Account Control Attributes Table // https://support.microsoft.com/es-us/help/305144/how-to-use-useraccountcontrol-to-manipulate-user-account-properties var uacFlags = [ @@ -1361,18 +1354,6 @@ var security = (function () { } }; - var addEventOutcome = function(evt) { - var auditResult = evt.Get("winlog.keywords"); - if (!auditResult) { - return; - } - var eventOutcome = eventOutcomes[auditResult]; - if (eventOutcome === undefined) { - return; - } - evt.Put("event.outcome", eventOutcome); - }; - var addLogonType = function(evt) { var code = evt.Get("winlog.event_data.LogonType"); if (!code) { @@ -1699,7 +1680,6 @@ var security = (function () { .Add(copyTargetUserLogonId) .Add(addLogonType) .Add(addEventFields) - .Add(addEventOutcome) .Build(); // Handles both 4624 @@ -1709,7 +1689,6 @@ var security = (function () { .Add(addLogonType) .Add(renameCommonAuthFields) .Add(addEventFields) - .Add(addEventOutcome) .Add(function(evt) { var user = evt.Get("winlog.event_data.SubjectUserName"); if (user) { @@ -1727,7 +1706,6 @@ var security = (function () { .Add(copySubjectUserLogonId) .Add(renameCommonAuthFields) .Add(addEventFields) - .Add(addEventOutcome) .Add(function(evt) { var user = evt.Get("winlog.event_data.SubjectUserName"); if (user) { @@ -1748,7 +1726,6 @@ var security = (function () { .Add(addFailureSubStatus) .Add(renameCommonAuthFields) .Add(addEventFields) - .Add(addEventOutcome) .Build(); var event4672 = new processor.Chain() @@ -1762,7 +1739,6 @@ var security = (function () { evt.Put("winlog.event_data.PrivilegeList", privs.split(/\s+/)); }) .Add(addEventFields) - .Add(addEventOutcome) .Build(); var event4688 = new processor.Chain() @@ -1770,7 +1746,6 @@ var security = (function () { .Add(copySubjectUserLogonId) .Add(renameNewProcessFields) .Add(addEventFields) - .Add(addEventOutcome) .Add(function(evt) { var user = evt.Get("winlog.event_data.TargetUserName"); var res = /^-$/.test(user); @@ -1785,7 +1760,6 @@ var security = (function () { .Add(copySubjectUserLogonId) .Add(renameCommonAuthFields) .Add(addEventFields) - .Add(addEventOutcome) .Build(); var event4697 = new processor.Chain() @@ -1794,7 +1768,6 @@ var security = (function () { .Add(renameCommonAuthFields) .Add(addServiceFields) .Add(addEventFields) - .Add(addEventOutcome) .Add(function(evt) { evt.AppendTo("event.type", "change"); }) @@ -1806,7 +1779,6 @@ var security = (function () { .Add(renameCommonAuthFields) .Add(addUACDescription) .Add(addEventFields) - .Add(addEventOutcome) .Add(function(evt) { var user = evt.Get("winlog.event_data.TargetUserName"); evt.AppendTo('related.user', user); @@ -1818,7 +1790,6 @@ var security = (function () { .Add(copySubjectUser) .Add(copySubjectUserLogonId) .Add(addEventFields) - .Add(addEventOutcome) .Add(function(evt) { var userNew = evt.Get("winlog.event_data.NewTargetUserName"); evt.AppendTo('related.user', userNew); @@ -1834,7 +1805,6 @@ var security = (function () { .Add(copyTargetUserToGroup) .Add(renameCommonAuthFields) .Add(addEventFields) - .Add(addEventOutcome) .Add(function(evt) { evt.AppendTo("event.type", "group"); var member = evt.Get("winlog.event_data.MemberName"); @@ -1851,7 +1821,6 @@ var security = (function () { .Add(copySubjectUserLogonIdFromUserData) .Add(renameCommonAuthFields) .Add(addEventFields) - .Add(addEventOutcome) .Add(function(evt) { evt.AppendTo("event.type", "change"); }) @@ -1863,7 +1832,6 @@ var security = (function () { .Add(renameCommonAuthFields) .Add(addAuditInfo) .Add(addEventFields) - .Add(addEventOutcome) .Add(function(evt) { evt.AppendTo("event.type", "change"); }) @@ -1872,7 +1840,6 @@ var security = (function () { var auditLogMgmt = new processor.Chain() .Add(renameCommonAuthFields) .Add(addEventFields) - .Add(addEventOutcome) .Build(); var computerMgmtEvts = new processor.Chain() @@ -1882,7 +1849,6 @@ var security = (function () { .Add(renameCommonAuthFields) .Add(addUACDescription) .Add(addEventFields) - .Add(addEventOutcome) .Add(function(evt) { var privs = evt.Get("winlog.event_data.PrivilegeList"); if (!privs) { @@ -1896,14 +1862,12 @@ var security = (function () { var sessionEvts = new processor.Chain() .Add(addSessionData) .Add(addEventFields) - .Add(addEventOutcome) .Build(); var event4964 = new processor.Chain() .Add(copyTargetUser) .Add(copyTargetUserLogonId) .Add(addEventFields) - .Add(addEventOutcome) .Add(function(evt) { evt.AppendTo("event.type", "group"); }) @@ -1916,7 +1880,6 @@ var security = (function () { .Add(addTicketEncryptionType) .Add(addTicketStatus) .Add(addEventFields) - .Add(addEventOutcome) .Add(function(evt) { var ip = evt.Get("source.ip"); if (/::ffff:/.test(ip)) { @@ -1929,14 +1892,12 @@ var security = (function () { .Add(copyTargetUser) .Add(addFailureStatus) .Add(addEventFields) - .Add(addEventOutcome) .Build(); var scheduledTask = new processor.Chain() .Add(copySubjectUser) .Add(copySubjectUserLogonId) .Add(addEventFields) - .Add(addEventOutcome) .Add(function(evt) { evt.AppendTo("event.type", "admin"); }) @@ -1947,7 +1908,6 @@ var security = (function () { .Add(copySubjectUserLogonId) .Add(renameCommonAuthFields) .Add(addEventFields) - .Add(addEventOutcome) .Add(function(evt) { var privs = evt.Get("winlog.event_data.PrivilegeList"); if (!privs) {