From 6659f48eda21ac17721986a38b2c9c484db00ca1 Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Tue, 11 Aug 2020 15:53:07 -0400 Subject: [PATCH] Set event.outcome based on raw keyword value 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 --- 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 fde6fe7abd0..c7932e0f5ca 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -326,6 +326,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d - Fix invalid IP addresses in DNS query results from Sysmon data. {issue}18432[18432] {pull}18436[18436] - Fields from Winlogbeat modules were not being included in index templates and patterns. {pull}18983[18983] +- Fix `event.outcome` in the security module for non-English languages. {issue}20079[20079] {pull}20564[20564] *Functionbeat* @@ -655,6 +656,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d - 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 new winlogbeat security dashboard {pull}18775[18775] +- 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) {