Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Winlogbeat] Add subdomain value for sysmon module #22999

Merged
merged 4 commits into from
Dec 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
- Add `event.outcome` to events based on the audit success and audit failure keywords. {pull}20564[20564]
- Add file.pe and process.pe fields to ProcessCreate & LoadImage events in Sysmon module. {issue}17335[17335] {pull}22217[22217]
- Add additional event categorization for security and sysmon modules. {pull}22988[22988]
- Add dns.question.subdomain fields for sysmon DNS events. {pull}22999[22999]

*Elastic Log Driver*

Expand Down
11 changes: 6 additions & 5 deletions libbeat/processors/registered_domain/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@
package registered_domain

type config struct {
Field string `config:"field" validate:"required"`
TargetField string `config:"target_field" validate:"required"`
IgnoreMissing bool `config:"ignore_missing"`
IgnoreFailure bool `config:"ignore_failure"`
ID string `config:"id"`
Field string `config:"field" validate:"required"`
TargetField string `config:"target_field" validate:"required"`
TargetSubdomainField string `config:"target_subdomain_field"`
IgnoreMissing bool `config:"ignore_missing"`
IgnoreFailure bool `config:"ignore_failure"`
ID string `config:"id"`
}

func defaultConfig() config {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ The `registered_domain` processor reads a field containing a hostname and then
writes the "registered domain" contained in the hostname to the target field.
For example, given `www.google.co.uk` the processor would output `google.co.uk`.
In other words the "registered domain" is the effective top-level domain
(`co.uk`) plus one level (`google`).
(`co.uk`) plus one level (`google`). Optionally, it can store the rest of the
domain, the `subdomain` into another target field.

This processor uses the Mozilla Public Suffix list to determine the value.
andrewstucki marked this conversation as resolved.
Show resolved Hide resolved

Expand All @@ -19,6 +20,7 @@ processors:
- registered_domain:
field: dns.question.name
target_field: dns.question.registered_domain
target_subdomain_field: dns.question.sudomain
ignore_missing: true
ignore_failure: true
----
Expand All @@ -28,10 +30,11 @@ The `registered_domain` processor has the following configuration settings:
.Registered Domain options
[options="header"]
|======
| Name | Required | Default | Description |
| `field` | yes | | Source field containing a fully qualified domain name (FQDN). |
| `target_field` | yes | | Target field for the registered domain value. |
| `ignore_missing` | no | false | Ignore errors when the source field is missing. |
| `ignore_failure` | no | false | Ignore all errors produced by the processor. |
| `id` | no | | An identifier for this processor instance. Useful for debugging. |
| Name | Required | Default | Description |
| `field` | yes | | Source field containing a fully qualified domain name (FQDN). |
| `target_field` | yes | | Target field for the registered domain value. |
| `target_subdomain_field` | no | | Target subdomain field for the subdomain value. |
| `ignore_missing` | no | false | Ignore errors when the source field is missing. |
| `ignore_failure` | no | false | Ignore all errors produced by the processor. |
| `id` | no | | An identifier for this processor instance. Useful for debugging. |
|======
14 changes: 14 additions & 0 deletions libbeat/processors/registered_domain/registered_domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package registered_domain

import (
"encoding/json"
"strings"

"github.com/pkg/errors"
"golang.org/x/net/publicsuffix"
Expand Down Expand Up @@ -105,5 +106,18 @@ func (p *processor) Run(event *beat.Event) (*beat.Event, error) {
return event, errors.Wrapf(err, "failed to write registered domain to target field [%v]", p.TargetField)
}

if p.TargetSubdomainField != "" {
subdomain := strings.TrimSuffix(strings.TrimSuffix(domain, rd), ".")
if subdomain != "" {
_, err = event.PutValue(p.TargetSubdomainField, subdomain)
if err != nil {
if p.IgnoreFailure {
return event, nil
}
return event, errors.Wrapf(err, "failed to write subdomain to target field [%v]", p.TargetSubdomainField)
}
}
}

return event, nil
}
26 changes: 17 additions & 9 deletions libbeat/processors/registered_domain/registered_domain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,25 @@ func TestProcessorRun(t *testing.T) {
Error bool
Domain string
RegisteredDomain string
Subdomain string
}{
{false, "www.google.com", "google.com"},
{false, "www.google.co.uk", "google.co.uk"},
{false, "google.com", "google.com"},
{false, "www.ak.local", "ak.local"},
{false, "www.navy.mil", "navy.mil"},
{false, "www.google.com", "google.com", "www"},
{false, "www.google.co.uk", "google.co.uk", "www"},
{false, "www.mail.google.co.uk", "google.co.uk", "www.mail"},
{false, "google.com", "google.com", ""},
{false, "www.ak.local", "ak.local", "www"},
{false, "www.navy.mil", "navy.mil", "www"},

{true, "com", ""},
{true, ".", "."},
{true, "", ""},
{true, "localhost", ""},
{true, "com", "", ""},
{true, ".", ".", ""},
{true, "", "", ""},
{true, "localhost", "", ""},
}

c := defaultConfig()
c.Field = "domain"
c.TargetField = "registered_domain"
c.TargetSubdomainField = "subdomain"
p, err := newRegisteredDomain(c)
if err != nil {
t.Fatal(err)
Expand All @@ -71,5 +74,10 @@ func TestProcessorRun(t *testing.T) {

rd, _ := evt.GetValue("registered_domain")
assert.Equal(t, tc.RegisteredDomain, rd)

if tc.Subdomain != "" {
subdomain, _ := evt.GetValue("subdomain")
assert.Equal(t, tc.Subdomain, subdomain)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1563,6 +1563,7 @@ var sysmon = (function () {
ignore_missing: true,
field: "dns.question.name",
target_field: "dns.question.registered_domain",
target_subdomain_field: "dns.question.subdomain",
})
.Add(setRuleName)
.Add(translateDnsQueryStatus)
Expand Down
Loading