Skip to content

Commit

Permalink
Sysmon and Security "modules" for Winlogbeat (elastic#11651)
Browse files Browse the repository at this point in the history
Add pipelines for the Security and Sysmon event logs

The Security processor handles just three events to start with - 4624, 4625, and 4648.
These are event.category=authentication events.

The Sysmon processor handles all event IDs found in the sysmon manifest (sysmon -s).
It moves the event_data fields that are in ECS and does some type conversions.
  • Loading branch information
andrewkroh authored and ph committed May 21, 2019
1 parent 47320c5 commit b0849cf
Show file tree
Hide file tree
Showing 17 changed files with 3,917 additions and 1 deletion.
2 changes: 1 addition & 1 deletion winlogbeat/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
winlogbeat
/winlogbeat

# Folders
_obj
Expand Down
1 change: 1 addition & 0 deletions winlogbeat/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (

// Import the script processor and supporting modules.
_ "github.com/elastic/beats/libbeat/processors/script"
_ "github.com/elastic/beats/winlogbeat/processors/script/javascript/module/winlogbeat"
)

// Name of this beat
Expand Down
21 changes: 21 additions & 0 deletions winlogbeat/processors/script/javascript/module/winlogbeat/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

// Package winlogbeat registers the winlogbeat module with the javascript script
// processor. The module has utilities specific to Winlogbeat like parsing
// Windows command lines.
package winlogbeat
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

// +build windows

package winlogbeat

import (
"syscall"
"unsafe"

"github.com/dop251/goja"
"github.com/dop251/goja_nodejs/require"
)

// SplitCommandLine splits a string into a list of space separated arguments.
// See Window's CommandLineToArgvW for more details.
func SplitCommandLine(cmd string) []string {
args, err := commandLineToArgvW(cmd)
if err != nil {
panic(err)
}

return args
}

func commandLineToArgvW(in string) ([]string, error) {
ptr, err := syscall.UTF16PtrFromString(in)
if err != nil {
return nil, err
}

var numArgs int32
argsWide, err := syscall.CommandLineToArgv(ptr, &numArgs)
if err != nil {
return nil, err
}

// Free memory allocated for CommandLineToArgvW arguments.
defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(argsWide)))

args := make([]string, numArgs)
for idx := range args {
args[idx] = syscall.UTF16ToString(argsWide[idx][:])
}
return args, nil
}

// Require registers the winlogbeat module that has utilities specific to
// Winlogbeat like parsing Windows command lines. It can be accessed using:
//
// // javascript
// var winlogbeat = require('winlogbeat');
//
func Require(vm *goja.Runtime, module *goja.Object) {
o := module.Get("exports").(*goja.Object)

o.Set("splitCommandLine", SplitCommandLine)
}

// Enable adds path to the given runtime.
func Enable(runtime *goja.Runtime) {
runtime.Set("winlogbeat", require.Require(runtime, "winlogbeat"))
}

func init() {
require.RegisterNativeModule("winlogbeat", Require)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

// +build windows

package winlogbeat

import (
"testing"

"github.com/stretchr/testify/assert"
)

const quotedCommandLine = `"C:\Program Files (x86)\Steam\bin\cef\cef.win7x64\steamwebhelper.exe" "-lang=en_US" "-cachedir=C:\Users\jimmy\AppData\Local\Steam\htmlcache" "-steampid=796" "-buildid=1546909276" "-steamid=0" "-steamuniverse=Dev" "-clientui=C:\Program Files (x86)\Steam\clientui" --disable-spell-checking --disable-out-of-process-pac --enable-blink-features=ResizeObserver,Worklet,AudioWorklet --disable-features=TouchpadAndWheelScrollLatching,AsyncWheelEvents --enable-media-stream --disable-smooth-scrolling --num-raster-threads=4 --enable-direct-write "--log-file=C:\Program Files (x86)\Steam\logs\cef_log.txt"`

func TestSplitCommandLine(t *testing.T) {
args := SplitCommandLine(quotedCommandLine)

for _, a := range args {
t.Log(a)
}

expected := []string{
`C:\Program Files (x86)\Steam\bin\cef\cef.win7x64\steamwebhelper.exe`,
`-lang=en_US`,
`-cachedir=C:\Users\jimmy\AppData\Local\Steam\htmlcache`,
`-steampid=796`,
`-buildid=1546909276`,
`-steamid=0`,
`-steamuniverse=Dev`,
`-clientui=C:\Program Files (x86)\Steam\clientui`,
`--disable-spell-checking`,
`--disable-out-of-process-pac`,
`--enable-blink-features=ResizeObserver,Worklet,AudioWorklet`,
`--disable-features=TouchpadAndWheelScrollLatching,AsyncWheelEvents`,
`--enable-media-stream`,
`--disable-smooth-scrolling`,
`--num-raster-threads=4`,
`--enable-direct-write`,
`--log-file=C:\Program Files (x86)\Steam\logs\cef_log.txt`,
}
assert.Equal(t, expected, args)
}
13 changes: 13 additions & 0 deletions x-pack/winlogbeat/_meta/beat.yml.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,17 @@ winlogbeat.event_logs:
- name: System

- name: Security
processors:
- script:
lang: javascript
id: security
file: ${path.home}/module/security/config/winlogbeat-security.js

- name: Microsoft-Windows-Sysmon/Operational
processors:
- script:
lang: javascript
id: sysmon
file: ${path.home}/module/sysmon/config/winlogbeat-sysmon.js

{{if not .Reference}}{{ template "elasticsearch_settings" . }}{{end}}
86 changes: 86 additions & 0 deletions x-pack/winlogbeat/module/security/config/winlogbeat-security.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

var security = (function () {
var path = require("path");
var processor = require("processor");
var winlogbeat = require("winlogbeat");

var addAuthSuccess = new processor.AddFields({
fields: {
"event.category": "authentication",
"event.type": "authentication_success",
},
target: "",
});

var addAuthFailed = new processor.AddFields({
fields: {
"event.category": "authentication",
"event.type": "authentication_failed",
},
target: "",
});

var convertAuthentication = new processor.Convert({
fields: [
{from: "winlog.event_data.TargetUserSid", to: "user.id"},
{from: "winlog.event_data.TargetUserName", to: "user.name"},
{from: "winlog.event_data.TargetDomainName", to: "user.domain"},
{from: "winlog.event_data.ProcessId", to: "process.pid", type: "long"},
{from: "winlog.event_data.ProcessName", to: "process.executable"},
{from: "winlog.event_data.IpAddress", to: "source.ip", type: "ip"},
{from: "winlog.event_data.IpPort", to: "source.port", type: "long"},
{from: "winlog.event_data.WorkstationName", to: "source.domain"},
],
mode: "rename",
ignore_missing: true,
fail_on_error: false,
});

var setProcessNameUsingExe = function(evt) {
var name = evt.Get("process.name");
if (name) {
return;
}
var exe = evt.Get("process.executable");
evt.Put("process.name", path.basename(exe));
};

var logonSuccess = new processor.Chain()
.Add(addAuthSuccess)
.Add(convertAuthentication)
.Add(setProcessNameUsingExe)
.Build();

var logonFailed = new processor.Chain()
.Add(addAuthFailed)
.Add(convertAuthentication)
.Add(setProcessNameUsingExe)
.Build();

return {
// 4624 - An account was successfully logged on.
4624: logonSuccess.Run,

// 4625 - An account failed to log on.
4625: logonFailed.Run,

// 4648 - A logon was attempted using explicit credentials.
4648: logonSuccess.Run,

process: function(evt) {
var event_id = evt.Get("winlog.event_id");
var processor = this[event_id];
if (processor === undefined) {
return;
}
processor(evt);
},
};
})();

function process(evt) {
return security.process(evt);
}
15 changes: 15 additions & 0 deletions x-pack/winlogbeat/module/security/test/security_windows_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package test

import (
"testing"

"github.com/elastic/beats/x-pack/winlogbeat/module"
)

func TestSecurity(t *testing.T) {
module.TestPipeline(t, "testdata/*.evtx", "../config/winlogbeat-security.js")
}
Binary file not shown.
Loading

0 comments on commit b0849cf

Please sign in to comment.